blob: c61e61240b3be72f6fe029b78a6396c79ca6793e [file] [log] [blame]
Arnaldo Carvalho de Meloa598bb52015-08-28 12:02:37 -03001/*
2 * builtin-trace.c
3 *
4 * Builtin 'trace' command:
5 *
6 * Display a continuously updated trace of any workload, CPU, specific PID,
7 * system wide, etc. Default format is loosely strace like, but any other
8 * event may be specified using --event.
9 *
10 * Copyright (C) 2012, 2013, 2014, 2015 Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
11 *
12 * Initially based on the 'trace' prototype by Thomas Gleixner:
13 *
14 * http://lwn.net/Articles/415728/ ("Announcing a new utility: 'trace'")
15 *
16 * Released under the GPL v2. (and only v2, not any later version)
17 */
18
Robert Richter4e319022013-06-11 17:29:18 +020019#include <traceevent/event-parse.h>
Jiri Olsa988bdb32015-09-02 09:56:35 +020020#include <api/fs/tracing_path.h>
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -030021#include "builtin.h"
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -030022#include "util/color.h"
Arnaldo Carvalho de Melo7c304ee02013-08-22 16:49:54 -030023#include "util/debug.h"
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -030024#include "util/evlist.h"
Josh Poimboeuf4b6ab942015-12-15 09:39:39 -060025#include <subcmd/exec-cmd.h>
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -030026#include "util/machine.h"
David Ahern6810fc92013-08-28 22:29:52 -060027#include "util/session.h"
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -030028#include "util/thread.h"
Josh Poimboeuf4b6ab942015-12-15 09:39:39 -060029#include <subcmd/parse-options.h>
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -030030#include "util/strlist.h"
David Ahernbdc89662013-08-28 22:29:53 -060031#include "util/intlist.h"
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -030032#include "util/thread_map.h"
David Ahernbf2575c2013-10-08 21:26:53 -060033#include "util/stat.h"
Jiri Olsa97978b32013-12-03 14:09:24 +010034#include "trace-event.h"
David Ahern9aca7f12013-12-04 19:41:39 -070035#include "util/parse-events.h"
Wang Nanba504232016-02-26 09:31:54 +000036#include "util/bpf-loader.h"
Milian Wolff566a0882016-04-08 13:34:15 +020037#include "callchain.h"
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -030038#include "syscalltbl.h"
Arnaldo Carvalho de Melo96c14452016-05-04 12:47:16 -030039#include "rb_resort.h"
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -030040
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -030041#include <libaudit.h> /* FIXME: Still needed for audit_errno_to_name */
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -030042#include <stdlib.h>
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -030043#include <linux/futex.h>
Jiri Olsa8dd2a132015-09-07 10:38:06 +020044#include <linux/err.h>
Arnaldo Carvalho de Melo997bba82016-03-30 19:43:32 -030045#include <linux/seccomp.h>
46#include <linux/filter.h>
47#include <linux/audit.h>
48#include <sys/ptrace.h>
Arnaldo Carvalho de Melo39878d42016-03-30 20:02:15 -030049#include <linux/random.h>
Arnaldo Carvalho de Meloc6d4a492016-04-14 18:29:08 -030050#include <linux/stringify.h>
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -030051
Arnaldo Carvalho de Meloc188e7a2015-05-14 17:39:03 -030052#ifndef O_CLOEXEC
53# define O_CLOEXEC 02000000
54#endif
55
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -030056struct trace {
57 struct perf_tool tool;
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -030058 struct syscalltbl *sctbl;
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -030059 struct {
60 int max;
61 struct syscall *table;
62 struct {
63 struct perf_evsel *sys_enter,
64 *sys_exit;
65 } events;
66 } syscalls;
67 struct record_opts opts;
68 struct perf_evlist *evlist;
69 struct machine *host;
70 struct thread *current;
71 u64 base_time;
72 FILE *output;
73 unsigned long nr_events;
74 struct strlist *ev_qualifier;
75 struct {
76 size_t nr;
77 int *entries;
78 } ev_qualifier_ids;
79 struct intlist *tid_list;
80 struct intlist *pid_list;
81 struct {
82 size_t nr;
83 pid_t *entries;
84 } filter_pids;
85 double duration_filter;
86 double runtime_ms;
87 struct {
88 u64 vfs_getname,
89 proc_getname;
90 } stats;
Arnaldo Carvalho de Meloc6d4a492016-04-14 18:29:08 -030091 unsigned int max_stack;
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -030092 unsigned int min_stack;
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -030093 bool not_ev_qualifier;
94 bool live;
95 bool full_time;
96 bool sched;
97 bool multiple_threads;
98 bool summary;
99 bool summary_only;
100 bool show_comm;
101 bool show_tool_stats;
102 bool trace_syscalls;
Arnaldo Carvalho de Melo44621812016-04-11 15:49:11 -0300103 bool kernel_syscallchains;
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -0300104 bool force;
105 bool vfs_getname;
106 int trace_pgfaults;
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -0300107 int open_id;
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -0300108};
Arnaldo Carvalho de Meloa1c25522015-06-11 22:47:54 -0300109
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300110struct tp_field {
111 int offset;
112 union {
113 u64 (*integer)(struct tp_field *field, struct perf_sample *sample);
114 void *(*pointer)(struct tp_field *field, struct perf_sample *sample);
115 };
116};
117
118#define TP_UINT_FIELD(bits) \
119static u64 tp_field__u##bits(struct tp_field *field, struct perf_sample *sample) \
120{ \
David Ahern55d43bca2015-02-19 15:00:22 -0500121 u##bits value; \
122 memcpy(&value, sample->raw_data + field->offset, sizeof(value)); \
123 return value; \
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300124}
125
126TP_UINT_FIELD(8);
127TP_UINT_FIELD(16);
128TP_UINT_FIELD(32);
129TP_UINT_FIELD(64);
130
131#define TP_UINT_FIELD__SWAPPED(bits) \
132static u64 tp_field__swapped_u##bits(struct tp_field *field, struct perf_sample *sample) \
133{ \
David Ahern55d43bca2015-02-19 15:00:22 -0500134 u##bits value; \
135 memcpy(&value, sample->raw_data + field->offset, sizeof(value)); \
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300136 return bswap_##bits(value);\
137}
138
139TP_UINT_FIELD__SWAPPED(16);
140TP_UINT_FIELD__SWAPPED(32);
141TP_UINT_FIELD__SWAPPED(64);
142
143static int tp_field__init_uint(struct tp_field *field,
144 struct format_field *format_field,
145 bool needs_swap)
146{
147 field->offset = format_field->offset;
148
149 switch (format_field->size) {
150 case 1:
151 field->integer = tp_field__u8;
152 break;
153 case 2:
154 field->integer = needs_swap ? tp_field__swapped_u16 : tp_field__u16;
155 break;
156 case 4:
157 field->integer = needs_swap ? tp_field__swapped_u32 : tp_field__u32;
158 break;
159 case 8:
160 field->integer = needs_swap ? tp_field__swapped_u64 : tp_field__u64;
161 break;
162 default:
163 return -1;
164 }
165
166 return 0;
167}
168
169static void *tp_field__ptr(struct tp_field *field, struct perf_sample *sample)
170{
171 return sample->raw_data + field->offset;
172}
173
174static int tp_field__init_ptr(struct tp_field *field, struct format_field *format_field)
175{
176 field->offset = format_field->offset;
177 field->pointer = tp_field__ptr;
178 return 0;
179}
180
181struct syscall_tp {
182 struct tp_field id;
183 union {
184 struct tp_field args, ret;
185 };
186};
187
188static int perf_evsel__init_tp_uint_field(struct perf_evsel *evsel,
189 struct tp_field *field,
190 const char *name)
191{
192 struct format_field *format_field = perf_evsel__field(evsel, name);
193
194 if (format_field == NULL)
195 return -1;
196
197 return tp_field__init_uint(field, format_field, evsel->needs_swap);
198}
199
200#define perf_evsel__init_sc_tp_uint_field(evsel, name) \
201 ({ struct syscall_tp *sc = evsel->priv;\
202 perf_evsel__init_tp_uint_field(evsel, &sc->name, #name); })
203
204static int perf_evsel__init_tp_ptr_field(struct perf_evsel *evsel,
205 struct tp_field *field,
206 const char *name)
207{
208 struct format_field *format_field = perf_evsel__field(evsel, name);
209
210 if (format_field == NULL)
211 return -1;
212
213 return tp_field__init_ptr(field, format_field);
214}
215
216#define perf_evsel__init_sc_tp_ptr_field(evsel, name) \
217 ({ struct syscall_tp *sc = evsel->priv;\
218 perf_evsel__init_tp_ptr_field(evsel, &sc->name, #name); })
219
220static void perf_evsel__delete_priv(struct perf_evsel *evsel)
221{
Arnaldo Carvalho de Melo04662522013-12-26 17:41:15 -0300222 zfree(&evsel->priv);
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300223 perf_evsel__delete(evsel);
224}
225
Namhyung Kim96695d42013-11-12 08:51:45 -0300226static int perf_evsel__init_syscall_tp(struct perf_evsel *evsel, void *handler)
227{
228 evsel->priv = malloc(sizeof(struct syscall_tp));
229 if (evsel->priv != NULL) {
230 if (perf_evsel__init_sc_tp_uint_field(evsel, id))
231 goto out_delete;
232
233 evsel->handler = handler;
234 return 0;
235 }
236
237 return -ENOMEM;
238
239out_delete:
Arnaldo Carvalho de Melo04662522013-12-26 17:41:15 -0300240 zfree(&evsel->priv);
Namhyung Kim96695d42013-11-12 08:51:45 -0300241 return -ENOENT;
242}
243
Arnaldo Carvalho de Meloef503832013-11-07 16:41:19 -0300244static struct perf_evsel *perf_evsel__syscall_newtp(const char *direction, void *handler)
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300245{
Arnaldo Carvalho de Meloef503832013-11-07 16:41:19 -0300246 struct perf_evsel *evsel = perf_evsel__newtp("raw_syscalls", direction);
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300247
David Ahern9aca7f12013-12-04 19:41:39 -0700248 /* older kernel (e.g., RHEL6) use syscalls:{enter,exit} */
Jiri Olsa8dd2a132015-09-07 10:38:06 +0200249 if (IS_ERR(evsel))
David Ahern9aca7f12013-12-04 19:41:39 -0700250 evsel = perf_evsel__newtp("syscalls", direction);
251
Jiri Olsa8dd2a132015-09-07 10:38:06 +0200252 if (IS_ERR(evsel))
253 return NULL;
254
255 if (perf_evsel__init_syscall_tp(evsel, handler))
256 goto out_delete;
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300257
258 return evsel;
259
260out_delete:
261 perf_evsel__delete_priv(evsel);
262 return NULL;
263}
264
265#define perf_evsel__sc_tp_uint(evsel, name, sample) \
266 ({ struct syscall_tp *fields = evsel->priv; \
267 fields->name.integer(&fields->name, sample); })
268
269#define perf_evsel__sc_tp_ptr(evsel, name, sample) \
270 ({ struct syscall_tp *fields = evsel->priv; \
271 fields->name.pointer(&fields->name, sample); })
272
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300273struct syscall_arg {
274 unsigned long val;
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300275 struct thread *thread;
276 struct trace *trace;
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300277 void *parm;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300278 u8 idx;
279 u8 mask;
280};
281
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300282struct strarray {
Arnaldo Carvalho de Melo03e3adc2013-10-08 16:00:21 -0300283 int offset;
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300284 int nr_entries;
285 const char **entries;
286};
287
288#define DEFINE_STRARRAY(array) struct strarray strarray__##array = { \
289 .nr_entries = ARRAY_SIZE(array), \
290 .entries = array, \
291}
292
Arnaldo Carvalho de Melo03e3adc2013-10-08 16:00:21 -0300293#define DEFINE_STRARRAY_OFFSET(array, off) struct strarray strarray__##array = { \
294 .offset = off, \
295 .nr_entries = ARRAY_SIZE(array), \
296 .entries = array, \
297}
298
Arnaldo Carvalho de Melo975b7c22013-10-08 17:17:43 -0300299static size_t __syscall_arg__scnprintf_strarray(char *bf, size_t size,
300 const char *intfmt,
301 struct syscall_arg *arg)
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300302{
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300303 struct strarray *sa = arg->parm;
Arnaldo Carvalho de Melo03e3adc2013-10-08 16:00:21 -0300304 int idx = arg->val - sa->offset;
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300305
306 if (idx < 0 || idx >= sa->nr_entries)
Arnaldo Carvalho de Melo975b7c22013-10-08 17:17:43 -0300307 return scnprintf(bf, size, intfmt, arg->val);
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300308
309 return scnprintf(bf, size, "%s", sa->entries[idx]);
310}
311
Arnaldo Carvalho de Melo975b7c22013-10-08 17:17:43 -0300312static size_t syscall_arg__scnprintf_strarray(char *bf, size_t size,
313 struct syscall_arg *arg)
314{
315 return __syscall_arg__scnprintf_strarray(bf, size, "%d", arg);
316}
317
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300318#define SCA_STRARRAY syscall_arg__scnprintf_strarray
319
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -0300320#if defined(__i386__) || defined(__x86_64__)
321/*
322 * FIXME: Make this available to all arches as soon as the ioctl beautifier
323 * gets rewritten to support all arches.
324 */
Arnaldo Carvalho de Melo78645cf2013-10-08 17:43:20 -0300325static size_t syscall_arg__scnprintf_strhexarray(char *bf, size_t size,
326 struct syscall_arg *arg)
327{
328 return __syscall_arg__scnprintf_strarray(bf, size, "%#x", arg);
329}
330
331#define SCA_STRHEXARRAY syscall_arg__scnprintf_strhexarray
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -0300332#endif /* defined(__i386__) || defined(__x86_64__) */
Arnaldo Carvalho de Melo78645cf2013-10-08 17:43:20 -0300333
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300334static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
335 struct syscall_arg *arg);
336
337#define SCA_FD syscall_arg__scnprintf_fd
338
339static size_t syscall_arg__scnprintf_fd_at(char *bf, size_t size,
340 struct syscall_arg *arg)
341{
342 int fd = arg->val;
343
344 if (fd == AT_FDCWD)
345 return scnprintf(bf, size, "CWD");
346
347 return syscall_arg__scnprintf_fd(bf, size, arg);
348}
349
350#define SCA_FDAT syscall_arg__scnprintf_fd_at
351
352static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
353 struct syscall_arg *arg);
354
355#define SCA_CLOSE_FD syscall_arg__scnprintf_close_fd
356
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -0300357static size_t syscall_arg__scnprintf_hex(char *bf, size_t size,
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300358 struct syscall_arg *arg)
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -0300359{
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300360 return scnprintf(bf, size, "%#lx", arg->val);
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -0300361}
362
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -0300363#define SCA_HEX syscall_arg__scnprintf_hex
364
Arnaldo Carvalho de Meloa1c25522015-06-11 22:47:54 -0300365static size_t syscall_arg__scnprintf_int(char *bf, size_t size,
366 struct syscall_arg *arg)
367{
368 return scnprintf(bf, size, "%d", arg->val);
369}
370
371#define SCA_INT syscall_arg__scnprintf_int
372
Arnaldo Carvalho de Melo5cea6ff2013-09-20 11:49:50 -0300373static size_t syscall_arg__scnprintf_flock(char *bf, size_t size,
374 struct syscall_arg *arg)
375{
376 int printed = 0, op = arg->val;
377
378 if (op == 0)
379 return scnprintf(bf, size, "NONE");
380#define P_CMD(cmd) \
381 if ((op & LOCK_##cmd) == LOCK_##cmd) { \
382 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #cmd); \
383 op &= ~LOCK_##cmd; \
384 }
385
386 P_CMD(SH);
387 P_CMD(EX);
388 P_CMD(NB);
389 P_CMD(UN);
390 P_CMD(MAND);
391 P_CMD(RW);
392 P_CMD(READ);
393 P_CMD(WRITE);
394#undef P_OP
395
396 if (op)
397 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", op);
398
399 return printed;
400}
401
402#define SCA_FLOCK syscall_arg__scnprintf_flock
403
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300404static size_t syscall_arg__scnprintf_futex_op(char *bf, size_t size, struct syscall_arg *arg)
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -0300405{
406 enum syscall_futex_args {
407 SCF_UADDR = (1 << 0),
408 SCF_OP = (1 << 1),
409 SCF_VAL = (1 << 2),
410 SCF_TIMEOUT = (1 << 3),
411 SCF_UADDR2 = (1 << 4),
412 SCF_VAL3 = (1 << 5),
413 };
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300414 int op = arg->val;
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -0300415 int cmd = op & FUTEX_CMD_MASK;
416 size_t printed = 0;
417
418 switch (cmd) {
419#define P_FUTEX_OP(n) case FUTEX_##n: printed = scnprintf(bf, size, #n);
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300420 P_FUTEX_OP(WAIT); arg->mask |= SCF_VAL3|SCF_UADDR2; break;
421 P_FUTEX_OP(WAKE); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
422 P_FUTEX_OP(FD); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
423 P_FUTEX_OP(REQUEUE); arg->mask |= SCF_VAL3|SCF_TIMEOUT; break;
424 P_FUTEX_OP(CMP_REQUEUE); arg->mask |= SCF_TIMEOUT; break;
425 P_FUTEX_OP(CMP_REQUEUE_PI); arg->mask |= SCF_TIMEOUT; break;
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -0300426 P_FUTEX_OP(WAKE_OP); break;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300427 P_FUTEX_OP(LOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
428 P_FUTEX_OP(UNLOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
429 P_FUTEX_OP(TRYLOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2; break;
430 P_FUTEX_OP(WAIT_BITSET); arg->mask |= SCF_UADDR2; break;
431 P_FUTEX_OP(WAKE_BITSET); arg->mask |= SCF_UADDR2; break;
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -0300432 P_FUTEX_OP(WAIT_REQUEUE_PI); break;
433 default: printed = scnprintf(bf, size, "%#x", cmd); break;
434 }
435
436 if (op & FUTEX_PRIVATE_FLAG)
437 printed += scnprintf(bf + printed, size - printed, "|PRIV");
438
439 if (op & FUTEX_CLOCK_REALTIME)
440 printed += scnprintf(bf + printed, size - printed, "|CLKRT");
441
442 return printed;
443}
444
Arnaldo Carvalho de Meloefe6b882013-09-03 16:15:12 -0300445#define SCA_FUTEX_OP syscall_arg__scnprintf_futex_op
446
Arnaldo Carvalho de Melo729a7842015-10-29 11:48:18 -0300447static const char *bpf_cmd[] = {
448 "MAP_CREATE", "MAP_LOOKUP_ELEM", "MAP_UPDATE_ELEM", "MAP_DELETE_ELEM",
449 "MAP_GET_NEXT_KEY", "PROG_LOAD",
450};
451static DEFINE_STRARRAY(bpf_cmd);
452
Arnaldo Carvalho de Melo03e3adc2013-10-08 16:00:21 -0300453static const char *epoll_ctl_ops[] = { "ADD", "DEL", "MOD", };
454static DEFINE_STRARRAY_OFFSET(epoll_ctl_ops, 1);
Arnaldo Carvalho de Meloeac032c2013-09-20 11:27:32 -0300455
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300456static const char *itimers[] = { "REAL", "VIRTUAL", "PROF", };
457static DEFINE_STRARRAY(itimers);
458
Arnaldo Carvalho de Melob62bee12015-08-11 11:05:36 -0300459static const char *keyctl_options[] = {
460 "GET_KEYRING_ID", "JOIN_SESSION_KEYRING", "UPDATE", "REVOKE", "CHOWN",
461 "SETPERM", "DESCRIBE", "CLEAR", "LINK", "UNLINK", "SEARCH", "READ",
462 "INSTANTIATE", "NEGATE", "SET_REQKEY_KEYRING", "SET_TIMEOUT",
463 "ASSUME_AUTHORITY", "GET_SECURITY", "SESSION_TO_PARENT", "REJECT",
464 "INSTANTIATE_IOV", "INVALIDATE", "GET_PERSISTENT",
465};
466static DEFINE_STRARRAY(keyctl_options);
467
Arnaldo Carvalho de Meloefe6b882013-09-03 16:15:12 -0300468static const char *whences[] = { "SET", "CUR", "END",
469#ifdef SEEK_DATA
470"DATA",
471#endif
472#ifdef SEEK_HOLE
473"HOLE",
474#endif
475};
476static DEFINE_STRARRAY(whences);
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -0300477
Arnaldo Carvalho de Melo80f587d2013-09-03 16:28:58 -0300478static const char *fcntl_cmds[] = {
479 "DUPFD", "GETFD", "SETFD", "GETFL", "SETFL", "GETLK", "SETLK",
480 "SETLKW", "SETOWN", "GETOWN", "SETSIG", "GETSIG", "F_GETLK64",
481 "F_SETLK64", "F_SETLKW64", "F_SETOWN_EX", "F_GETOWN_EX",
482 "F_GETOWNER_UIDS",
483};
484static DEFINE_STRARRAY(fcntl_cmds);
485
Arnaldo Carvalho de Meloc045bf02013-09-04 11:52:33 -0300486static const char *rlimit_resources[] = {
487 "CPU", "FSIZE", "DATA", "STACK", "CORE", "RSS", "NPROC", "NOFILE",
488 "MEMLOCK", "AS", "LOCKS", "SIGPENDING", "MSGQUEUE", "NICE", "RTPRIO",
489 "RTTIME",
490};
491static DEFINE_STRARRAY(rlimit_resources);
492
Arnaldo Carvalho de Meloeb5b1b12013-09-03 16:37:46 -0300493static const char *sighow[] = { "BLOCK", "UNBLOCK", "SETMASK", };
494static DEFINE_STRARRAY(sighow);
495
David Ahern4f8c1b72013-09-22 19:45:00 -0600496static const char *clockid[] = {
497 "REALTIME", "MONOTONIC", "PROCESS_CPUTIME_ID", "THREAD_CPUTIME_ID",
Arnaldo Carvalho de Melo28ebb872015-08-11 10:38:38 -0300498 "MONOTONIC_RAW", "REALTIME_COARSE", "MONOTONIC_COARSE", "BOOTTIME",
499 "REALTIME_ALARM", "BOOTTIME_ALARM", "SGI_CYCLE", "TAI"
David Ahern4f8c1b72013-09-22 19:45:00 -0600500};
501static DEFINE_STRARRAY(clockid);
502
Arnaldo Carvalho de Meloe10bce82013-09-04 10:27:41 -0300503static const char *socket_families[] = {
504 "UNSPEC", "LOCAL", "INET", "AX25", "IPX", "APPLETALK", "NETROM",
505 "BRIDGE", "ATMPVC", "X25", "INET6", "ROSE", "DECnet", "NETBEUI",
506 "SECURITY", "KEY", "NETLINK", "PACKET", "ASH", "ECONET", "ATMSVC",
507 "RDS", "SNA", "IRDA", "PPPOX", "WANPIPE", "LLC", "IB", "CAN", "TIPC",
508 "BLUETOOTH", "IUCV", "RXRPC", "ISDN", "PHONET", "IEEE802154", "CAIF",
509 "ALG", "NFC", "VSOCK",
510};
511static DEFINE_STRARRAY(socket_families);
512
Arnaldo Carvalho de Melo51108992013-09-04 11:42:27 -0300513static size_t syscall_arg__scnprintf_access_mode(char *bf, size_t size,
514 struct syscall_arg *arg)
515{
516 size_t printed = 0;
517 int mode = arg->val;
518
519 if (mode == F_OK) /* 0 */
520 return scnprintf(bf, size, "F");
521#define P_MODE(n) \
522 if (mode & n##_OK) { \
523 printed += scnprintf(bf + printed, size - printed, "%s", #n); \
524 mode &= ~n##_OK; \
525 }
526
527 P_MODE(R);
528 P_MODE(W);
529 P_MODE(X);
530#undef P_MODE
531
532 if (mode)
533 printed += scnprintf(bf + printed, size - printed, "|%#x", mode);
534
535 return printed;
536}
537
538#define SCA_ACCMODE syscall_arg__scnprintf_access_mode
539
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -0300540static size_t syscall_arg__scnprintf_filename(char *bf, size_t size,
541 struct syscall_arg *arg);
542
543#define SCA_FILENAME syscall_arg__scnprintf_filename
544
Arnaldo Carvalho de Melobe65a892013-09-02 16:22:31 -0300545static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300546 struct syscall_arg *arg)
Arnaldo Carvalho de Melobe65a892013-09-02 16:22:31 -0300547{
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300548 int printed = 0, flags = arg->val;
Arnaldo Carvalho de Melobe65a892013-09-02 16:22:31 -0300549
550 if (!(flags & O_CREAT))
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300551 arg->mask |= 1 << (arg->idx + 1); /* Mask the mode parm */
Arnaldo Carvalho de Melobe65a892013-09-02 16:22:31 -0300552
553 if (flags == 0)
554 return scnprintf(bf, size, "RDONLY");
555#define P_FLAG(n) \
556 if (flags & O_##n) { \
557 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
558 flags &= ~O_##n; \
559 }
560
561 P_FLAG(APPEND);
562 P_FLAG(ASYNC);
563 P_FLAG(CLOEXEC);
564 P_FLAG(CREAT);
565 P_FLAG(DIRECT);
566 P_FLAG(DIRECTORY);
567 P_FLAG(EXCL);
568 P_FLAG(LARGEFILE);
569 P_FLAG(NOATIME);
570 P_FLAG(NOCTTY);
571#ifdef O_NONBLOCK
572 P_FLAG(NONBLOCK);
573#elif O_NDELAY
574 P_FLAG(NDELAY);
575#endif
576#ifdef O_PATH
577 P_FLAG(PATH);
578#endif
579 P_FLAG(RDWR);
580#ifdef O_DSYNC
581 if ((flags & O_SYNC) == O_SYNC)
582 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", "SYNC");
583 else {
584 P_FLAG(DSYNC);
585 }
586#else
587 P_FLAG(SYNC);
588#endif
589 P_FLAG(TRUNC);
590 P_FLAG(WRONLY);
591#undef P_FLAG
592
593 if (flags)
594 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
595
596 return printed;
597}
598
599#define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags
600
Arnaldo Carvalho de Melo46cce192013-09-23 12:52:04 -0300601static size_t syscall_arg__scnprintf_pipe_flags(char *bf, size_t size,
602 struct syscall_arg *arg)
603{
604 int printed = 0, flags = arg->val;
605
606#define P_FLAG(n) \
607 if (flags & O_##n) { \
608 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
609 flags &= ~O_##n; \
610 }
611
612 P_FLAG(CLOEXEC);
613 P_FLAG(NONBLOCK);
614#undef P_FLAG
615
616 if (flags)
617 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
618
619 return printed;
620}
621
622#define SCA_PIPE_FLAGS syscall_arg__scnprintf_pipe_flags
623
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -0300624static size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscall_arg *arg)
625{
626 int sig = arg->val;
627
628 switch (sig) {
629#define P_SIGNUM(n) case SIG##n: return scnprintf(bf, size, #n)
630 P_SIGNUM(HUP);
631 P_SIGNUM(INT);
632 P_SIGNUM(QUIT);
633 P_SIGNUM(ILL);
634 P_SIGNUM(TRAP);
635 P_SIGNUM(ABRT);
636 P_SIGNUM(BUS);
637 P_SIGNUM(FPE);
638 P_SIGNUM(KILL);
639 P_SIGNUM(USR1);
640 P_SIGNUM(SEGV);
641 P_SIGNUM(USR2);
642 P_SIGNUM(PIPE);
643 P_SIGNUM(ALRM);
644 P_SIGNUM(TERM);
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -0300645 P_SIGNUM(CHLD);
646 P_SIGNUM(CONT);
647 P_SIGNUM(STOP);
648 P_SIGNUM(TSTP);
649 P_SIGNUM(TTIN);
650 P_SIGNUM(TTOU);
651 P_SIGNUM(URG);
652 P_SIGNUM(XCPU);
653 P_SIGNUM(XFSZ);
654 P_SIGNUM(VTALRM);
655 P_SIGNUM(PROF);
656 P_SIGNUM(WINCH);
657 P_SIGNUM(IO);
658 P_SIGNUM(PWR);
659 P_SIGNUM(SYS);
Ben Hutchings02c5bb42014-02-06 01:00:41 +0000660#ifdef SIGEMT
661 P_SIGNUM(EMT);
662#endif
663#ifdef SIGSTKFLT
664 P_SIGNUM(STKFLT);
665#endif
666#ifdef SIGSWI
667 P_SIGNUM(SWI);
668#endif
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -0300669 default: break;
670 }
671
672 return scnprintf(bf, size, "%#x", sig);
673}
674
675#define SCA_SIGNUM syscall_arg__scnprintf_signum
676
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -0300677#if defined(__i386__) || defined(__x86_64__)
678/*
679 * FIXME: Make this available to all arches.
680 */
Arnaldo Carvalho de Melo78645cf2013-10-08 17:43:20 -0300681#define TCGETS 0x5401
682
683static const char *tioctls[] = {
684 "TCGETS", "TCSETS", "TCSETSW", "TCSETSF", "TCGETA", "TCSETA", "TCSETAW",
685 "TCSETAF", "TCSBRK", "TCXONC", "TCFLSH", "TIOCEXCL", "TIOCNXCL",
686 "TIOCSCTTY", "TIOCGPGRP", "TIOCSPGRP", "TIOCOUTQ", "TIOCSTI",
687 "TIOCGWINSZ", "TIOCSWINSZ", "TIOCMGET", "TIOCMBIS", "TIOCMBIC",
688 "TIOCMSET", "TIOCGSOFTCAR", "TIOCSSOFTCAR", "FIONREAD", "TIOCLINUX",
689 "TIOCCONS", "TIOCGSERIAL", "TIOCSSERIAL", "TIOCPKT", "FIONBIO",
690 "TIOCNOTTY", "TIOCSETD", "TIOCGETD", "TCSBRKP", [0x27] = "TIOCSBRK",
691 "TIOCCBRK", "TIOCGSID", "TCGETS2", "TCSETS2", "TCSETSW2", "TCSETSF2",
692 "TIOCGRS485", "TIOCSRS485", "TIOCGPTN", "TIOCSPTLCK",
693 "TIOCGDEV||TCGETX", "TCSETX", "TCSETXF", "TCSETXW", "TIOCSIG",
694 "TIOCVHANGUP", "TIOCGPKT", "TIOCGPTLCK", "TIOCGEXCL",
695 [0x50] = "FIONCLEX", "FIOCLEX", "FIOASYNC", "TIOCSERCONFIG",
696 "TIOCSERGWILD", "TIOCSERSWILD", "TIOCGLCKTRMIOS", "TIOCSLCKTRMIOS",
697 "TIOCSERGSTRUCT", "TIOCSERGETLSR", "TIOCSERGETMULTI", "TIOCSERSETMULTI",
698 "TIOCMIWAIT", "TIOCGICOUNT", [0x60] = "FIOQSIZE",
699};
700
701static DEFINE_STRARRAY_OFFSET(tioctls, 0x5401);
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -0300702#endif /* defined(__i386__) || defined(__x86_64__) */
Arnaldo Carvalho de Melo78645cf2013-10-08 17:43:20 -0300703
Arnaldo Carvalho de Melo6fb35b92016-04-13 11:50:23 -0300704#ifndef SECCOMP_SET_MODE_STRICT
705#define SECCOMP_SET_MODE_STRICT 0
706#endif
707#ifndef SECCOMP_SET_MODE_FILTER
708#define SECCOMP_SET_MODE_FILTER 1
709#endif
710
Arnaldo Carvalho de Melo997bba82016-03-30 19:43:32 -0300711static size_t syscall_arg__scnprintf_seccomp_op(char *bf, size_t size, struct syscall_arg *arg)
712{
713 int op = arg->val;
714 size_t printed = 0;
715
716 switch (op) {
717#define P_SECCOMP_SET_MODE_OP(n) case SECCOMP_SET_MODE_##n: printed = scnprintf(bf, size, #n); break
718 P_SECCOMP_SET_MODE_OP(STRICT);
719 P_SECCOMP_SET_MODE_OP(FILTER);
720#undef P_SECCOMP_SET_MODE_OP
721 default: printed = scnprintf(bf, size, "%#x", op); break;
722 }
723
724 return printed;
725}
726
727#define SCA_SECCOMP_OP syscall_arg__scnprintf_seccomp_op
728
Arnaldo Carvalho de Melo6fb35b92016-04-13 11:50:23 -0300729#ifndef SECCOMP_FILTER_FLAG_TSYNC
730#define SECCOMP_FILTER_FLAG_TSYNC 1
731#endif
732
Arnaldo Carvalho de Melo997bba82016-03-30 19:43:32 -0300733static size_t syscall_arg__scnprintf_seccomp_flags(char *bf, size_t size,
734 struct syscall_arg *arg)
735{
736 int printed = 0, flags = arg->val;
737
738#define P_FLAG(n) \
739 if (flags & SECCOMP_FILTER_FLAG_##n) { \
740 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
741 flags &= ~SECCOMP_FILTER_FLAG_##n; \
742 }
743
744 P_FLAG(TSYNC);
745#undef P_FLAG
746
747 if (flags)
748 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
749
750 return printed;
751}
752
753#define SCA_SECCOMP_FLAGS syscall_arg__scnprintf_seccomp_flags
754
Arnaldo Carvalho de Meloa355a612016-04-13 11:55:18 -0300755#ifndef GRND_NONBLOCK
756#define GRND_NONBLOCK 0x0001
757#endif
758#ifndef GRND_RANDOM
759#define GRND_RANDOM 0x0002
760#endif
761
Arnaldo Carvalho de Melo39878d42016-03-30 20:02:15 -0300762static size_t syscall_arg__scnprintf_getrandom_flags(char *bf, size_t size,
763 struct syscall_arg *arg)
764{
765 int printed = 0, flags = arg->val;
766
767#define P_FLAG(n) \
768 if (flags & GRND_##n) { \
769 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
770 flags &= ~GRND_##n; \
771 }
772
773 P_FLAG(RANDOM);
774 P_FLAG(NONBLOCK);
775#undef P_FLAG
776
777 if (flags)
778 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
779
780 return printed;
781}
782
783#define SCA_GETRANDOM_FLAGS syscall_arg__scnprintf_getrandom_flags
784
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300785#define STRARRAY(arg, name, array) \
786 .arg_scnprintf = { [arg] = SCA_STRARRAY, }, \
787 .arg_parm = { [arg] = &strarray__##array, }
788
Arnaldo Carvalho de Meloea8dc3c2016-04-13 12:10:19 -0300789#include "trace/beauty/eventfd.c"
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -0300790#include "trace/beauty/pid.c"
Arnaldo Carvalho de Melodf4cb162016-04-13 12:05:44 -0300791#include "trace/beauty/mmap.c"
Arnaldo Carvalho de Meloba2f22c2016-04-07 12:05:51 -0300792#include "trace/beauty/mode_t.c"
Arnaldo Carvalho de Meloa30e6252016-04-27 19:01:52 -0300793#include "trace/beauty/msg_flags.c"
Arnaldo Carvalho de Melo62de3442016-04-26 11:03:03 -0300794#include "trace/beauty/perf_event_open.c"
Arnaldo Carvalho de Meloa3bca912016-04-06 12:51:33 -0300795#include "trace/beauty/sched_policy.c"
Arnaldo Carvalho de Melobbf86c42016-04-14 13:53:10 -0300796#include "trace/beauty/socket_type.c"
Arnaldo Carvalho de Melo7206b902016-04-06 14:11:36 -0300797#include "trace/beauty/waitid_options.c"
Arnaldo Carvalho de Meloa3bca912016-04-06 12:51:33 -0300798
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300799static struct syscall_fmt {
800 const char *name;
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -0300801 const char *alias;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300802 size_t (*arg_scnprintf[6])(char *bf, size_t size, struct syscall_arg *arg);
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300803 void *arg_parm[6];
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300804 bool errmsg;
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -0300805 bool errpid;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300806 bool timeout;
Arnaldo Carvalho de Melo04b34722013-08-26 11:36:30 -0300807 bool hexret;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300808} syscall_fmts[] = {
Arnaldo Carvalho de Melo51108992013-09-04 11:42:27 -0300809 { .name = "access", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300810 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */
811 [1] = SCA_ACCMODE, /* mode */ }, },
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -0300812 { .name = "arch_prctl", .errmsg = true, .alias = "prctl", },
Arnaldo Carvalho de Melo729a7842015-10-29 11:48:18 -0300813 { .name = "bpf", .errmsg = true, STRARRAY(0, cmd, bpf_cmd), },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -0300814 { .name = "brk", .hexret = true,
815 .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300816 { .name = "chdir", .errmsg = true,
817 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
818 { .name = "chmod", .errmsg = true,
819 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
820 { .name = "chroot", .errmsg = true,
821 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
David Ahern4f8c1b72013-09-22 19:45:00 -0600822 { .name = "clock_gettime", .errmsg = true, STRARRAY(0, clk_id, clockid), },
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -0300823 { .name = "clone", .errpid = true, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300824 { .name = "close", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300825 .arg_scnprintf = { [0] = SCA_CLOSE_FD, /* fd */ }, },
Arnaldo Carvalho de Meloa14bb862013-07-30 16:38:23 -0300826 { .name = "connect", .errmsg = true, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300827 { .name = "creat", .errmsg = true,
828 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300829 { .name = "dup", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300830 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300831 { .name = "dup2", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300832 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300833 { .name = "dup3", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300834 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300835 { .name = "epoll_ctl", .errmsg = true, STRARRAY(1, op, epoll_ctl_ops), },
Arnaldo Carvalho de Melo49af9e92013-09-12 12:18:56 -0300836 { .name = "eventfd2", .errmsg = true,
837 .arg_scnprintf = { [1] = SCA_EFD_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300838 { .name = "faccessat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300839 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
840 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300841 { .name = "fadvise64", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300842 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300843 { .name = "fallocate", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300844 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300845 { .name = "fchdir", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300846 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300847 { .name = "fchmod", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300848 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300849 { .name = "fchmodat", .errmsg = true,
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -0300850 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */
851 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300852 { .name = "fchown", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300853 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300854 { .name = "fchownat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300855 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */
856 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300857 { .name = "fcntl", .errmsg = true,
858 .arg_scnprintf = { [0] = SCA_FD, /* fd */
859 [1] = SCA_STRARRAY, /* cmd */ },
860 .arg_parm = { [1] = &strarray__fcntl_cmds, /* cmd */ }, },
861 { .name = "fdatasync", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300862 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo5cea6ff2013-09-20 11:49:50 -0300863 { .name = "flock", .errmsg = true,
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300864 .arg_scnprintf = { [0] = SCA_FD, /* fd */
865 [1] = SCA_FLOCK, /* cmd */ }, },
866 { .name = "fsetxattr", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300867 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300868 { .name = "fstat", .errmsg = true, .alias = "newfstat",
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300869 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300870 { .name = "fstatat", .errmsg = true, .alias = "newfstatat",
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300871 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
872 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300873 { .name = "fstatfs", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300874 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300875 { .name = "fsync", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300876 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300877 { .name = "ftruncate", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300878 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -0300879 { .name = "futex", .errmsg = true,
880 .arg_scnprintf = { [1] = SCA_FUTEX_OP, /* op */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300881 { .name = "futimesat", .errmsg = true,
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -0300882 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */
883 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300884 { .name = "getdents", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300885 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300886 { .name = "getdents64", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300887 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300888 { .name = "getitimer", .errmsg = true, STRARRAY(0, which, itimers), },
Arnaldo Carvalho de Meloc65f1072016-04-06 14:55:18 -0300889 { .name = "getpid", .errpid = true, },
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -0300890 { .name = "getpgid", .errpid = true, },
Arnaldo Carvalho de Meloc65f1072016-04-06 14:55:18 -0300891 { .name = "getppid", .errpid = true, },
Arnaldo Carvalho de Melo39878d42016-03-30 20:02:15 -0300892 { .name = "getrandom", .errmsg = true,
893 .arg_scnprintf = { [2] = SCA_GETRANDOM_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300894 { .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300895 { .name = "getxattr", .errmsg = true,
896 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
897 { .name = "inotify_add_watch", .errmsg = true,
898 .arg_scnprintf = { [1] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -0300899 { .name = "ioctl", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300900 .arg_scnprintf = { [0] = SCA_FD, /* fd */
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -0300901#if defined(__i386__) || defined(__x86_64__)
902/*
903 * FIXME: Make this available to all arches.
904 */
Arnaldo Carvalho de Melo78645cf2013-10-08 17:43:20 -0300905 [1] = SCA_STRHEXARRAY, /* cmd */
906 [2] = SCA_HEX, /* arg */ },
907 .arg_parm = { [1] = &strarray__tioctls, /* cmd */ }, },
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -0300908#else
909 [2] = SCA_HEX, /* arg */ }, },
910#endif
Arnaldo Carvalho de Melob62bee12015-08-11 11:05:36 -0300911 { .name = "keyctl", .errmsg = true, STRARRAY(0, option, keyctl_options), },
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -0300912 { .name = "kill", .errmsg = true,
913 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300914 { .name = "lchown", .errmsg = true,
915 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
916 { .name = "lgetxattr", .errmsg = true,
917 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300918 { .name = "linkat", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300919 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300920 { .name = "listxattr", .errmsg = true,
921 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -0300922 { .name = "llistxattr", .errmsg = true,
923 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
924 { .name = "lremovexattr", .errmsg = true,
925 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300926 { .name = "lseek", .errmsg = true,
927 .arg_scnprintf = { [0] = SCA_FD, /* fd */
928 [2] = SCA_STRARRAY, /* whence */ },
929 .arg_parm = { [2] = &strarray__whences, /* whence */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300930 { .name = "lsetxattr", .errmsg = true,
931 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -0300932 { .name = "lstat", .errmsg = true, .alias = "newlstat",
933 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300934 { .name = "lsxattr", .errmsg = true,
935 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo9e9716d2013-08-23 10:06:41 -0300936 { .name = "madvise", .errmsg = true,
937 .arg_scnprintf = { [0] = SCA_HEX, /* start */
938 [2] = SCA_MADV_BHV, /* behavior */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300939 { .name = "mkdir", .errmsg = true,
940 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300941 { .name = "mkdirat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300942 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */
943 [1] = SCA_FILENAME, /* pathname */ }, },
944 { .name = "mknod", .errmsg = true,
945 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300946 { .name = "mknodat", .errmsg = true,
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -0300947 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */
948 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo3d903aa2013-09-24 00:09:38 -0300949 { .name = "mlock", .errmsg = true,
950 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
951 { .name = "mlockall", .errmsg = true,
952 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -0300953 { .name = "mmap", .hexret = true,
Arnaldo Carvalho de Meloae685382013-08-20 17:44:42 -0300954 .arg_scnprintf = { [0] = SCA_HEX, /* addr */
Arnaldo Carvalho de Melo941557e2013-08-23 10:48:33 -0300955 [2] = SCA_MMAP_PROT, /* prot */
Namhyung Kim73faab32013-11-12 15:24:59 +0900956 [3] = SCA_MMAP_FLAGS, /* flags */
957 [4] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -0300958 { .name = "mprotect", .errmsg = true,
Arnaldo Carvalho de Meloae685382013-08-20 17:44:42 -0300959 .arg_scnprintf = { [0] = SCA_HEX, /* start */
960 [2] = SCA_MMAP_PROT, /* prot */ }, },
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -0300961 { .name = "mq_unlink", .errmsg = true,
962 .arg_scnprintf = { [0] = SCA_FILENAME, /* u_name */ }, },
Arnaldo Carvalho de Meloae685382013-08-20 17:44:42 -0300963 { .name = "mremap", .hexret = true,
964 .arg_scnprintf = { [0] = SCA_HEX, /* addr */
Alex Snast86998dd2014-08-13 18:42:40 +0300965 [3] = SCA_MREMAP_FLAGS, /* flags */
Arnaldo Carvalho de Meloae685382013-08-20 17:44:42 -0300966 [4] = SCA_HEX, /* new_addr */ }, },
Arnaldo Carvalho de Melo3d903aa2013-09-24 00:09:38 -0300967 { .name = "munlock", .errmsg = true,
968 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -0300969 { .name = "munmap", .errmsg = true,
970 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300971 { .name = "name_to_handle_at", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300972 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300973 { .name = "newfstatat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300974 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
975 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melobe65a892013-09-02 16:22:31 -0300976 { .name = "open", .errmsg = true,
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -0300977 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */
978 [1] = SCA_OPEN_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo31cd3852013-09-02 16:40:40 -0300979 { .name = "open_by_handle_at", .errmsg = true,
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300980 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
981 [2] = SCA_OPEN_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo31cd3852013-09-02 16:40:40 -0300982 { .name = "openat", .errmsg = true,
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300983 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300984 [1] = SCA_FILENAME, /* filename */
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300985 [2] = SCA_OPEN_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Meloa1c25522015-06-11 22:47:54 -0300986 { .name = "perf_event_open", .errmsg = true,
Arnaldo Carvalho de Meloccd9b2a2016-04-26 11:40:17 -0300987 .arg_scnprintf = { [2] = SCA_INT, /* cpu */
Arnaldo Carvalho de Meloa1c25522015-06-11 22:47:54 -0300988 [3] = SCA_FD, /* group_fd */
989 [4] = SCA_PERF_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo46cce192013-09-23 12:52:04 -0300990 { .name = "pipe2", .errmsg = true,
991 .arg_scnprintf = { [1] = SCA_PIPE_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -0300992 { .name = "poll", .errmsg = true, .timeout = true, },
993 { .name = "ppoll", .errmsg = true, .timeout = true, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300994 { .name = "pread", .errmsg = true, .alias = "pread64",
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300995 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300996 { .name = "preadv", .errmsg = true, .alias = "pread",
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300997 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300998 { .name = "prlimit64", .errmsg = true, STRARRAY(1, resource, rlimit_resources), },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300999 { .name = "pwrite", .errmsg = true, .alias = "pwrite64",
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001000 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001001 { .name = "pwritev", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001002 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001003 { .name = "read", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001004 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001005 { .name = "readlink", .errmsg = true,
1006 .arg_scnprintf = { [0] = SCA_FILENAME, /* path */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001007 { .name = "readlinkat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001008 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
1009 [1] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001010 { .name = "readv", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001011 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -03001012 { .name = "recvfrom", .errmsg = true,
Arnaldo Carvalho de Melo8d8c66a2015-08-11 10:57:02 -03001013 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1014 [3] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -03001015 { .name = "recvmmsg", .errmsg = true,
Arnaldo Carvalho de Melo8d8c66a2015-08-11 10:57:02 -03001016 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1017 [3] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -03001018 { .name = "recvmsg", .errmsg = true,
Arnaldo Carvalho de Melo8d8c66a2015-08-11 10:57:02 -03001019 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1020 [2] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001021 { .name = "removexattr", .errmsg = true,
1022 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001023 { .name = "renameat", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001024 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001025 { .name = "rmdir", .errmsg = true,
1026 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -03001027 { .name = "rt_sigaction", .errmsg = true,
1028 .arg_scnprintf = { [0] = SCA_SIGNUM, /* sig */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -03001029 { .name = "rt_sigprocmask", .errmsg = true, STRARRAY(0, how, sighow), },
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -03001030 { .name = "rt_sigqueueinfo", .errmsg = true,
1031 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
1032 { .name = "rt_tgsigqueueinfo", .errmsg = true,
1033 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
Arnaldo Carvalho de Meloa3bca912016-04-06 12:51:33 -03001034 { .name = "sched_setscheduler", .errmsg = true,
1035 .arg_scnprintf = { [1] = SCA_SCHED_POLICY, /* policy */ }, },
Arnaldo Carvalho de Melo997bba82016-03-30 19:43:32 -03001036 { .name = "seccomp", .errmsg = true,
1037 .arg_scnprintf = { [0] = SCA_SECCOMP_OP, /* op */
1038 [1] = SCA_SECCOMP_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -03001039 { .name = "select", .errmsg = true, .timeout = true, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -03001040 { .name = "sendmmsg", .errmsg = true,
Arnaldo Carvalho de Melo8d8c66a2015-08-11 10:57:02 -03001041 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1042 [3] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -03001043 { .name = "sendmsg", .errmsg = true,
Arnaldo Carvalho de Melo8d8c66a2015-08-11 10:57:02 -03001044 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1045 [2] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -03001046 { .name = "sendto", .errmsg = true,
Arnaldo Carvalho de Melo8d8c66a2015-08-11 10:57:02 -03001047 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1048 [3] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Meloc65f1072016-04-06 14:55:18 -03001049 { .name = "set_tid_address", .errpid = true, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -03001050 { .name = "setitimer", .errmsg = true, STRARRAY(0, which, itimers), },
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -03001051 { .name = "setpgid", .errmsg = true, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -03001052 { .name = "setrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001053 { .name = "setxattr", .errmsg = true,
1054 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001055 { .name = "shutdown", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001056 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Meloe10bce82013-09-04 10:27:41 -03001057 { .name = "socket", .errmsg = true,
Arnaldo Carvalho de Meloa28b24b2013-09-04 11:00:44 -03001058 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
1059 [1] = SCA_SK_TYPE, /* type */ },
Arnaldo Carvalho de Meloe10bce82013-09-04 10:27:41 -03001060 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, },
Arnaldo Carvalho de Melo07120aa2013-09-20 12:24:20 -03001061 { .name = "socketpair", .errmsg = true,
1062 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
1063 [1] = SCA_SK_TYPE, /* type */ },
1064 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, },
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -03001065 { .name = "stat", .errmsg = true, .alias = "newstat",
1066 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001067 { .name = "statfs", .errmsg = true,
1068 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
1069 { .name = "swapoff", .errmsg = true,
1070 .arg_scnprintf = { [0] = SCA_FILENAME, /* specialfile */ }, },
1071 { .name = "swapon", .errmsg = true,
1072 .arg_scnprintf = { [0] = SCA_FILENAME, /* specialfile */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001073 { .name = "symlinkat", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001074 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -03001075 { .name = "tgkill", .errmsg = true,
1076 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
1077 { .name = "tkill", .errmsg = true,
1078 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001079 { .name = "truncate", .errmsg = true,
1080 .arg_scnprintf = { [0] = SCA_FILENAME, /* path */ }, },
Arnaldo Carvalho de Meloe5959682013-08-26 12:21:41 -03001081 { .name = "uname", .errmsg = true, .alias = "newuname", },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001082 { .name = "unlinkat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001083 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
1084 [1] = SCA_FILENAME, /* pathname */ }, },
1085 { .name = "utime", .errmsg = true,
1086 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001087 { .name = "utimensat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001088 .arg_scnprintf = { [0] = SCA_FDAT, /* dirfd */
1089 [1] = SCA_FILENAME, /* filename */ }, },
1090 { .name = "utimes", .errmsg = true,
1091 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -03001092 { .name = "vmsplice", .errmsg = true,
1093 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -03001094 { .name = "wait4", .errpid = true,
Arnaldo Carvalho de Melo7206b902016-04-06 14:11:36 -03001095 .arg_scnprintf = { [2] = SCA_WAITID_OPTIONS, /* options */ }, },
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -03001096 { .name = "waitid", .errpid = true,
Arnaldo Carvalho de Melo7206b902016-04-06 14:11:36 -03001097 .arg_scnprintf = { [3] = SCA_WAITID_OPTIONS, /* options */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001098 { .name = "write", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001099 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001100 { .name = "writev", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001101 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001102};
1103
1104static int syscall_fmt__cmp(const void *name, const void *fmtp)
1105{
1106 const struct syscall_fmt *fmt = fmtp;
1107 return strcmp(name, fmt->name);
1108}
1109
1110static struct syscall_fmt *syscall_fmt__find(const char *name)
1111{
1112 const int nmemb = ARRAY_SIZE(syscall_fmts);
1113 return bsearch(name, syscall_fmts, nmemb, sizeof(struct syscall_fmt), syscall_fmt__cmp);
1114}
1115
1116struct syscall {
1117 struct event_format *tp_format;
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001118 int nr_args;
1119 struct format_field *args;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001120 const char *name;
Arnaldo Carvalho de Melo5089f202014-06-17 14:29:24 -03001121 bool is_exit;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001122 struct syscall_fmt *fmt;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001123 size_t (**arg_scnprintf)(char *bf, size_t size, struct syscall_arg *arg);
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -03001124 void **arg_parm;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001125};
1126
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001127static size_t fprintf_duration(unsigned long t, FILE *fp)
1128{
1129 double duration = (double)t / NSEC_PER_MSEC;
1130 size_t printed = fprintf(fp, "(");
1131
1132 if (duration >= 1.0)
1133 printed += color_fprintf(fp, PERF_COLOR_RED, "%6.3f ms", duration);
1134 else if (duration >= 0.01)
1135 printed += color_fprintf(fp, PERF_COLOR_YELLOW, "%6.3f ms", duration);
1136 else
1137 printed += color_fprintf(fp, PERF_COLOR_NORMAL, "%6.3f ms", duration);
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001138 return printed + fprintf(fp, "): ");
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001139}
1140
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001141/**
1142 * filename.ptr: The filename char pointer that will be vfs_getname'd
1143 * filename.entry_str_pos: Where to insert the string translated from
1144 * filename.ptr by the vfs_getname tracepoint/kprobe.
1145 */
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001146struct thread_trace {
1147 u64 entry_time;
1148 u64 exit_time;
1149 bool entry_pending;
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03001150 unsigned long nr_events;
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04001151 unsigned long pfmaj, pfmin;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001152 char *entry_str;
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001153 double runtime_ms;
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001154 struct {
1155 unsigned long ptr;
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03001156 short int entry_str_pos;
1157 bool pending_open;
1158 unsigned int namelen;
1159 char *name;
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001160 } filename;
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001161 struct {
1162 int max;
1163 char **table;
1164 } paths;
David Ahernbf2575c2013-10-08 21:26:53 -06001165
1166 struct intlist *syscall_stats;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001167};
1168
1169static struct thread_trace *thread_trace__new(void)
1170{
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001171 struct thread_trace *ttrace = zalloc(sizeof(struct thread_trace));
1172
1173 if (ttrace)
1174 ttrace->paths.max = -1;
1175
David Ahernbf2575c2013-10-08 21:26:53 -06001176 ttrace->syscall_stats = intlist__new(NULL);
1177
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001178 return ttrace;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001179}
1180
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001181static struct thread_trace *thread__trace(struct thread *thread, FILE *fp)
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001182{
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03001183 struct thread_trace *ttrace;
1184
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001185 if (thread == NULL)
1186 goto fail;
1187
Namhyung Kim89dceb22014-10-06 09:46:03 +09001188 if (thread__priv(thread) == NULL)
1189 thread__set_priv(thread, thread_trace__new());
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001190
Namhyung Kim89dceb22014-10-06 09:46:03 +09001191 if (thread__priv(thread) == NULL)
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001192 goto fail;
1193
Namhyung Kim89dceb22014-10-06 09:46:03 +09001194 ttrace = thread__priv(thread);
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03001195 ++ttrace->nr_events;
1196
1197 return ttrace;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001198fail:
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001199 color_fprintf(fp, PERF_COLOR_RED,
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001200 "WARNING: not enough memory, dropping samples!\n");
1201 return NULL;
1202}
1203
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04001204#define TRACE_PFMAJ (1 << 0)
1205#define TRACE_PFMIN (1 << 1)
1206
Arnaldo Carvalho de Meloe4d44e82015-08-04 22:17:29 -03001207static const size_t trace__entry_str_size = 2048;
1208
Arnaldo Carvalho de Melo97119f32013-09-27 17:34:10 -03001209static int trace__set_fd_pathname(struct thread *thread, int fd, const char *pathname)
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001210{
Namhyung Kim89dceb22014-10-06 09:46:03 +09001211 struct thread_trace *ttrace = thread__priv(thread);
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001212
1213 if (fd > ttrace->paths.max) {
1214 char **npath = realloc(ttrace->paths.table, (fd + 1) * sizeof(char *));
1215
1216 if (npath == NULL)
1217 return -1;
1218
1219 if (ttrace->paths.max != -1) {
1220 memset(npath + ttrace->paths.max + 1, 0,
1221 (fd - ttrace->paths.max) * sizeof(char *));
1222 } else {
1223 memset(npath, 0, (fd + 1) * sizeof(char *));
1224 }
1225
1226 ttrace->paths.table = npath;
1227 ttrace->paths.max = fd;
1228 }
1229
1230 ttrace->paths.table[fd] = strdup(pathname);
1231
1232 return ttrace->paths.table[fd] != NULL ? 0 : -1;
1233}
1234
Arnaldo Carvalho de Melo97119f32013-09-27 17:34:10 -03001235static int thread__read_fd_path(struct thread *thread, int fd)
1236{
1237 char linkname[PATH_MAX], pathname[PATH_MAX];
1238 struct stat st;
1239 int ret;
1240
1241 if (thread->pid_ == thread->tid) {
1242 scnprintf(linkname, sizeof(linkname),
1243 "/proc/%d/fd/%d", thread->pid_, fd);
1244 } else {
1245 scnprintf(linkname, sizeof(linkname),
1246 "/proc/%d/task/%d/fd/%d", thread->pid_, thread->tid, fd);
1247 }
1248
1249 if (lstat(linkname, &st) < 0 || st.st_size + 1 > (off_t)sizeof(pathname))
1250 return -1;
1251
1252 ret = readlink(linkname, pathname, sizeof(pathname));
1253
1254 if (ret < 0 || ret > st.st_size)
1255 return -1;
1256
1257 pathname[ret] = '\0';
1258 return trace__set_fd_pathname(thread, fd, pathname);
1259}
1260
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001261static const char *thread__fd_path(struct thread *thread, int fd,
1262 struct trace *trace)
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001263{
Namhyung Kim89dceb22014-10-06 09:46:03 +09001264 struct thread_trace *ttrace = thread__priv(thread);
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001265
1266 if (ttrace == NULL)
1267 return NULL;
1268
1269 if (fd < 0)
1270 return NULL;
1271
Arnaldo Carvalho de Melocdcd1e62014-06-10 16:00:18 -03001272 if ((fd > ttrace->paths.max || ttrace->paths.table[fd] == NULL)) {
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001273 if (!trace->live)
1274 return NULL;
1275 ++trace->stats.proc_getname;
Arnaldo Carvalho de Melocdcd1e62014-06-10 16:00:18 -03001276 if (thread__read_fd_path(thread, fd))
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001277 return NULL;
1278 }
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001279
1280 return ttrace->paths.table[fd];
1281}
1282
1283static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
1284 struct syscall_arg *arg)
1285{
1286 int fd = arg->val;
1287 size_t printed = scnprintf(bf, size, "%d", fd);
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001288 const char *path = thread__fd_path(arg->thread, fd, arg->trace);
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001289
1290 if (path)
1291 printed += scnprintf(bf + printed, size - printed, "<%s>", path);
1292
1293 return printed;
1294}
1295
1296static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
1297 struct syscall_arg *arg)
1298{
1299 int fd = arg->val;
1300 size_t printed = syscall_arg__scnprintf_fd(bf, size, arg);
Namhyung Kim89dceb22014-10-06 09:46:03 +09001301 struct thread_trace *ttrace = thread__priv(arg->thread);
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001302
Arnaldo Carvalho de Melo04662522013-12-26 17:41:15 -03001303 if (ttrace && fd >= 0 && fd <= ttrace->paths.max)
1304 zfree(&ttrace->paths.table[fd]);
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001305
1306 return printed;
1307}
1308
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001309static void thread__set_filename_pos(struct thread *thread, const char *bf,
1310 unsigned long ptr)
1311{
1312 struct thread_trace *ttrace = thread__priv(thread);
1313
1314 ttrace->filename.ptr = ptr;
1315 ttrace->filename.entry_str_pos = bf - ttrace->entry_str;
1316}
1317
1318static size_t syscall_arg__scnprintf_filename(char *bf, size_t size,
1319 struct syscall_arg *arg)
1320{
1321 unsigned long ptr = arg->val;
1322
1323 if (!arg->trace->vfs_getname)
1324 return scnprintf(bf, size, "%#x", ptr);
1325
1326 thread__set_filename_pos(arg->thread, bf, ptr);
1327 return 0;
1328}
1329
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001330static bool trace__filter_duration(struct trace *trace, double t)
1331{
1332 return t < (trace->duration_filter * NSEC_PER_MSEC);
1333}
1334
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001335static size_t trace__fprintf_tstamp(struct trace *trace, u64 tstamp, FILE *fp)
1336{
1337 double ts = (double)(tstamp - trace->base_time) / NSEC_PER_MSEC;
1338
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001339 return fprintf(fp, "%10.3f ", ts);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001340}
1341
Namhyung Kimf15eb532012-10-05 14:02:16 +09001342static bool done = false;
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03001343static bool interrupted = false;
Namhyung Kimf15eb532012-10-05 14:02:16 +09001344
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03001345static void sig_handler(int sig)
Namhyung Kimf15eb532012-10-05 14:02:16 +09001346{
1347 done = true;
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03001348 interrupted = sig == SIGINT;
Namhyung Kimf15eb532012-10-05 14:02:16 +09001349}
1350
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001351static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thread,
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001352 u64 duration, u64 tstamp, FILE *fp)
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001353{
1354 size_t printed = trace__fprintf_tstamp(trace, tstamp, fp);
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001355 printed += fprintf_duration(duration, fp);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001356
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -03001357 if (trace->multiple_threads) {
1358 if (trace->show_comm)
Frederic Weisbecker1902efe2013-09-11 16:56:44 +02001359 printed += fprintf(fp, "%.14s/", thread__comm_str(thread));
Adrian Hunter38051232013-07-04 16:20:31 +03001360 printed += fprintf(fp, "%d ", thread->tid);
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -03001361 }
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001362
1363 return printed;
1364}
1365
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001366static int trace__process_event(struct trace *trace, struct machine *machine,
Frederic Weisbecker162f0be2013-09-11 16:18:24 +02001367 union perf_event *event, struct perf_sample *sample)
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001368{
1369 int ret = 0;
1370
1371 switch (event->header.type) {
1372 case PERF_RECORD_LOST:
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001373 color_fprintf(trace->output, PERF_COLOR_RED,
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001374 "LOST %" PRIu64 " events!\n", event->lost.lost);
Frederic Weisbecker162f0be2013-09-11 16:18:24 +02001375 ret = machine__process_lost_event(machine, event, sample);
Arnaldo Carvalho de Melo3ed5ca22016-03-30 16:51:17 -03001376 break;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001377 default:
Frederic Weisbecker162f0be2013-09-11 16:18:24 +02001378 ret = machine__process_event(machine, event, sample);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001379 break;
1380 }
1381
1382 return ret;
1383}
1384
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001385static int trace__tool_process(struct perf_tool *tool,
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001386 union perf_event *event,
Frederic Weisbecker162f0be2013-09-11 16:18:24 +02001387 struct perf_sample *sample,
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001388 struct machine *machine)
1389{
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001390 struct trace *trace = container_of(tool, struct trace, tool);
Frederic Weisbecker162f0be2013-09-11 16:18:24 +02001391 return trace__process_event(trace, machine, event, sample);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001392}
1393
1394static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
1395{
Namhyung Kim0a7e6d12014-08-12 15:40:45 +09001396 int err = symbol__init(NULL);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001397
1398 if (err)
1399 return err;
1400
David Ahern8fb598e2013-09-28 13:13:00 -06001401 trace->host = machine__new_host();
1402 if (trace->host == NULL)
1403 return -ENOMEM;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001404
Arnaldo Carvalho de Melo959c2192015-07-24 12:13:05 -03001405 if (trace_event__register_resolver(trace->host, machine__resolve_kernel_addr) < 0)
Arnaldo Carvalho de Melo706c3da2015-07-22 16:16:16 -03001406 return -errno;
1407
Arnaldo Carvalho de Meloa33fbd52013-11-11 11:36:12 -03001408 err = __machine__synthesize_threads(trace->host, &trace->tool, &trace->opts.target,
Kan Liang9d9cad72015-06-17 09:51:11 -04001409 evlist->threads, trace__tool_process, false,
1410 trace->opts.proc_map_timeout);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001411 if (err)
1412 symbol__exit();
1413
1414 return err;
1415}
1416
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001417static int syscall__set_arg_fmts(struct syscall *sc)
1418{
1419 struct format_field *field;
1420 int idx = 0;
1421
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001422 sc->arg_scnprintf = calloc(sc->nr_args, sizeof(void *));
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001423 if (sc->arg_scnprintf == NULL)
1424 return -1;
1425
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -03001426 if (sc->fmt)
1427 sc->arg_parm = sc->fmt->arg_parm;
1428
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001429 for (field = sc->args; field; field = field->next) {
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -03001430 if (sc->fmt && sc->fmt->arg_scnprintf[idx])
1431 sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx];
1432 else if (field->flags & FIELD_IS_POINTER)
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001433 sc->arg_scnprintf[idx] = syscall_arg__scnprintf_hex;
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -03001434 else if (strcmp(field->type, "pid_t") == 0)
1435 sc->arg_scnprintf[idx] = SCA_PID;
Arnaldo Carvalho de Meloba2f22c2016-04-07 12:05:51 -03001436 else if (strcmp(field->type, "umode_t") == 0)
1437 sc->arg_scnprintf[idx] = SCA_MODE_T;
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001438 ++idx;
1439 }
1440
1441 return 0;
1442}
1443
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001444static int trace__read_syscall_info(struct trace *trace, int id)
1445{
1446 char tp_name[128];
1447 struct syscall *sc;
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03001448 const char *name = syscalltbl__name(trace->sctbl, id);
Arnaldo Carvalho de Melo3a531262012-10-20 12:39:03 -03001449
1450 if (name == NULL)
1451 return -1;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001452
1453 if (id > trace->syscalls.max) {
1454 struct syscall *nsyscalls = realloc(trace->syscalls.table, (id + 1) * sizeof(*sc));
1455
1456 if (nsyscalls == NULL)
1457 return -1;
1458
1459 if (trace->syscalls.max != -1) {
1460 memset(nsyscalls + trace->syscalls.max + 1, 0,
1461 (id - trace->syscalls.max) * sizeof(*sc));
1462 } else {
1463 memset(nsyscalls, 0, (id + 1) * sizeof(*sc));
1464 }
1465
1466 trace->syscalls.table = nsyscalls;
1467 trace->syscalls.max = id;
1468 }
1469
1470 sc = trace->syscalls.table + id;
Arnaldo Carvalho de Melo3a531262012-10-20 12:39:03 -03001471 sc->name = name;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001472
Arnaldo Carvalho de Melo3a531262012-10-20 12:39:03 -03001473 sc->fmt = syscall_fmt__find(sc->name);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001474
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -03001475 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name);
Jiri Olsa97978b32013-12-03 14:09:24 +01001476 sc->tp_format = trace_event__tp_format("syscalls", tp_name);
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -03001477
Jiri Olsa8dd2a132015-09-07 10:38:06 +02001478 if (IS_ERR(sc->tp_format) && sc->fmt && sc->fmt->alias) {
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -03001479 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->fmt->alias);
Jiri Olsa97978b32013-12-03 14:09:24 +01001480 sc->tp_format = trace_event__tp_format("syscalls", tp_name);
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -03001481 }
1482
Jiri Olsa8dd2a132015-09-07 10:38:06 +02001483 if (IS_ERR(sc->tp_format))
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001484 return -1;
1485
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001486 sc->args = sc->tp_format->format.fields;
1487 sc->nr_args = sc->tp_format->format.nr_fields;
Taeung Songc42de702016-02-26 22:14:25 +09001488 /*
1489 * We need to check and discard the first variable '__syscall_nr'
1490 * or 'nr' that mean the syscall number. It is needless here.
1491 * So drop '__syscall_nr' or 'nr' field but does not exist on older kernels.
1492 */
1493 if (sc->args && (!strcmp(sc->args->name, "__syscall_nr") || !strcmp(sc->args->name, "nr"))) {
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001494 sc->args = sc->args->next;
1495 --sc->nr_args;
1496 }
1497
Arnaldo Carvalho de Melo5089f202014-06-17 14:29:24 -03001498 sc->is_exit = !strcmp(name, "exit_group") || !strcmp(name, "exit");
1499
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001500 return syscall__set_arg_fmts(sc);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001501}
1502
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001503static int trace__validate_ev_qualifier(struct trace *trace)
1504{
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001505 int err = 0, i;
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001506 struct str_node *pos;
1507
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001508 trace->ev_qualifier_ids.nr = strlist__nr_entries(trace->ev_qualifier);
1509 trace->ev_qualifier_ids.entries = malloc(trace->ev_qualifier_ids.nr *
1510 sizeof(trace->ev_qualifier_ids.entries[0]));
1511
1512 if (trace->ev_qualifier_ids.entries == NULL) {
1513 fputs("Error:\tNot enough memory for allocating events qualifier ids\n",
1514 trace->output);
1515 err = -EINVAL;
1516 goto out;
1517 }
1518
1519 i = 0;
1520
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001521 strlist__for_each(pos, trace->ev_qualifier) {
1522 const char *sc = pos->s;
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03001523 int id = syscalltbl__id(trace->sctbl, sc);
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001524
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001525 if (id < 0) {
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001526 if (err == 0) {
1527 fputs("Error:\tInvalid syscall ", trace->output);
1528 err = -EINVAL;
1529 } else {
1530 fputs(", ", trace->output);
1531 }
1532
1533 fputs(sc, trace->output);
1534 }
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001535
1536 trace->ev_qualifier_ids.entries[i++] = id;
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001537 }
1538
1539 if (err < 0) {
1540 fputs("\nHint:\ttry 'perf list syscalls:sys_enter_*'"
1541 "\nHint:\tand: 'man syscalls'\n", trace->output);
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001542 zfree(&trace->ev_qualifier_ids.entries);
1543 trace->ev_qualifier_ids.nr = 0;
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001544 }
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001545out:
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001546 return err;
1547}
1548
David Ahern55d43bca2015-02-19 15:00:22 -05001549/*
1550 * args is to be interpreted as a series of longs but we need to handle
1551 * 8-byte unaligned accesses. args points to raw_data within the event
1552 * and raw_data is guaranteed to be 8-byte unaligned because it is
1553 * preceded by raw_size which is a u32. So we need to copy args to a temp
1554 * variable to read it. Most notably this avoids extended load instructions
1555 * on unaligned addresses
1556 */
1557
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001558static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
David Ahern55d43bca2015-02-19 15:00:22 -05001559 unsigned char *args, struct trace *trace,
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001560 struct thread *thread)
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001561{
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001562 size_t printed = 0;
David Ahern55d43bca2015-02-19 15:00:22 -05001563 unsigned char *p;
1564 unsigned long val;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001565
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001566 if (sc->args != NULL) {
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001567 struct format_field *field;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001568 u8 bit = 1;
1569 struct syscall_arg arg = {
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001570 .idx = 0,
1571 .mask = 0,
1572 .trace = trace,
1573 .thread = thread,
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001574 };
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001575
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001576 for (field = sc->args; field;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001577 field = field->next, ++arg.idx, bit <<= 1) {
1578 if (arg.mask & bit)
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -03001579 continue;
David Ahern55d43bca2015-02-19 15:00:22 -05001580
1581 /* special care for unaligned accesses */
1582 p = args + sizeof(unsigned long) * arg.idx;
1583 memcpy(&val, p, sizeof(val));
1584
Arnaldo Carvalho de Melo4aa58232013-09-20 12:19:41 -03001585 /*
1586 * Suppress this argument if its value is zero and
1587 * and we don't have a string associated in an
1588 * strarray for it.
1589 */
David Ahern55d43bca2015-02-19 15:00:22 -05001590 if (val == 0 &&
Arnaldo Carvalho de Melo4aa58232013-09-20 12:19:41 -03001591 !(sc->arg_scnprintf &&
1592 sc->arg_scnprintf[arg.idx] == SCA_STRARRAY &&
1593 sc->arg_parm[arg.idx]))
Arnaldo Carvalho de Melo22ae5cf12013-09-12 11:27:34 -03001594 continue;
1595
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001596 printed += scnprintf(bf + printed, size - printed,
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001597 "%s%s: ", printed ? ", " : "", field->name);
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001598 if (sc->arg_scnprintf && sc->arg_scnprintf[arg.idx]) {
David Ahern55d43bca2015-02-19 15:00:22 -05001599 arg.val = val;
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -03001600 if (sc->arg_parm)
1601 arg.parm = sc->arg_parm[arg.idx];
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001602 printed += sc->arg_scnprintf[arg.idx](bf + printed,
1603 size - printed, &arg);
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -03001604 } else {
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001605 printed += scnprintf(bf + printed, size - printed,
David Ahern55d43bca2015-02-19 15:00:22 -05001606 "%ld", val);
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -03001607 }
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001608 }
1609 } else {
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001610 int i = 0;
1611
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001612 while (i < 6) {
David Ahern55d43bca2015-02-19 15:00:22 -05001613 /* special care for unaligned accesses */
1614 p = args + sizeof(unsigned long) * i;
1615 memcpy(&val, p, sizeof(val));
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001616 printed += scnprintf(bf + printed, size - printed,
1617 "%sarg%d: %ld",
David Ahern55d43bca2015-02-19 15:00:22 -05001618 printed ? ", " : "", i, val);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001619 ++i;
1620 }
1621 }
1622
1623 return printed;
1624}
1625
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001626typedef int (*tracepoint_handler)(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04001627 union perf_event *event,
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001628 struct perf_sample *sample);
1629
1630static struct syscall *trace__syscall_info(struct trace *trace,
David Ahernbf2575c2013-10-08 21:26:53 -06001631 struct perf_evsel *evsel, int id)
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001632{
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001633
1634 if (id < 0) {
Arnaldo Carvalho de Meloadaa18b2013-08-22 17:55:25 -03001635
1636 /*
1637 * XXX: Noticed on x86_64, reproduced as far back as 3.0.36, haven't tried
1638 * before that, leaving at a higher verbosity level till that is
1639 * explained. Reproduced with plain ftrace with:
1640 *
1641 * echo 1 > /t/events/raw_syscalls/sys_exit/enable
1642 * grep "NR -1 " /t/trace_pipe
1643 *
1644 * After generating some load on the machine.
1645 */
1646 if (verbose > 1) {
1647 static u64 n;
1648 fprintf(trace->output, "Invalid syscall %d id, skipping (%s, %" PRIu64 ") ...\n",
1649 id, perf_evsel__name(evsel), ++n);
1650 }
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001651 return NULL;
1652 }
1653
1654 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL) &&
1655 trace__read_syscall_info(trace, id))
1656 goto out_cant_read;
1657
1658 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL))
1659 goto out_cant_read;
1660
1661 return &trace->syscalls.table[id];
1662
1663out_cant_read:
Arnaldo Carvalho de Melo7c304ee02013-08-22 16:49:54 -03001664 if (verbose) {
1665 fprintf(trace->output, "Problems reading syscall %d", id);
1666 if (id <= trace->syscalls.max && trace->syscalls.table[id].name != NULL)
1667 fprintf(trace->output, "(%s)", trace->syscalls.table[id].name);
1668 fputs(" information\n", trace->output);
1669 }
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001670 return NULL;
1671}
1672
David Ahernbf2575c2013-10-08 21:26:53 -06001673static void thread__update_stats(struct thread_trace *ttrace,
1674 int id, struct perf_sample *sample)
1675{
1676 struct int_node *inode;
1677 struct stats *stats;
1678 u64 duration = 0;
1679
1680 inode = intlist__findnew(ttrace->syscall_stats, id);
1681 if (inode == NULL)
1682 return;
1683
1684 stats = inode->priv;
1685 if (stats == NULL) {
1686 stats = malloc(sizeof(struct stats));
1687 if (stats == NULL)
1688 return;
1689 init_stats(stats);
1690 inode->priv = stats;
1691 }
1692
1693 if (ttrace->entry_time && sample->time > ttrace->entry_time)
1694 duration = sample->time - ttrace->entry_time;
1695
1696 update_stats(stats, duration);
1697}
1698
Arnaldo Carvalho de Meloe5966632015-02-13 13:22:21 -03001699static int trace__printf_interrupted_entry(struct trace *trace, struct perf_sample *sample)
1700{
1701 struct thread_trace *ttrace;
1702 u64 duration;
1703 size_t printed;
1704
1705 if (trace->current == NULL)
1706 return 0;
1707
1708 ttrace = thread__priv(trace->current);
1709
1710 if (!ttrace->entry_pending)
1711 return 0;
1712
1713 duration = sample->time - ttrace->entry_time;
1714
1715 printed = trace__fprintf_entry_head(trace, trace->current, duration, sample->time, trace->output);
1716 printed += fprintf(trace->output, "%-70s) ...\n", ttrace->entry_str);
1717 ttrace->entry_pending = false;
1718
1719 return printed;
1720}
1721
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001722static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04001723 union perf_event *event __maybe_unused,
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001724 struct perf_sample *sample)
1725{
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001726 char *msg;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001727 void *args;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001728 size_t printed = 0;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001729 struct thread *thread;
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001730 int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
David Ahernbf2575c2013-10-08 21:26:53 -06001731 struct syscall *sc = trace__syscall_info(trace, evsel, id);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001732 struct thread_trace *ttrace;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001733
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001734 if (sc == NULL)
1735 return -1;
1736
David Ahern8fb598e2013-09-28 13:13:00 -06001737 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001738 ttrace = thread__trace(thread, trace->output);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001739 if (ttrace == NULL)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001740 goto out_put;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001741
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -03001742 args = perf_evsel__sc_tp_ptr(evsel, args, sample);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001743
1744 if (ttrace->entry_str == NULL) {
Arnaldo Carvalho de Meloe4d44e82015-08-04 22:17:29 -03001745 ttrace->entry_str = malloc(trace__entry_str_size);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001746 if (!ttrace->entry_str)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001747 goto out_put;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001748 }
1749
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -03001750 if (!(trace->duration_filter || trace->summary_only || trace->min_stack))
Arnaldo Carvalho de Melo6ebad5c2015-03-25 18:01:15 -03001751 trace__printf_interrupted_entry(trace, sample);
Arnaldo Carvalho de Meloe5966632015-02-13 13:22:21 -03001752
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001753 ttrace->entry_time = sample->time;
1754 msg = ttrace->entry_str;
Arnaldo Carvalho de Meloe4d44e82015-08-04 22:17:29 -03001755 printed += scnprintf(msg + printed, trace__entry_str_size - printed, "%s(", sc->name);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001756
Arnaldo Carvalho de Meloe4d44e82015-08-04 22:17:29 -03001757 printed += syscall__scnprintf_args(sc, msg + printed, trace__entry_str_size - printed,
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001758 args, trace, thread);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001759
Arnaldo Carvalho de Melo5089f202014-06-17 14:29:24 -03001760 if (sc->is_exit) {
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -03001761 if (!(trace->duration_filter || trace->summary_only || trace->min_stack)) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001762 trace__fprintf_entry_head(trace, thread, 1, sample->time, trace->output);
1763 fprintf(trace->output, "%-70s\n", ttrace->entry_str);
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001764 }
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03001765 } else {
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001766 ttrace->entry_pending = true;
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03001767 /* See trace__vfs_getname & trace__sys_exit */
1768 ttrace->filename.pending_open = false;
1769 }
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001770
Arnaldo Carvalho de Melof3b623b2015-03-02 22:21:35 -03001771 if (trace->current != thread) {
1772 thread__put(trace->current);
1773 trace->current = thread__get(thread);
1774 }
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001775 err = 0;
1776out_put:
1777 thread__put(thread);
1778 return err;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001779}
1780
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -03001781static int trace__resolve_callchain(struct trace *trace, struct perf_evsel *evsel,
1782 struct perf_sample *sample,
1783 struct callchain_cursor *cursor)
Arnaldo Carvalho de Melo202ff962016-04-12 10:11:07 -03001784{
1785 struct addr_location al;
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -03001786
1787 if (machine__resolve(trace->host, &al, sample) < 0 ||
1788 thread__resolve_callchain(al.thread, cursor, evsel, sample, NULL, NULL, trace->max_stack))
1789 return -1;
1790
1791 return 0;
1792}
1793
1794static int trace__fprintf_callchain(struct trace *trace, struct perf_sample *sample)
1795{
Arnaldo Carvalho de Melo202ff962016-04-12 10:11:07 -03001796 /* TODO: user-configurable print_opts */
Arnaldo Carvalho de Meloe20ab862016-04-12 15:16:15 -03001797 const unsigned int print_opts = EVSEL__PRINT_SYM |
1798 EVSEL__PRINT_DSO |
1799 EVSEL__PRINT_UNKNOWN_AS_ADDR;
Arnaldo Carvalho de Melo202ff962016-04-12 10:11:07 -03001800
Arnaldo Carvalho de Melod327e602016-04-14 17:53:49 -03001801 return sample__fprintf_callchain(sample, 38, print_opts, &callchain_cursor, trace->output);
Arnaldo Carvalho de Melo202ff962016-04-12 10:11:07 -03001802}
1803
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001804static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04001805 union perf_event *event __maybe_unused,
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001806 struct perf_sample *sample)
1807{
Chang Hyun Park2c82c3a2014-09-26 21:54:01 +09001808 long ret;
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001809 u64 duration = 0;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001810 struct thread *thread;
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -03001811 int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1, callchain_ret = 0;
David Ahernbf2575c2013-10-08 21:26:53 -06001812 struct syscall *sc = trace__syscall_info(trace, evsel, id);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001813 struct thread_trace *ttrace;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001814
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001815 if (sc == NULL)
1816 return -1;
1817
David Ahern8fb598e2013-09-28 13:13:00 -06001818 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001819 ttrace = thread__trace(thread, trace->output);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001820 if (ttrace == NULL)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001821 goto out_put;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001822
David Ahernbf2575c2013-10-08 21:26:53 -06001823 if (trace->summary)
1824 thread__update_stats(ttrace, id, sample);
1825
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -03001826 ret = perf_evsel__sc_tp_uint(evsel, ret, sample);
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001827
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03001828 if (id == trace->open_id && ret >= 0 && ttrace->filename.pending_open) {
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03001829 trace__set_fd_pathname(thread, ret, ttrace->filename.name);
1830 ttrace->filename.pending_open = false;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001831 ++trace->stats.vfs_getname;
1832 }
1833
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001834 ttrace->exit_time = sample->time;
1835
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001836 if (ttrace->entry_time) {
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001837 duration = sample->time - ttrace->entry_time;
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001838 if (trace__filter_duration(trace, duration))
1839 goto out;
1840 } else if (trace->duration_filter)
1841 goto out;
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001842
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -03001843 if (sample->callchain) {
1844 callchain_ret = trace__resolve_callchain(trace, evsel, sample, &callchain_cursor);
1845 if (callchain_ret == 0) {
1846 if (callchain_cursor.nr < trace->min_stack)
1847 goto out;
1848 callchain_ret = 1;
1849 }
1850 }
1851
David Ahernfd2eaba2013-11-12 09:31:15 -07001852 if (trace->summary_only)
1853 goto out;
1854
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001855 trace__fprintf_entry_head(trace, thread, duration, sample->time, trace->output);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001856
1857 if (ttrace->entry_pending) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001858 fprintf(trace->output, "%-70s", ttrace->entry_str);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001859 } else {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001860 fprintf(trace->output, " ... [");
1861 color_fprintf(trace->output, PERF_COLOR_YELLOW, "continued");
1862 fprintf(trace->output, "]: %s()", sc->name);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001863 }
1864
Arnaldo Carvalho de Meloda3c9a42013-08-26 11:28:34 -03001865 if (sc->fmt == NULL) {
1866signed_print:
Chang Hyun Park2c82c3a2014-09-26 21:54:01 +09001867 fprintf(trace->output, ") = %ld", ret);
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -03001868 } else if (ret < 0 && (sc->fmt->errmsg || sc->fmt->errpid)) {
Masami Hiramatsu942a91e2014-08-14 02:22:41 +00001869 char bf[STRERR_BUFSIZE];
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001870 const char *emsg = strerror_r(-ret, bf, sizeof(bf)),
1871 *e = audit_errno_to_name(-ret);
1872
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001873 fprintf(trace->output, ") = -1 %s %s", e, emsg);
Arnaldo Carvalho de Meloda3c9a42013-08-26 11:28:34 -03001874 } else if (ret == 0 && sc->fmt->timeout)
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001875 fprintf(trace->output, ") = 0 Timeout");
Arnaldo Carvalho de Melo04b34722013-08-26 11:36:30 -03001876 else if (sc->fmt->hexret)
Chang Hyun Park2c82c3a2014-09-26 21:54:01 +09001877 fprintf(trace->output, ") = %#lx", ret);
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -03001878 else if (sc->fmt->errpid) {
1879 struct thread *child = machine__find_thread(trace->host, ret, ret);
1880
1881 if (child != NULL) {
1882 fprintf(trace->output, ") = %ld", ret);
1883 if (child->comm_set)
1884 fprintf(trace->output, " (%s)", thread__comm_str(child));
1885 thread__put(child);
1886 }
1887 } else
Arnaldo Carvalho de Meloda3c9a42013-08-26 11:28:34 -03001888 goto signed_print;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001889
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001890 fputc('\n', trace->output);
Milian Wolff566a0882016-04-08 13:34:15 +02001891
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -03001892 if (callchain_ret > 0)
1893 trace__fprintf_callchain(trace, sample);
1894 else if (callchain_ret < 0)
1895 pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel));
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001896out:
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001897 ttrace->entry_pending = false;
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001898 err = 0;
1899out_put:
1900 thread__put(thread);
1901 return err;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001902}
1903
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001904static int trace__vfs_getname(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04001905 union perf_event *event __maybe_unused,
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001906 struct perf_sample *sample)
1907{
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001908 struct thread *thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
1909 struct thread_trace *ttrace;
1910 size_t filename_len, entry_str_len, to_move;
1911 ssize_t remaining_space;
1912 char *pos;
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03001913 const char *filename = perf_evsel__rawptr(evsel, sample, "pathname");
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001914
1915 if (!thread)
1916 goto out;
1917
1918 ttrace = thread__priv(thread);
1919 if (!ttrace)
1920 goto out;
1921
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03001922 filename_len = strlen(filename);
1923
1924 if (ttrace->filename.namelen < filename_len) {
1925 char *f = realloc(ttrace->filename.name, filename_len + 1);
1926
1927 if (f == NULL)
1928 goto out;
1929
1930 ttrace->filename.namelen = filename_len;
1931 ttrace->filename.name = f;
1932 }
1933
1934 strcpy(ttrace->filename.name, filename);
1935 ttrace->filename.pending_open = true;
1936
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001937 if (!ttrace->filename.ptr)
1938 goto out;
1939
1940 entry_str_len = strlen(ttrace->entry_str);
1941 remaining_space = trace__entry_str_size - entry_str_len - 1; /* \0 */
1942 if (remaining_space <= 0)
1943 goto out;
1944
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001945 if (filename_len > (size_t)remaining_space) {
1946 filename += filename_len - remaining_space;
1947 filename_len = remaining_space;
1948 }
1949
1950 to_move = entry_str_len - ttrace->filename.entry_str_pos + 1; /* \0 */
1951 pos = ttrace->entry_str + ttrace->filename.entry_str_pos;
1952 memmove(pos + filename_len, pos, to_move);
1953 memcpy(pos, filename, filename_len);
1954
1955 ttrace->filename.ptr = 0;
1956 ttrace->filename.entry_str_pos = 0;
1957out:
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001958 return 0;
1959}
1960
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001961static int trace__sched_stat_runtime(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04001962 union perf_event *event __maybe_unused,
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001963 struct perf_sample *sample)
1964{
1965 u64 runtime = perf_evsel__intval(evsel, sample, "runtime");
1966 double runtime_ms = (double)runtime / NSEC_PER_MSEC;
David Ahern8fb598e2013-09-28 13:13:00 -06001967 struct thread *thread = machine__findnew_thread(trace->host,
Adrian Hunter314add62013-08-27 11:23:03 +03001968 sample->pid,
1969 sample->tid);
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001970 struct thread_trace *ttrace = thread__trace(thread, trace->output);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001971
1972 if (ttrace == NULL)
1973 goto out_dump;
1974
1975 ttrace->runtime_ms += runtime_ms;
1976 trace->runtime_ms += runtime_ms;
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001977 thread__put(thread);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001978 return 0;
1979
1980out_dump:
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001981 fprintf(trace->output, "%s: comm=%s,pid=%u,runtime=%" PRIu64 ",vruntime=%" PRIu64 ")\n",
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001982 evsel->name,
1983 perf_evsel__strval(evsel, sample, "comm"),
1984 (pid_t)perf_evsel__intval(evsel, sample, "pid"),
1985 runtime,
1986 perf_evsel__intval(evsel, sample, "vruntime"));
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001987 thread__put(thread);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001988 return 0;
1989}
1990
Wang Nan1d6c9402016-02-26 09:31:55 +00001991static void bpf_output__printer(enum binary_printer_ops op,
1992 unsigned int val, void *extra)
1993{
1994 FILE *output = extra;
1995 unsigned char ch = (unsigned char)val;
1996
1997 switch (op) {
1998 case BINARY_PRINT_CHAR_DATA:
1999 fprintf(output, "%c", isprint(ch) ? ch : '.');
2000 break;
2001 case BINARY_PRINT_DATA_BEGIN:
2002 case BINARY_PRINT_LINE_BEGIN:
2003 case BINARY_PRINT_ADDR:
2004 case BINARY_PRINT_NUM_DATA:
2005 case BINARY_PRINT_NUM_PAD:
2006 case BINARY_PRINT_SEP:
2007 case BINARY_PRINT_CHAR_PAD:
2008 case BINARY_PRINT_LINE_END:
2009 case BINARY_PRINT_DATA_END:
2010 default:
2011 break;
2012 }
2013}
2014
2015static void bpf_output__fprintf(struct trace *trace,
2016 struct perf_sample *sample)
2017{
2018 print_binary(sample->raw_data, sample->raw_size, 8,
2019 bpf_output__printer, trace->output);
2020}
2021
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002022static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
2023 union perf_event *event __maybe_unused,
2024 struct perf_sample *sample)
2025{
Arnaldo Carvalho de Melo7ad35612016-04-20 19:55:48 -03002026 int callchain_ret = 0;
2027
2028 if (sample->callchain) {
2029 callchain_ret = trace__resolve_callchain(trace, evsel, sample, &callchain_cursor);
2030 if (callchain_ret == 0) {
2031 if (callchain_cursor.nr < trace->min_stack)
2032 goto out;
2033 callchain_ret = 1;
2034 }
2035 }
2036
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002037 trace__printf_interrupted_entry(trace, sample);
2038 trace__fprintf_tstamp(trace, sample->time, trace->output);
Arnaldo Carvalho de Melo08089212015-02-19 21:51:50 -08002039
2040 if (trace->trace_syscalls)
2041 fprintf(trace->output, "( ): ");
2042
2043 fprintf(trace->output, "%s:", evsel->name);
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002044
Wang Nan1d6c9402016-02-26 09:31:55 +00002045 if (perf_evsel__is_bpf_output(evsel)) {
2046 bpf_output__fprintf(trace, sample);
2047 } else if (evsel->tp_format) {
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002048 event_format__fprintf(evsel->tp_format, sample->cpu,
2049 sample->raw_data, sample->raw_size,
2050 trace->output);
2051 }
2052
2053 fprintf(trace->output, ")\n");
Arnaldo Carvalho de Melo202ff962016-04-12 10:11:07 -03002054
Arnaldo Carvalho de Melo7ad35612016-04-20 19:55:48 -03002055 if (callchain_ret > 0)
2056 trace__fprintf_callchain(trace, sample);
2057 else if (callchain_ret < 0)
2058 pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel));
2059out:
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002060 return 0;
2061}
2062
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002063static void print_location(FILE *f, struct perf_sample *sample,
2064 struct addr_location *al,
2065 bool print_dso, bool print_sym)
2066{
2067
2068 if ((verbose || print_dso) && al->map)
2069 fprintf(f, "%s@", al->map->dso->long_name);
2070
2071 if ((verbose || print_sym) && al->sym)
Arnaldo Carvalho de Melo4414a3c2014-07-08 15:39:21 -03002072 fprintf(f, "%s+0x%" PRIx64, al->sym->name,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002073 al->addr - al->sym->start);
2074 else if (al->map)
Arnaldo Carvalho de Melo4414a3c2014-07-08 15:39:21 -03002075 fprintf(f, "0x%" PRIx64, al->addr);
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002076 else
Arnaldo Carvalho de Melo4414a3c2014-07-08 15:39:21 -03002077 fprintf(f, "0x%" PRIx64, sample->addr);
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002078}
2079
2080static int trace__pgfault(struct trace *trace,
2081 struct perf_evsel *evsel,
Arnaldo Carvalho de Melo473398a2016-03-22 18:23:43 -03002082 union perf_event *event __maybe_unused,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002083 struct perf_sample *sample)
2084{
2085 struct thread *thread;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002086 struct addr_location al;
2087 char map_type = 'd';
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04002088 struct thread_trace *ttrace;
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002089 int err = -1;
Arnaldo Carvalho de Melo1df54292016-04-20 20:06:02 -03002090 int callchain_ret = 0;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002091
2092 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
Arnaldo Carvalho de Melo1df54292016-04-20 20:06:02 -03002093
2094 if (sample->callchain) {
2095 callchain_ret = trace__resolve_callchain(trace, evsel, sample, &callchain_cursor);
2096 if (callchain_ret == 0) {
2097 if (callchain_cursor.nr < trace->min_stack)
2098 goto out_put;
2099 callchain_ret = 1;
2100 }
2101 }
2102
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04002103 ttrace = thread__trace(thread, trace->output);
2104 if (ttrace == NULL)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002105 goto out_put;
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04002106
2107 if (evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ)
2108 ttrace->pfmaj++;
2109 else
2110 ttrace->pfmin++;
2111
2112 if (trace->summary_only)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002113 goto out;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002114
Arnaldo Carvalho de Melo473398a2016-03-22 18:23:43 -03002115 thread__find_addr_location(thread, sample->cpumode, MAP__FUNCTION,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002116 sample->ip, &al);
2117
2118 trace__fprintf_entry_head(trace, thread, 0, sample->time, trace->output);
2119
2120 fprintf(trace->output, "%sfault [",
2121 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ?
2122 "maj" : "min");
2123
2124 print_location(trace->output, sample, &al, false, true);
2125
2126 fprintf(trace->output, "] => ");
2127
Arnaldo Carvalho de Melo473398a2016-03-22 18:23:43 -03002128 thread__find_addr_location(thread, sample->cpumode, MAP__VARIABLE,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002129 sample->addr, &al);
2130
2131 if (!al.map) {
Arnaldo Carvalho de Melo473398a2016-03-22 18:23:43 -03002132 thread__find_addr_location(thread, sample->cpumode,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002133 MAP__FUNCTION, sample->addr, &al);
2134
2135 if (al.map)
2136 map_type = 'x';
2137 else
2138 map_type = '?';
2139 }
2140
2141 print_location(trace->output, sample, &al, true, false);
2142
2143 fprintf(trace->output, " (%c%c)\n", map_type, al.level);
Arnaldo Carvalho de Melo0c3a6ef2016-04-19 16:31:12 -03002144
Arnaldo Carvalho de Melo1df54292016-04-20 20:06:02 -03002145 if (callchain_ret > 0)
2146 trace__fprintf_callchain(trace, sample);
2147 else if (callchain_ret < 0)
2148 pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel));
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002149out:
2150 err = 0;
2151out_put:
2152 thread__put(thread);
2153 return err;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002154}
2155
David Ahernbdc89662013-08-28 22:29:53 -06002156static bool skip_sample(struct trace *trace, struct perf_sample *sample)
2157{
2158 if ((trace->pid_list && intlist__find(trace->pid_list, sample->pid)) ||
2159 (trace->tid_list && intlist__find(trace->tid_list, sample->tid)))
2160 return false;
2161
2162 if (trace->pid_list || trace->tid_list)
2163 return true;
2164
2165 return false;
2166}
2167
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03002168static void trace__set_base_time(struct trace *trace,
Arnaldo Carvalho de Melo8a07a802016-03-31 15:19:39 -03002169 struct perf_evsel *evsel,
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03002170 struct perf_sample *sample)
2171{
Arnaldo Carvalho de Melo8a07a802016-03-31 15:19:39 -03002172 /*
2173 * BPF events were not setting PERF_SAMPLE_TIME, so be more robust
2174 * and don't use sample->time unconditionally, we may end up having
2175 * some other event in the future without PERF_SAMPLE_TIME for good
2176 * reason, i.e. we may not be interested in its timestamps, just in
2177 * it taking place, picking some piece of information when it
2178 * appears in our event stream (vfs_getname comes to mind).
2179 */
2180 if (trace->base_time == 0 && !trace->full_time &&
2181 (evsel->attr.sample_type & PERF_SAMPLE_TIME))
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03002182 trace->base_time = sample->time;
2183}
2184
David Ahern6810fc92013-08-28 22:29:52 -06002185static int trace__process_sample(struct perf_tool *tool,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04002186 union perf_event *event,
David Ahern6810fc92013-08-28 22:29:52 -06002187 struct perf_sample *sample,
2188 struct perf_evsel *evsel,
2189 struct machine *machine __maybe_unused)
2190{
2191 struct trace *trace = container_of(tool, struct trace, tool);
2192 int err = 0;
2193
Arnaldo Carvalho de Melo744a9712013-11-06 10:17:38 -03002194 tracepoint_handler handler = evsel->handler;
David Ahern6810fc92013-08-28 22:29:52 -06002195
David Ahernbdc89662013-08-28 22:29:53 -06002196 if (skip_sample(trace, sample))
2197 return 0;
2198
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03002199 trace__set_base_time(trace, evsel, sample);
David Ahern6810fc92013-08-28 22:29:52 -06002200
David Ahern31605652013-12-04 19:41:41 -07002201 if (handler) {
2202 ++trace->nr_events;
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04002203 handler(trace, evsel, event, sample);
David Ahern31605652013-12-04 19:41:41 -07002204 }
David Ahern6810fc92013-08-28 22:29:52 -06002205
2206 return err;
2207}
2208
David Ahernbdc89662013-08-28 22:29:53 -06002209static int parse_target_str(struct trace *trace)
2210{
2211 if (trace->opts.target.pid) {
2212 trace->pid_list = intlist__new(trace->opts.target.pid);
2213 if (trace->pid_list == NULL) {
2214 pr_err("Error parsing process id string\n");
2215 return -EINVAL;
2216 }
2217 }
2218
2219 if (trace->opts.target.tid) {
2220 trace->tid_list = intlist__new(trace->opts.target.tid);
2221 if (trace->tid_list == NULL) {
2222 pr_err("Error parsing thread id string\n");
2223 return -EINVAL;
2224 }
2225 }
2226
2227 return 0;
2228}
2229
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002230static int trace__record(struct trace *trace, int argc, const char **argv)
David Ahern5e2485b2013-09-28 13:13:01 -06002231{
2232 unsigned int rec_argc, i, j;
2233 const char **rec_argv;
2234 const char * const record_args[] = {
2235 "record",
2236 "-R",
2237 "-m", "1024",
2238 "-c", "1",
David Ahern5e2485b2013-09-28 13:13:01 -06002239 };
2240
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002241 const char * const sc_args[] = { "-e", };
2242 unsigned int sc_args_nr = ARRAY_SIZE(sc_args);
2243 const char * const majpf_args[] = { "-e", "major-faults" };
2244 unsigned int majpf_args_nr = ARRAY_SIZE(majpf_args);
2245 const char * const minpf_args[] = { "-e", "minor-faults" };
2246 unsigned int minpf_args_nr = ARRAY_SIZE(minpf_args);
2247
David Ahern9aca7f12013-12-04 19:41:39 -07002248 /* +1 is for the event string below */
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002249 rec_argc = ARRAY_SIZE(record_args) + sc_args_nr + 1 +
2250 majpf_args_nr + minpf_args_nr + argc;
David Ahern5e2485b2013-09-28 13:13:01 -06002251 rec_argv = calloc(rec_argc + 1, sizeof(char *));
2252
2253 if (rec_argv == NULL)
2254 return -ENOMEM;
2255
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002256 j = 0;
David Ahern5e2485b2013-09-28 13:13:01 -06002257 for (i = 0; i < ARRAY_SIZE(record_args); i++)
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002258 rec_argv[j++] = record_args[i];
2259
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002260 if (trace->trace_syscalls) {
2261 for (i = 0; i < sc_args_nr; i++)
2262 rec_argv[j++] = sc_args[i];
David Ahern5e2485b2013-09-28 13:13:01 -06002263
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002264 /* event string may be different for older kernels - e.g., RHEL6 */
2265 if (is_valid_tracepoint("raw_syscalls:sys_enter"))
2266 rec_argv[j++] = "raw_syscalls:sys_enter,raw_syscalls:sys_exit";
2267 else if (is_valid_tracepoint("syscalls:sys_enter"))
2268 rec_argv[j++] = "syscalls:sys_enter,syscalls:sys_exit";
2269 else {
2270 pr_err("Neither raw_syscalls nor syscalls events exist.\n");
2271 return -1;
2272 }
David Ahern9aca7f12013-12-04 19:41:39 -07002273 }
David Ahern9aca7f12013-12-04 19:41:39 -07002274
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002275 if (trace->trace_pgfaults & TRACE_PFMAJ)
2276 for (i = 0; i < majpf_args_nr; i++)
2277 rec_argv[j++] = majpf_args[i];
David Ahern5e2485b2013-09-28 13:13:01 -06002278
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002279 if (trace->trace_pgfaults & TRACE_PFMIN)
2280 for (i = 0; i < minpf_args_nr; i++)
2281 rec_argv[j++] = minpf_args[i];
2282
2283 for (i = 0; i < (unsigned int)argc; i++)
2284 rec_argv[j++] = argv[i];
2285
2286 return cmd_record(j, rec_argv, NULL);
David Ahern5e2485b2013-09-28 13:13:01 -06002287}
2288
David Ahernbf2575c2013-10-08 21:26:53 -06002289static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp);
2290
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002291static bool perf_evlist__add_vfs_getname(struct perf_evlist *evlist)
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002292{
Arnaldo Carvalho de Meloef503832013-11-07 16:41:19 -03002293 struct perf_evsel *evsel = perf_evsel__newtp("probe", "vfs_getname");
Jiri Olsa8dd2a132015-09-07 10:38:06 +02002294
2295 if (IS_ERR(evsel))
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002296 return false;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002297
2298 if (perf_evsel__field(evsel, "pathname") == NULL) {
2299 perf_evsel__delete(evsel);
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002300 return false;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002301 }
2302
Arnaldo Carvalho de Melo744a9712013-11-06 10:17:38 -03002303 evsel->handler = trace__vfs_getname;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002304 perf_evlist__add(evlist, evsel);
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002305 return true;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002306}
2307
Arnaldo Carvalho de Melo0ae537c2016-04-19 16:00:01 -03002308static struct perf_evsel *perf_evsel__new_pgfault(u64 config)
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002309{
2310 struct perf_evsel *evsel;
2311 struct perf_event_attr attr = {
2312 .type = PERF_TYPE_SOFTWARE,
2313 .mmap_data = 1,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002314 };
2315
2316 attr.config = config;
Arnaldo Carvalho de Melo05247982014-07-23 18:15:09 -03002317 attr.sample_period = 1;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002318
2319 event_attr_init(&attr);
2320
2321 evsel = perf_evsel__new(&attr);
Arnaldo Carvalho de Melo0ae537c2016-04-19 16:00:01 -03002322 if (evsel)
2323 evsel->handler = trace__pgfault;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002324
Arnaldo Carvalho de Melo0ae537c2016-04-19 16:00:01 -03002325 return evsel;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002326}
2327
Arnaldo Carvalho de Meloddbb1b12015-02-21 12:10:29 -08002328static void trace__handle_event(struct trace *trace, union perf_event *event, struct perf_sample *sample)
2329{
2330 const u32 type = event->header.type;
2331 struct perf_evsel *evsel;
2332
Arnaldo Carvalho de Meloddbb1b12015-02-21 12:10:29 -08002333 if (type != PERF_RECORD_SAMPLE) {
2334 trace__process_event(trace, trace->host, event, sample);
2335 return;
2336 }
2337
2338 evsel = perf_evlist__id2evsel(trace->evlist, sample->id);
2339 if (evsel == NULL) {
2340 fprintf(trace->output, "Unknown tp ID %" PRIu64 ", skipping...\n", sample->id);
2341 return;
2342 }
2343
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03002344 trace__set_base_time(trace, evsel, sample);
2345
Arnaldo Carvalho de Meloddbb1b12015-02-21 12:10:29 -08002346 if (evsel->attr.type == PERF_TYPE_TRACEPOINT &&
2347 sample->raw_data == NULL) {
2348 fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n",
2349 perf_evsel__name(evsel), sample->tid,
2350 sample->cpu, sample->raw_size);
2351 } else {
2352 tracepoint_handler handler = evsel->handler;
2353 handler(trace, evsel, event, sample);
2354 }
2355}
2356
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03002357static int trace__add_syscall_newtp(struct trace *trace)
2358{
2359 int ret = -1;
2360 struct perf_evlist *evlist = trace->evlist;
2361 struct perf_evsel *sys_enter, *sys_exit;
2362
2363 sys_enter = perf_evsel__syscall_newtp("sys_enter", trace__sys_enter);
2364 if (sys_enter == NULL)
2365 goto out;
2366
2367 if (perf_evsel__init_sc_tp_ptr_field(sys_enter, args))
2368 goto out_delete_sys_enter;
2369
2370 sys_exit = perf_evsel__syscall_newtp("sys_exit", trace__sys_exit);
2371 if (sys_exit == NULL)
2372 goto out_delete_sys_enter;
2373
2374 if (perf_evsel__init_sc_tp_uint_field(sys_exit, ret))
2375 goto out_delete_sys_exit;
2376
2377 perf_evlist__add(evlist, sys_enter);
2378 perf_evlist__add(evlist, sys_exit);
2379
Arnaldo Carvalho de Melo2ddd5c02016-04-18 12:09:08 -03002380 if (callchain_param.enabled && !trace->kernel_syscallchains) {
Arnaldo Carvalho de Melo44621812016-04-11 15:49:11 -03002381 /*
2382 * We're interested only in the user space callchain
2383 * leading to the syscall, allow overriding that for
2384 * debugging reasons using --kernel_syscall_callchains
2385 */
2386 sys_exit->attr.exclude_callchain_kernel = 1;
2387 }
2388
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03002389 trace->syscalls.events.sys_enter = sys_enter;
2390 trace->syscalls.events.sys_exit = sys_exit;
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03002391
2392 ret = 0;
2393out:
2394 return ret;
2395
2396out_delete_sys_exit:
2397 perf_evsel__delete_priv(sys_exit);
2398out_delete_sys_enter:
2399 perf_evsel__delete_priv(sys_enter);
2400 goto out;
2401}
2402
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002403static int trace__set_ev_qualifier_filter(struct trace *trace)
2404{
2405 int err = -1;
2406 char *filter = asprintf_expr_inout_ints("id", !trace->not_ev_qualifier,
2407 trace->ev_qualifier_ids.nr,
2408 trace->ev_qualifier_ids.entries);
2409
2410 if (filter == NULL)
2411 goto out_enomem;
2412
2413 if (!perf_evsel__append_filter(trace->syscalls.events.sys_enter, "&&", filter))
2414 err = perf_evsel__append_filter(trace->syscalls.events.sys_exit, "&&", filter);
2415
2416 free(filter);
2417out:
2418 return err;
2419out_enomem:
2420 errno = ENOMEM;
2421 goto out;
2422}
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03002423
Namhyung Kimf15eb532012-10-05 14:02:16 +09002424static int trace__run(struct trace *trace, int argc, const char **argv)
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002425{
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002426 struct perf_evlist *evlist = trace->evlist;
Arnaldo Carvalho de Melo0ae537c2016-04-19 16:00:01 -03002427 struct perf_evsel *evsel, *pgfault_maj = NULL, *pgfault_min = NULL;
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03002428 int err = -1, i;
2429 unsigned long before;
Namhyung Kimf15eb532012-10-05 14:02:16 +09002430 const bool forks = argc > 0;
Arnaldo Carvalho de Melo46fb3c22014-09-22 14:39:48 -03002431 bool draining = false;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002432
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03002433 trace->live = true;
2434
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03002435 if (trace->trace_syscalls && trace__add_syscall_newtp(trace))
Arnaldo Carvalho de Melo801c67b2015-01-22 10:52:55 -03002436 goto out_error_raw_syscalls;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002437
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002438 if (trace->trace_syscalls)
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002439 trace->vfs_getname = perf_evlist__add_vfs_getname(evlist);
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002440
Arnaldo Carvalho de Melo0ae537c2016-04-19 16:00:01 -03002441 if ((trace->trace_pgfaults & TRACE_PFMAJ)) {
2442 pgfault_maj = perf_evsel__new_pgfault(PERF_COUNT_SW_PAGE_FAULTS_MAJ);
2443 if (pgfault_maj == NULL)
2444 goto out_error_mem;
2445 perf_evlist__add(evlist, pgfault_maj);
Arnaldo Carvalho de Meloe2726d92015-01-22 10:34:22 -03002446 }
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002447
Arnaldo Carvalho de Melo0ae537c2016-04-19 16:00:01 -03002448 if ((trace->trace_pgfaults & TRACE_PFMIN)) {
2449 pgfault_min = perf_evsel__new_pgfault(PERF_COUNT_SW_PAGE_FAULTS_MIN);
2450 if (pgfault_min == NULL)
2451 goto out_error_mem;
2452 perf_evlist__add(evlist, pgfault_min);
2453 }
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002454
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002455 if (trace->sched &&
Arnaldo Carvalho de Melo2cc990b2015-01-22 11:13:43 -03002456 perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime",
2457 trace__sched_stat_runtime))
2458 goto out_error_sched_stat_runtime;
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002459
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002460 err = perf_evlist__create_maps(evlist, &trace->opts.target);
2461 if (err < 0) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002462 fprintf(trace->output, "Problems parsing the target to trace, check your options!\n");
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002463 goto out_delete_evlist;
2464 }
2465
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03002466 err = trace__symbols_init(trace, evlist);
2467 if (err < 0) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002468 fprintf(trace->output, "Problems initializing symbol libraries!\n");
Arnaldo Carvalho de Melo03ad9742014-01-03 15:56:06 -03002469 goto out_delete_evlist;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03002470 }
2471
Arnaldo Carvalho de Melofde54b72016-04-11 18:42:37 -03002472 perf_evlist__config(evlist, &trace->opts, NULL);
2473
Arnaldo Carvalho de Melo0c3a6ef2016-04-19 16:31:12 -03002474 if (callchain_param.enabled) {
2475 bool use_identifier = false;
2476
2477 if (trace->syscalls.events.sys_exit) {
2478 perf_evsel__config_callchain(trace->syscalls.events.sys_exit,
2479 &trace->opts, &callchain_param);
2480 use_identifier = true;
2481 }
2482
2483 if (pgfault_maj) {
2484 perf_evsel__config_callchain(pgfault_maj, &trace->opts, &callchain_param);
2485 use_identifier = true;
2486 }
2487
2488 if (pgfault_min) {
2489 perf_evsel__config_callchain(pgfault_min, &trace->opts, &callchain_param);
2490 use_identifier = true;
2491 }
2492
2493 if (use_identifier) {
2494 /*
2495 * Now we have evsels with different sample_ids, use
2496 * PERF_SAMPLE_IDENTIFIER to map from sample to evsel
2497 * from a fixed position in each ring buffer record.
2498 *
2499 * As of this the changeset introducing this comment, this
2500 * isn't strictly needed, as the fields that can come before
2501 * PERF_SAMPLE_ID are all used, but we'll probably disable
2502 * some of those for things like copying the payload of
2503 * pointer syscall arguments, and for vfs_getname we don't
2504 * need PERF_SAMPLE_ADDR and PERF_SAMPLE_IP, so do this
2505 * here as a warning we need to use PERF_SAMPLE_IDENTIFIER.
2506 */
2507 perf_evlist__set_sample_bit(evlist, IDENTIFIER);
2508 perf_evlist__reset_sample_bit(evlist, ID);
2509 }
Arnaldo Carvalho de Melofde54b72016-04-11 18:42:37 -03002510 }
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002511
Namhyung Kimf15eb532012-10-05 14:02:16 +09002512 signal(SIGCHLD, sig_handler);
2513 signal(SIGINT, sig_handler);
2514
2515 if (forks) {
Namhyung Kim6ef73ec2013-03-11 16:43:15 +09002516 err = perf_evlist__prepare_workload(evlist, &trace->opts.target,
Arnaldo Carvalho de Melo735f7e02014-01-03 14:56:49 -03002517 argv, false, NULL);
Namhyung Kimf15eb532012-10-05 14:02:16 +09002518 if (err < 0) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002519 fprintf(trace->output, "Couldn't run the workload!\n");
Arnaldo Carvalho de Melo03ad9742014-01-03 15:56:06 -03002520 goto out_delete_evlist;
Namhyung Kimf15eb532012-10-05 14:02:16 +09002521 }
2522 }
2523
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002524 err = perf_evlist__open(evlist);
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002525 if (err < 0)
2526 goto out_error_open;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002527
Wang Nanba504232016-02-26 09:31:54 +00002528 err = bpf__apply_obj_config();
2529 if (err) {
2530 char errbuf[BUFSIZ];
2531
2532 bpf__strerror_apply_obj_config(err, errbuf, sizeof(errbuf));
2533 pr_err("ERROR: Apply config to BPF failed: %s\n",
2534 errbuf);
2535 goto out_error_open;
2536 }
2537
Arnaldo Carvalho de Melo241b0572015-02-21 10:15:21 -08002538 /*
2539 * Better not use !target__has_task() here because we need to cover the
2540 * case where no threads were specified in the command line, but a
2541 * workload was, and in that case we will fill in the thread_map when
2542 * we fork the workload in perf_evlist__prepare_workload.
2543 */
Arnaldo Carvalho de Melof078c382015-02-21 11:36:52 -08002544 if (trace->filter_pids.nr > 0)
2545 err = perf_evlist__set_filter_pids(evlist, trace->filter_pids.nr, trace->filter_pids.entries);
Jiri Olsae13798c2015-06-23 00:36:02 +02002546 else if (thread_map__pid(evlist->threads, 0) == -1)
Arnaldo Carvalho de Melof078c382015-02-21 11:36:52 -08002547 err = perf_evlist__set_filter_pid(evlist, getpid());
2548
Arnaldo Carvalho de Melo94ad89b2015-07-03 17:42:03 -03002549 if (err < 0)
2550 goto out_error_mem;
2551
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002552 if (trace->ev_qualifier_ids.nr > 0) {
2553 err = trace__set_ev_qualifier_filter(trace);
2554 if (err < 0)
2555 goto out_errno;
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002556
Arnaldo Carvalho de Melo2e5e5f82015-08-03 17:12:29 -03002557 pr_debug("event qualifier tracepoint filter: %s\n",
2558 trace->syscalls.events.sys_exit->filter);
2559 }
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002560
Arnaldo Carvalho de Melo94ad89b2015-07-03 17:42:03 -03002561 err = perf_evlist__apply_filters(evlist, &evsel);
2562 if (err < 0)
2563 goto out_error_apply_filters;
Arnaldo Carvalho de Melo241b0572015-02-21 10:15:21 -08002564
Jiri Olsaf8850372013-11-28 17:57:22 +01002565 err = perf_evlist__mmap(evlist, trace->opts.mmap_pages, false);
Arnaldo Carvalho de Meloe09b18d2014-12-11 18:04:10 -03002566 if (err < 0)
2567 goto out_error_mmap;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002568
Arnaldo Carvalho de Melocb24d012015-04-22 10:04:23 -03002569 if (!target__none(&trace->opts.target))
2570 perf_evlist__enable(evlist);
2571
Namhyung Kimf15eb532012-10-05 14:02:16 +09002572 if (forks)
2573 perf_evlist__start_workload(evlist);
2574
Jiri Olsae13798c2015-06-23 00:36:02 +02002575 trace->multiple_threads = thread_map__pid(evlist->threads, 0) == -1 ||
Arnaldo Carvalho de Melo42052be2015-02-13 12:32:45 -03002576 evlist->threads->nr > 1 ||
2577 perf_evlist__first(evlist)->attr.inherit;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002578again:
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03002579 before = trace->nr_events;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002580
2581 for (i = 0; i < evlist->nr_mmaps; i++) {
2582 union perf_event *event;
2583
2584 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002585 struct perf_sample sample;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002586
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03002587 ++trace->nr_events;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002588
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002589 err = perf_evlist__parse_sample(evlist, event, &sample);
2590 if (err) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002591 fprintf(trace->output, "Can't parse sample, err = %d, skipping...\n", err);
Zhouyi Zhou8e50d382013-10-24 15:43:33 +08002592 goto next_event;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002593 }
2594
Arnaldo Carvalho de Meloddbb1b12015-02-21 12:10:29 -08002595 trace__handle_event(trace, event, &sample);
Zhouyi Zhou8e50d382013-10-24 15:43:33 +08002596next_event:
2597 perf_evlist__mmap_consume(evlist, i);
Arnaldo Carvalho de Melo20c5f102013-09-03 11:55:07 -03002598
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002599 if (interrupted)
2600 goto out_disable;
Arnaldo Carvalho de Melo02ac5422015-04-22 11:11:57 -03002601
2602 if (done && !draining) {
2603 perf_evlist__disable(evlist);
2604 draining = true;
2605 }
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002606 }
2607 }
2608
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03002609 if (trace->nr_events == before) {
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002610 int timeout = done ? 100 : -1;
Namhyung Kimf15eb532012-10-05 14:02:16 +09002611
Arnaldo Carvalho de Melo46fb3c22014-09-22 14:39:48 -03002612 if (!draining && perf_evlist__poll(evlist, timeout) > 0) {
2613 if (perf_evlist__filter_pollfd(evlist, POLLERR | POLLHUP) == 0)
2614 draining = true;
2615
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002616 goto again;
Arnaldo Carvalho de Melo46fb3c22014-09-22 14:39:48 -03002617 }
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002618 } else {
2619 goto again;
Namhyung Kimf15eb532012-10-05 14:02:16 +09002620 }
2621
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002622out_disable:
Arnaldo Carvalho de Melof3b623b2015-03-02 22:21:35 -03002623 thread__zput(trace->current);
2624
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002625 perf_evlist__disable(evlist);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002626
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002627 if (!err) {
2628 if (trace->summary)
2629 trace__fprintf_thread_summary(trace, trace->output);
2630
2631 if (trace->show_tool_stats) {
2632 fprintf(trace->output, "Stats:\n "
2633 " vfs_getname : %" PRIu64 "\n"
2634 " proc_getname: %" PRIu64 "\n",
2635 trace->stats.vfs_getname,
2636 trace->stats.proc_getname);
2637 }
2638 }
David Ahernbf2575c2013-10-08 21:26:53 -06002639
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002640out_delete_evlist:
2641 perf_evlist__delete(evlist);
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002642 trace->evlist = NULL;
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03002643 trace->live = false;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002644 return err;
Arnaldo Carvalho de Melo6ef068c2013-10-17 12:07:58 -03002645{
2646 char errbuf[BUFSIZ];
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002647
Arnaldo Carvalho de Melo2cc990b2015-01-22 11:13:43 -03002648out_error_sched_stat_runtime:
Jiri Olsa988bdb32015-09-02 09:56:35 +02002649 tracing_path__strerror_open_tp(errno, errbuf, sizeof(errbuf), "sched", "sched_stat_runtime");
Arnaldo Carvalho de Melo2cc990b2015-01-22 11:13:43 -03002650 goto out_error;
2651
Arnaldo Carvalho de Melo801c67b2015-01-22 10:52:55 -03002652out_error_raw_syscalls:
Jiri Olsa988bdb32015-09-02 09:56:35 +02002653 tracing_path__strerror_open_tp(errno, errbuf, sizeof(errbuf), "raw_syscalls", "sys_(enter|exit)");
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002654 goto out_error;
2655
Arnaldo Carvalho de Meloe09b18d2014-12-11 18:04:10 -03002656out_error_mmap:
2657 perf_evlist__strerror_mmap(evlist, errno, errbuf, sizeof(errbuf));
2658 goto out_error;
2659
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002660out_error_open:
2661 perf_evlist__strerror_open(evlist, errno, errbuf, sizeof(errbuf));
2662
2663out_error:
Arnaldo Carvalho de Melo6ef068c2013-10-17 12:07:58 -03002664 fprintf(trace->output, "%s\n", errbuf);
Ramkumar Ramachandra87f91862013-10-04 10:47:31 +05302665 goto out_delete_evlist;
Arnaldo Carvalho de Melo94ad89b2015-07-03 17:42:03 -03002666
2667out_error_apply_filters:
2668 fprintf(trace->output,
2669 "Failed to set filter \"%s\" on event %s with %d (%s)\n",
2670 evsel->filter, perf_evsel__name(evsel), errno,
2671 strerror_r(errno, errbuf, sizeof(errbuf)));
2672 goto out_delete_evlist;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002673}
Arnaldo Carvalho de Melo5ed08da2015-01-22 11:08:04 -03002674out_error_mem:
2675 fprintf(trace->output, "Not enough memory to run!\n");
2676 goto out_delete_evlist;
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002677
2678out_errno:
2679 fprintf(trace->output, "errno=%d,%s\n", errno, strerror(errno));
2680 goto out_delete_evlist;
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002681}
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002682
David Ahern6810fc92013-08-28 22:29:52 -06002683static int trace__replay(struct trace *trace)
2684{
2685 const struct perf_evsel_str_handler handlers[] = {
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002686 { "probe:vfs_getname", trace__vfs_getname, },
David Ahern6810fc92013-08-28 22:29:52 -06002687 };
Jiri Olsaf5fc14122013-10-15 16:27:32 +02002688 struct perf_data_file file = {
2689 .path = input_name,
2690 .mode = PERF_DATA_MODE_READ,
Yunlong Songe366a6d2015-04-02 21:47:18 +08002691 .force = trace->force,
Jiri Olsaf5fc14122013-10-15 16:27:32 +02002692 };
David Ahern6810fc92013-08-28 22:29:52 -06002693 struct perf_session *session;
Namhyung Kim003824e2013-11-12 15:25:00 +09002694 struct perf_evsel *evsel;
David Ahern6810fc92013-08-28 22:29:52 -06002695 int err = -1;
2696
2697 trace->tool.sample = trace__process_sample;
2698 trace->tool.mmap = perf_event__process_mmap;
David Ahern384c6712013-09-22 19:44:58 -06002699 trace->tool.mmap2 = perf_event__process_mmap2;
David Ahern6810fc92013-08-28 22:29:52 -06002700 trace->tool.comm = perf_event__process_comm;
2701 trace->tool.exit = perf_event__process_exit;
2702 trace->tool.fork = perf_event__process_fork;
2703 trace->tool.attr = perf_event__process_attr;
2704 trace->tool.tracing_data = perf_event__process_tracing_data;
2705 trace->tool.build_id = perf_event__process_build_id;
2706
Jiri Olsa0a8cb852014-07-06 14:18:21 +02002707 trace->tool.ordered_events = true;
David Ahern6810fc92013-08-28 22:29:52 -06002708 trace->tool.ordering_requires_timestamps = true;
2709
2710 /* add tid to output */
2711 trace->multiple_threads = true;
2712
Jiri Olsaf5fc14122013-10-15 16:27:32 +02002713 session = perf_session__new(&file, false, &trace->tool);
David Ahern6810fc92013-08-28 22:29:52 -06002714 if (session == NULL)
Taeung Song52e028342014-09-24 10:33:37 +09002715 return -1;
David Ahern6810fc92013-08-28 22:29:52 -06002716
Namhyung Kim0a7e6d12014-08-12 15:40:45 +09002717 if (symbol__init(&session->header.env) < 0)
Namhyung Kimcb2ffae2014-08-12 15:40:44 +09002718 goto out;
2719
David Ahern8fb598e2013-09-28 13:13:00 -06002720 trace->host = &session->machines.host;
2721
David Ahern6810fc92013-08-28 22:29:52 -06002722 err = perf_session__set_tracepoints_handlers(session, handlers);
2723 if (err)
2724 goto out;
2725
Namhyung Kim003824e2013-11-12 15:25:00 +09002726 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2727 "raw_syscalls:sys_enter");
David Ahern9aca7f12013-12-04 19:41:39 -07002728 /* older kernels have syscalls tp versus raw_syscalls */
2729 if (evsel == NULL)
2730 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2731 "syscalls:sys_enter");
David Ahern6810fc92013-08-28 22:29:52 -06002732
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002733 if (evsel &&
2734 (perf_evsel__init_syscall_tp(evsel, trace__sys_enter) < 0 ||
2735 perf_evsel__init_sc_tp_ptr_field(evsel, args))) {
Namhyung Kim003824e2013-11-12 15:25:00 +09002736 pr_err("Error during initialize raw_syscalls:sys_enter event\n");
2737 goto out;
2738 }
2739
2740 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2741 "raw_syscalls:sys_exit");
David Ahern9aca7f12013-12-04 19:41:39 -07002742 if (evsel == NULL)
2743 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2744 "syscalls:sys_exit");
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002745 if (evsel &&
2746 (perf_evsel__init_syscall_tp(evsel, trace__sys_exit) < 0 ||
2747 perf_evsel__init_sc_tp_uint_field(evsel, ret))) {
Namhyung Kim003824e2013-11-12 15:25:00 +09002748 pr_err("Error during initialize raw_syscalls:sys_exit event\n");
David Ahern6810fc92013-08-28 22:29:52 -06002749 goto out;
2750 }
2751
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002752 evlist__for_each(session->evlist, evsel) {
2753 if (evsel->attr.type == PERF_TYPE_SOFTWARE &&
2754 (evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ||
2755 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MIN ||
2756 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS))
2757 evsel->handler = trace__pgfault;
2758 }
2759
David Ahernbdc89662013-08-28 22:29:53 -06002760 err = parse_target_str(trace);
2761 if (err != 0)
2762 goto out;
2763
David Ahern6810fc92013-08-28 22:29:52 -06002764 setup_pager();
2765
Arnaldo Carvalho de Melob7b61cb2015-03-03 11:58:45 -03002766 err = perf_session__process_events(session);
David Ahern6810fc92013-08-28 22:29:52 -06002767 if (err)
2768 pr_err("Failed to process events, error %d", err);
2769
David Ahernbf2575c2013-10-08 21:26:53 -06002770 else if (trace->summary)
2771 trace__fprintf_thread_summary(trace, trace->output);
2772
David Ahern6810fc92013-08-28 22:29:52 -06002773out:
2774 perf_session__delete(session);
2775
2776 return err;
2777}
2778
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002779static size_t trace__fprintf_threads_header(FILE *fp)
2780{
2781 size_t printed;
2782
Pekka Enberg99ff7152013-11-12 16:42:14 +02002783 printed = fprintf(fp, "\n Summary of events:\n\n");
David Ahernbf2575c2013-10-08 21:26:53 -06002784
2785 return printed;
2786}
2787
Arnaldo Carvalho de Melob535d522016-05-04 16:06:26 -03002788DEFINE_RESORT_RB(syscall_stats, a->msecs > b->msecs,
2789 struct stats *stats;
2790 double msecs;
2791 int syscall;
2792)
2793{
2794 struct int_node *source = rb_entry(nd, struct int_node, rb_node);
2795 struct stats *stats = source->priv;
2796
2797 entry->syscall = source->i;
2798 entry->stats = stats;
2799 entry->msecs = stats ? (u64)stats->n * (avg_stats(stats) / NSEC_PER_MSEC) : 0;
2800}
2801
David Ahernbf2575c2013-10-08 21:26:53 -06002802static size_t thread__dump_stats(struct thread_trace *ttrace,
2803 struct trace *trace, FILE *fp)
2804{
David Ahernbf2575c2013-10-08 21:26:53 -06002805 size_t printed = 0;
2806 struct syscall *sc;
Arnaldo Carvalho de Melob535d522016-05-04 16:06:26 -03002807 struct rb_node *nd;
2808 DECLARE_RESORT_RB_INTLIST(syscall_stats, ttrace->syscall_stats);
David Ahernbf2575c2013-10-08 21:26:53 -06002809
Arnaldo Carvalho de Melob535d522016-05-04 16:06:26 -03002810 if (syscall_stats == NULL)
David Ahernbf2575c2013-10-08 21:26:53 -06002811 return 0;
2812
2813 printed += fprintf(fp, "\n");
2814
Milian Wolff834fd462015-08-06 11:24:29 +02002815 printed += fprintf(fp, " syscall calls total min avg max stddev\n");
2816 printed += fprintf(fp, " (msec) (msec) (msec) (msec) (%%)\n");
2817 printed += fprintf(fp, " --------------- -------- --------- --------- --------- --------- ------\n");
Pekka Enberg99ff7152013-11-12 16:42:14 +02002818
Arnaldo Carvalho de Melob535d522016-05-04 16:06:26 -03002819 resort_rb__for_each(nd, syscall_stats) {
2820 struct stats *stats = syscall_stats_entry->stats;
David Ahernbf2575c2013-10-08 21:26:53 -06002821 if (stats) {
2822 double min = (double)(stats->min) / NSEC_PER_MSEC;
2823 double max = (double)(stats->max) / NSEC_PER_MSEC;
2824 double avg = avg_stats(stats);
2825 double pct;
2826 u64 n = (u64) stats->n;
2827
2828 pct = avg ? 100.0 * stddev_stats(stats)/avg : 0.0;
2829 avg /= NSEC_PER_MSEC;
2830
Arnaldo Carvalho de Melob535d522016-05-04 16:06:26 -03002831 sc = &trace->syscalls.table[syscall_stats_entry->syscall];
Pekka Enberg99ff7152013-11-12 16:42:14 +02002832 printed += fprintf(fp, " %-15s", sc->name);
Milian Wolff834fd462015-08-06 11:24:29 +02002833 printed += fprintf(fp, " %8" PRIu64 " %9.3f %9.3f %9.3f",
Arnaldo Carvalho de Melob535d522016-05-04 16:06:26 -03002834 n, syscall_stats_entry->msecs, min, avg);
Pekka Enberg27a778b2013-11-13 14:21:48 +02002835 printed += fprintf(fp, " %9.3f %9.2f%%\n", max, pct);
David Ahernbf2575c2013-10-08 21:26:53 -06002836 }
David Ahernbf2575c2013-10-08 21:26:53 -06002837 }
2838
Arnaldo Carvalho de Melob535d522016-05-04 16:06:26 -03002839 resort_rb__delete(syscall_stats);
David Ahernbf2575c2013-10-08 21:26:53 -06002840 printed += fprintf(fp, "\n\n");
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002841
2842 return printed;
2843}
2844
Arnaldo Carvalho de Melo96c14452016-05-04 12:47:16 -03002845static size_t trace__fprintf_thread(FILE *fp, struct thread *thread, struct trace *trace)
David Ahern896cbb52013-09-28 13:12:59 -06002846{
Arnaldo Carvalho de Melo96c14452016-05-04 12:47:16 -03002847 size_t printed = 0;
Namhyung Kim89dceb22014-10-06 09:46:03 +09002848 struct thread_trace *ttrace = thread__priv(thread);
David Ahern896cbb52013-09-28 13:12:59 -06002849 double ratio;
2850
2851 if (ttrace == NULL)
2852 return 0;
2853
2854 ratio = (double)ttrace->nr_events / trace->nr_events * 100.0;
2855
Pekka Enberg15e65c62013-11-14 18:43:30 +02002856 printed += fprintf(fp, " %s (%d), ", thread__comm_str(thread), thread->tid);
Pekka Enberg99ff7152013-11-12 16:42:14 +02002857 printed += fprintf(fp, "%lu events, ", ttrace->nr_events);
Pekka Enberg15e65c62013-11-14 18:43:30 +02002858 printed += fprintf(fp, "%.1f%%", ratio);
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04002859 if (ttrace->pfmaj)
2860 printed += fprintf(fp, ", %lu majfaults", ttrace->pfmaj);
2861 if (ttrace->pfmin)
2862 printed += fprintf(fp, ", %lu minfaults", ttrace->pfmin);
Pekka Enberg99ff7152013-11-12 16:42:14 +02002863 printed += fprintf(fp, ", %.3f msec\n", ttrace->runtime_ms);
David Ahernbf2575c2013-10-08 21:26:53 -06002864 printed += thread__dump_stats(ttrace, trace, fp);
David Ahern896cbb52013-09-28 13:12:59 -06002865
Arnaldo Carvalho de Melo96c14452016-05-04 12:47:16 -03002866 return printed;
2867}
David Ahern896cbb52013-09-28 13:12:59 -06002868
Arnaldo Carvalho de Melo96c14452016-05-04 12:47:16 -03002869static unsigned long thread__nr_events(struct thread_trace *ttrace)
2870{
2871 return ttrace ? ttrace->nr_events : 0;
2872}
2873
2874DEFINE_RESORT_RB(threads, (thread__nr_events(a->thread->priv) < thread__nr_events(b->thread->priv)),
2875 struct thread *thread;
2876)
2877{
2878 entry->thread = rb_entry(nd, struct thread, rb_node);
David Ahern896cbb52013-09-28 13:12:59 -06002879}
2880
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002881static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp)
2882{
Arnaldo Carvalho de Melo96c14452016-05-04 12:47:16 -03002883 DECLARE_RESORT_RB_MACHINE_THREADS(threads, trace->host);
2884 size_t printed = trace__fprintf_threads_header(fp);
2885 struct rb_node *nd;
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002886
Arnaldo Carvalho de Melo96c14452016-05-04 12:47:16 -03002887 if (threads == NULL) {
2888 fprintf(fp, "%s", "Error sorting output by nr_events!\n");
2889 return 0;
2890 }
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002891
Arnaldo Carvalho de Melo96c14452016-05-04 12:47:16 -03002892 resort_rb__for_each(nd, threads)
2893 printed += trace__fprintf_thread(fp, threads_entry->thread, trace);
2894
2895 resort_rb__delete(threads);
2896
2897 return printed;
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002898}
2899
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03002900static int trace__set_duration(const struct option *opt, const char *str,
2901 int unset __maybe_unused)
2902{
2903 struct trace *trace = opt->value;
2904
2905 trace->duration_filter = atof(str);
2906 return 0;
2907}
2908
Arnaldo Carvalho de Melof078c382015-02-21 11:36:52 -08002909static int trace__set_filter_pids(const struct option *opt, const char *str,
2910 int unset __maybe_unused)
2911{
2912 int ret = -1;
2913 size_t i;
2914 struct trace *trace = opt->value;
2915 /*
2916 * FIXME: introduce a intarray class, plain parse csv and create a
2917 * { int nr, int entries[] } struct...
2918 */
2919 struct intlist *list = intlist__new(str);
2920
2921 if (list == NULL)
2922 return -1;
2923
2924 i = trace->filter_pids.nr = intlist__nr_entries(list) + 1;
2925 trace->filter_pids.entries = calloc(i, sizeof(pid_t));
2926
2927 if (trace->filter_pids.entries == NULL)
2928 goto out;
2929
2930 trace->filter_pids.entries[0] = getpid();
2931
2932 for (i = 1; i < trace->filter_pids.nr; ++i)
2933 trace->filter_pids.entries[i] = intlist__entry(list, i - 1)->i;
2934
2935 intlist__delete(list);
2936 ret = 0;
2937out:
2938 return ret;
2939}
2940
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002941static int trace__open_output(struct trace *trace, const char *filename)
2942{
2943 struct stat st;
2944
2945 if (!stat(filename, &st) && st.st_size) {
2946 char oldname[PATH_MAX];
2947
2948 scnprintf(oldname, sizeof(oldname), "%s.old", filename);
2949 unlink(oldname);
2950 rename(filename, oldname);
2951 }
2952
2953 trace->output = fopen(filename, "w");
2954
2955 return trace->output == NULL ? -errno : 0;
2956}
2957
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002958static int parse_pagefaults(const struct option *opt, const char *str,
2959 int unset __maybe_unused)
2960{
2961 int *trace_pgfaults = opt->value;
2962
2963 if (strcmp(str, "all") == 0)
2964 *trace_pgfaults |= TRACE_PFMAJ | TRACE_PFMIN;
2965 else if (strcmp(str, "maj") == 0)
2966 *trace_pgfaults |= TRACE_PFMAJ;
2967 else if (strcmp(str, "min") == 0)
2968 *trace_pgfaults |= TRACE_PFMIN;
2969 else
2970 return -1;
2971
2972 return 0;
2973}
2974
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002975static void evlist__set_evsel_handler(struct perf_evlist *evlist, void *handler)
2976{
2977 struct perf_evsel *evsel;
2978
2979 evlist__for_each(evlist, evsel)
2980 evsel->handler = handler;
2981}
2982
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002983int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
2984{
Yunlong Song6fdd9cb2015-03-18 21:35:57 +08002985 const char *trace_usage[] = {
Namhyung Kimf15eb532012-10-05 14:02:16 +09002986 "perf trace [<options>] [<command>]",
2987 "perf trace [<options>] -- <command> [<options>]",
David Ahern5e2485b2013-09-28 13:13:01 -06002988 "perf trace record [<options>] [<command>]",
2989 "perf trace record [<options>] -- <command> [<options>]",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002990 NULL
2991 };
2992 struct trace trace = {
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002993 .syscalls = {
2994 . max = -1,
2995 },
2996 .opts = {
2997 .target = {
2998 .uid = UINT_MAX,
2999 .uses_mmap = true,
3000 },
3001 .user_freq = UINT_MAX,
3002 .user_interval = ULLONG_MAX,
Arnaldo Carvalho de Melo509051e2014-01-14 17:52:14 -03003003 .no_buffering = true,
Arnaldo Carvalho de Melo38d54472014-12-12 17:28:32 -03003004 .mmap_pages = UINT_MAX,
Kan Liang9d9cad72015-06-17 09:51:11 -04003005 .proc_map_timeout = 500,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003006 },
Milian Wolff007d66a2015-08-05 16:52:23 -03003007 .output = stderr,
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -03003008 .show_comm = true,
Stanislav Fomicheve281a962014-06-26 20:14:28 +04003009 .trace_syscalls = true,
Arnaldo Carvalho de Melo44621812016-04-11 15:49:11 -03003010 .kernel_syscallchains = false,
Arnaldo Carvalho de Melo05614992016-04-15 16:41:19 -03003011 .max_stack = UINT_MAX,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003012 };
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003013 const char *output_name = NULL;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03003014 const char *ev_qualifier_str = NULL;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003015 const struct option trace_options[] = {
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003016 OPT_CALLBACK(0, "event", &trace.evlist, "event",
3017 "event selector. use 'perf list' to list available events",
3018 parse_events_option),
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -03003019 OPT_BOOLEAN(0, "comm", &trace.show_comm,
3020 "show the thread COMM next to its id"),
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03003021 OPT_BOOLEAN(0, "tool_stats", &trace.show_tool_stats, "show tool stats"),
Arnaldo Carvalho de Melod303e852015-04-23 12:02:07 -03003022 OPT_STRING('e', "expr", &ev_qualifier_str, "expr", "list of syscalls to trace"),
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003023 OPT_STRING('o', "output", &output_name, "file", "output file name"),
David Ahern6810fc92013-08-28 22:29:52 -06003024 OPT_STRING('i', "input", &input_name, "file", "Analyze events in file"),
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003025 OPT_STRING('p', "pid", &trace.opts.target.pid, "pid",
3026 "trace events on existing process id"),
David Ahernac9be8e2013-08-20 11:15:45 -06003027 OPT_STRING('t', "tid", &trace.opts.target.tid, "tid",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003028 "trace events on existing thread id"),
Arnaldo Carvalho de Melofa0e4ff2015-04-23 11:59:20 -03003029 OPT_CALLBACK(0, "filter-pids", &trace, "CSV list of pids",
3030 "pids to filter (by the kernel)", trace__set_filter_pids),
David Ahernac9be8e2013-08-20 11:15:45 -06003031 OPT_BOOLEAN('a', "all-cpus", &trace.opts.target.system_wide,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003032 "system-wide collection from all CPUs"),
David Ahernac9be8e2013-08-20 11:15:45 -06003033 OPT_STRING('C', "cpu", &trace.opts.target.cpu_list, "cpu",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003034 "list of cpus to monitor"),
David Ahern6810fc92013-08-28 22:29:52 -06003035 OPT_BOOLEAN(0, "no-inherit", &trace.opts.no_inherit,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003036 "child tasks do not inherit counters"),
Jiri Olsa994a1f72013-09-01 12:36:12 +02003037 OPT_CALLBACK('m', "mmap-pages", &trace.opts.mmap_pages, "pages",
3038 "number of mmap data pages",
3039 perf_evlist__parse_mmap_pages),
David Ahernac9be8e2013-08-20 11:15:45 -06003040 OPT_STRING('u', "uid", &trace.opts.target.uid_str, "user",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003041 "user to profile"),
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03003042 OPT_CALLBACK(0, "duration", &trace, "float",
3043 "show only events with duration > N.M ms",
3044 trace__set_duration),
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03003045 OPT_BOOLEAN(0, "sched", &trace.sched, "show blocking scheduler events"),
Arnaldo Carvalho de Melo7c304ee02013-08-22 16:49:54 -03003046 OPT_INCR('v', "verbose", &verbose, "be more verbose"),
David Ahern4bb09192013-09-04 12:37:43 -06003047 OPT_BOOLEAN('T', "time", &trace.full_time,
3048 "Show full timestamp, not time relative to first start"),
David Ahernfd2eaba2013-11-12 09:31:15 -07003049 OPT_BOOLEAN('s', "summary", &trace.summary_only,
3050 "Show only syscall summary with statistics"),
3051 OPT_BOOLEAN('S', "with-summary", &trace.summary,
3052 "Show all syscalls and summary with statistics"),
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04003053 OPT_CALLBACK_DEFAULT('F', "pf", &trace.trace_pgfaults, "all|maj|min",
3054 "Trace pagefaults", parse_pagefaults, "maj"),
Stanislav Fomicheve281a962014-06-26 20:14:28 +04003055 OPT_BOOLEAN(0, "syscalls", &trace.trace_syscalls, "Trace syscalls"),
Yunlong Songe366a6d2015-04-02 21:47:18 +08003056 OPT_BOOLEAN('f', "force", &trace.force, "don't complain, do it"),
Milian Wolff566a0882016-04-08 13:34:15 +02003057 OPT_CALLBACK(0, "call-graph", &trace.opts,
3058 "record_mode[,record_size]", record_callchain_help,
3059 &record_parse_callchain_opt),
Arnaldo Carvalho de Melo44621812016-04-11 15:49:11 -03003060 OPT_BOOLEAN(0, "kernel-syscall-graph", &trace.kernel_syscallchains,
3061 "Show the kernel callchains on the syscall exit path"),
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -03003062 OPT_UINTEGER(0, "min-stack", &trace.min_stack,
3063 "Set the minimum stack depth when parsing the callchain, "
3064 "anything below the specified depth will be ignored."),
Arnaldo Carvalho de Meloc6d4a492016-04-14 18:29:08 -03003065 OPT_UINTEGER(0, "max-stack", &trace.max_stack,
3066 "Set the maximum stack depth when parsing the callchain, "
3067 "anything beyond the specified depth will be ignored. "
Arnaldo Carvalho de Melo4cb93442016-04-27 10:16:24 -03003068 "Default: kernel.perf_event_max_stack or " __stringify(PERF_MAX_STACK_DEPTH)),
Kan Liang9d9cad72015-06-17 09:51:11 -04003069 OPT_UINTEGER(0, "proc-map-timeout", &trace.opts.proc_map_timeout,
3070 "per thread proc mmap processing timeout in ms"),
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003071 OPT_END()
3072 };
Arnaldo Carvalho de Meloccd62a82016-04-16 09:36:32 -03003073 bool __maybe_unused max_stack_user_set = true;
Arnaldo Carvalho de Melof3e459d2016-04-15 17:52:34 -03003074 bool mmap_pages_user_set = true;
Yunlong Song6fdd9cb2015-03-18 21:35:57 +08003075 const char * const trace_subcommands[] = { "record", NULL };
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003076 int err;
Namhyung Kim32caf0d2012-10-05 14:02:13 +09003077 char bf[BUFSIZ];
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003078
Arnaldo Carvalho de Melo4d08cb82015-02-24 15:35:55 -03003079 signal(SIGSEGV, sighandler_dump_stack);
3080 signal(SIGFPE, sighandler_dump_stack);
3081
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003082 trace.evlist = perf_evlist__new();
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03003083 trace.sctbl = syscalltbl__new();
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003084
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03003085 if (trace.evlist == NULL || trace.sctbl == NULL) {
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003086 pr_err("Not enough memory to run!\n");
He Kuangff8f6952015-05-11 12:28:36 +00003087 err = -ENOMEM;
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003088 goto out;
3089 }
3090
Yunlong Song6fdd9cb2015-03-18 21:35:57 +08003091 argc = parse_options_subcommand(argc, argv, trace_options, trace_subcommands,
3092 trace_usage, PARSE_OPT_STOP_AT_NON_OPTION);
David Ahernfd2eaba2013-11-12 09:31:15 -07003093
Wang Nand7888572016-04-08 15:07:24 +00003094 err = bpf__setup_stdout(trace.evlist);
3095 if (err) {
3096 bpf__strerror_setup_stdout(trace.evlist, err, bf, sizeof(bf));
3097 pr_err("ERROR: Setup BPF stdout failed: %s\n", bf);
3098 goto out;
3099 }
3100
Arnaldo Carvalho de Melo59247e32016-04-12 16:05:02 -03003101 err = -1;
3102
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04003103 if (trace.trace_pgfaults) {
3104 trace.opts.sample_address = true;
3105 trace.opts.sample_time = true;
3106 }
3107
Arnaldo Carvalho de Melof3e459d2016-04-15 17:52:34 -03003108 if (trace.opts.mmap_pages == UINT_MAX)
3109 mmap_pages_user_set = false;
3110
Arnaldo Carvalho de Melo05614992016-04-15 16:41:19 -03003111 if (trace.max_stack == UINT_MAX) {
Arnaldo Carvalho de Melo4cb93442016-04-27 10:16:24 -03003112 trace.max_stack = sysctl_perf_event_max_stack;
Arnaldo Carvalho de Melo05614992016-04-15 16:41:19 -03003113 max_stack_user_set = false;
3114 }
3115
3116#ifdef HAVE_DWARF_UNWIND_SUPPORT
Arnaldo Carvalho de Melo2ddd5c02016-04-18 12:09:08 -03003117 if ((trace.min_stack || max_stack_user_set) && !callchain_param.enabled)
Arnaldo Carvalho de Melo05614992016-04-15 16:41:19 -03003118 record_opts__parse_callchain(&trace.opts, &callchain_param, "dwarf", false);
3119#endif
3120
Arnaldo Carvalho de Melo2ddd5c02016-04-18 12:09:08 -03003121 if (callchain_param.enabled) {
Arnaldo Carvalho de Melof3e459d2016-04-15 17:52:34 -03003122 if (!mmap_pages_user_set && geteuid() == 0)
3123 trace.opts.mmap_pages = perf_event_mlock_kb_in_pages() * 4;
3124
Milian Wolff566a0882016-04-08 13:34:15 +02003125 symbol_conf.use_callchain = true;
Arnaldo Carvalho de Melof3e459d2016-04-15 17:52:34 -03003126 }
Milian Wolff566a0882016-04-08 13:34:15 +02003127
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003128 if (trace.evlist->nr_entries > 0)
3129 evlist__set_evsel_handler(trace.evlist, trace__event_handler);
3130
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04003131 if ((argc >= 1) && (strcmp(argv[0], "record") == 0))
3132 return trace__record(&trace, argc-1, &argv[1]);
3133
3134 /* summary_only implies summary option, but don't overwrite summary if set */
3135 if (trace.summary_only)
3136 trace.summary = trace.summary_only;
3137
Arnaldo Carvalho de Melo726f3232015-02-06 10:16:45 +01003138 if (!trace.trace_syscalls && !trace.trace_pgfaults &&
3139 trace.evlist->nr_entries == 0 /* Was --events used? */) {
Stanislav Fomicheve281a962014-06-26 20:14:28 +04003140 pr_err("Please specify something to trace.\n");
3141 return -1;
3142 }
3143
Arnaldo Carvalho de Melo59247e32016-04-12 16:05:02 -03003144 if (!trace.trace_syscalls && ev_qualifier_str) {
3145 pr_err("The -e option can't be used with --no-syscalls.\n");
3146 goto out;
3147 }
3148
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003149 if (output_name != NULL) {
3150 err = trace__open_output(&trace, output_name);
3151 if (err < 0) {
3152 perror("failed to create output file");
3153 goto out;
3154 }
3155 }
3156
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03003157 trace.open_id = syscalltbl__id(trace.sctbl, "open");
3158
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03003159 if (ev_qualifier_str != NULL) {
Arnaldo Carvalho de Melob059efd2013-08-21 12:56:21 -03003160 const char *s = ev_qualifier_str;
Arnaldo Carvalho de Melo005438a82015-07-20 12:02:09 -03003161 struct strlist_config slist_config = {
3162 .dirname = system_path(STRACE_GROUPS_DIR),
3163 };
Arnaldo Carvalho de Melob059efd2013-08-21 12:56:21 -03003164
3165 trace.not_ev_qualifier = *s == '!';
3166 if (trace.not_ev_qualifier)
3167 ++s;
Arnaldo Carvalho de Melo005438a82015-07-20 12:02:09 -03003168 trace.ev_qualifier = strlist__new(s, &slist_config);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03003169 if (trace.ev_qualifier == NULL) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003170 fputs("Not enough memory to parse event qualifier",
3171 trace.output);
3172 err = -ENOMEM;
3173 goto out_close;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03003174 }
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03003175
3176 err = trace__validate_ev_qualifier(&trace);
3177 if (err)
3178 goto out_close;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03003179 }
3180
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003181 err = target__validate(&trace.opts.target);
Namhyung Kim32caf0d2012-10-05 14:02:13 +09003182 if (err) {
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003183 target__strerror(&trace.opts.target, err, bf, sizeof(bf));
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003184 fprintf(trace.output, "%s", bf);
3185 goto out_close;
Namhyung Kim32caf0d2012-10-05 14:02:13 +09003186 }
3187
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003188 err = target__parse_uid(&trace.opts.target);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003189 if (err) {
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003190 target__strerror(&trace.opts.target, err, bf, sizeof(bf));
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003191 fprintf(trace.output, "%s", bf);
3192 goto out_close;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003193 }
3194
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003195 if (!argc && target__none(&trace.opts.target))
Namhyung Kimee761202012-10-05 14:02:14 +09003196 trace.opts.target.system_wide = true;
3197
David Ahern6810fc92013-08-28 22:29:52 -06003198 if (input_name)
3199 err = trace__replay(&trace);
3200 else
3201 err = trace__run(&trace, argc, argv);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03003202
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003203out_close:
3204 if (output_name != NULL)
3205 fclose(trace.output);
3206out:
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03003207 return err;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003208}