blob: a4e294e24f6ad63f9d0e41a12154a4dded21e24e [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 Ahern55d43bc2015-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 Ahern55d43bc2015-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 Melo46cce192013-09-23 12:52:04 -0300545static size_t syscall_arg__scnprintf_pipe_flags(char *bf, size_t size,
546 struct syscall_arg *arg)
547{
548 int printed = 0, flags = arg->val;
549
550#define P_FLAG(n) \
551 if (flags & O_##n) { \
552 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
553 flags &= ~O_##n; \
554 }
555
556 P_FLAG(CLOEXEC);
557 P_FLAG(NONBLOCK);
558#undef P_FLAG
559
560 if (flags)
561 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
562
563 return printed;
564}
565
566#define SCA_PIPE_FLAGS syscall_arg__scnprintf_pipe_flags
567
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -0300568#if defined(__i386__) || defined(__x86_64__)
569/*
570 * FIXME: Make this available to all arches.
571 */
Arnaldo Carvalho de Melo78645cf2013-10-08 17:43:20 -0300572#define TCGETS 0x5401
573
574static const char *tioctls[] = {
575 "TCGETS", "TCSETS", "TCSETSW", "TCSETSF", "TCGETA", "TCSETA", "TCSETAW",
576 "TCSETAF", "TCSBRK", "TCXONC", "TCFLSH", "TIOCEXCL", "TIOCNXCL",
577 "TIOCSCTTY", "TIOCGPGRP", "TIOCSPGRP", "TIOCOUTQ", "TIOCSTI",
578 "TIOCGWINSZ", "TIOCSWINSZ", "TIOCMGET", "TIOCMBIS", "TIOCMBIC",
579 "TIOCMSET", "TIOCGSOFTCAR", "TIOCSSOFTCAR", "FIONREAD", "TIOCLINUX",
580 "TIOCCONS", "TIOCGSERIAL", "TIOCSSERIAL", "TIOCPKT", "FIONBIO",
581 "TIOCNOTTY", "TIOCSETD", "TIOCGETD", "TCSBRKP", [0x27] = "TIOCSBRK",
582 "TIOCCBRK", "TIOCGSID", "TCGETS2", "TCSETS2", "TCSETSW2", "TCSETSF2",
583 "TIOCGRS485", "TIOCSRS485", "TIOCGPTN", "TIOCSPTLCK",
584 "TIOCGDEV||TCGETX", "TCSETX", "TCSETXF", "TCSETXW", "TIOCSIG",
585 "TIOCVHANGUP", "TIOCGPKT", "TIOCGPTLCK", "TIOCGEXCL",
586 [0x50] = "FIONCLEX", "FIOCLEX", "FIOASYNC", "TIOCSERCONFIG",
587 "TIOCSERGWILD", "TIOCSERSWILD", "TIOCGLCKTRMIOS", "TIOCSLCKTRMIOS",
588 "TIOCSERGSTRUCT", "TIOCSERGETLSR", "TIOCSERGETMULTI", "TIOCSERSETMULTI",
589 "TIOCMIWAIT", "TIOCGICOUNT", [0x60] = "FIOQSIZE",
590};
591
592static DEFINE_STRARRAY_OFFSET(tioctls, 0x5401);
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -0300593#endif /* defined(__i386__) || defined(__x86_64__) */
Arnaldo Carvalho de Melo78645cf2013-10-08 17:43:20 -0300594
Arnaldo Carvalho de Melo6fb35b92016-04-13 11:50:23 -0300595#ifndef SECCOMP_SET_MODE_STRICT
596#define SECCOMP_SET_MODE_STRICT 0
597#endif
598#ifndef SECCOMP_SET_MODE_FILTER
599#define SECCOMP_SET_MODE_FILTER 1
600#endif
601
Arnaldo Carvalho de Melo997bba82016-03-30 19:43:32 -0300602static size_t syscall_arg__scnprintf_seccomp_op(char *bf, size_t size, struct syscall_arg *arg)
603{
604 int op = arg->val;
605 size_t printed = 0;
606
607 switch (op) {
608#define P_SECCOMP_SET_MODE_OP(n) case SECCOMP_SET_MODE_##n: printed = scnprintf(bf, size, #n); break
609 P_SECCOMP_SET_MODE_OP(STRICT);
610 P_SECCOMP_SET_MODE_OP(FILTER);
611#undef P_SECCOMP_SET_MODE_OP
612 default: printed = scnprintf(bf, size, "%#x", op); break;
613 }
614
615 return printed;
616}
617
618#define SCA_SECCOMP_OP syscall_arg__scnprintf_seccomp_op
619
Arnaldo Carvalho de Melo6fb35b92016-04-13 11:50:23 -0300620#ifndef SECCOMP_FILTER_FLAG_TSYNC
621#define SECCOMP_FILTER_FLAG_TSYNC 1
622#endif
623
Arnaldo Carvalho de Melo997bba82016-03-30 19:43:32 -0300624static size_t syscall_arg__scnprintf_seccomp_flags(char *bf, size_t size,
625 struct syscall_arg *arg)
626{
627 int printed = 0, flags = arg->val;
628
629#define P_FLAG(n) \
630 if (flags & SECCOMP_FILTER_FLAG_##n) { \
631 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
632 flags &= ~SECCOMP_FILTER_FLAG_##n; \
633 }
634
635 P_FLAG(TSYNC);
636#undef P_FLAG
637
638 if (flags)
639 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
640
641 return printed;
642}
643
644#define SCA_SECCOMP_FLAGS syscall_arg__scnprintf_seccomp_flags
645
Arnaldo Carvalho de Meloa355a612016-04-13 11:55:18 -0300646#ifndef GRND_NONBLOCK
647#define GRND_NONBLOCK 0x0001
648#endif
649#ifndef GRND_RANDOM
650#define GRND_RANDOM 0x0002
651#endif
652
Arnaldo Carvalho de Melo39878d42016-03-30 20:02:15 -0300653static size_t syscall_arg__scnprintf_getrandom_flags(char *bf, size_t size,
654 struct syscall_arg *arg)
655{
656 int printed = 0, flags = arg->val;
657
658#define P_FLAG(n) \
659 if (flags & GRND_##n) { \
660 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
661 flags &= ~GRND_##n; \
662 }
663
664 P_FLAG(RANDOM);
665 P_FLAG(NONBLOCK);
666#undef P_FLAG
667
668 if (flags)
669 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
670
671 return printed;
672}
673
674#define SCA_GETRANDOM_FLAGS syscall_arg__scnprintf_getrandom_flags
675
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300676#define STRARRAY(arg, name, array) \
677 .arg_scnprintf = { [arg] = SCA_STRARRAY, }, \
678 .arg_parm = { [arg] = &strarray__##array, }
679
Arnaldo Carvalho de Meloea8dc3c2016-04-13 12:10:19 -0300680#include "trace/beauty/eventfd.c"
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -0300681#include "trace/beauty/pid.c"
Arnaldo Carvalho de Melodf4cb162016-04-13 12:05:44 -0300682#include "trace/beauty/mmap.c"
Arnaldo Carvalho de Meloba2f22c2016-04-07 12:05:51 -0300683#include "trace/beauty/mode_t.c"
Arnaldo Carvalho de Meloa30e6252016-04-27 19:01:52 -0300684#include "trace/beauty/msg_flags.c"
Arnaldo Carvalho de Melo8f48df62016-05-06 10:02:32 -0300685#include "trace/beauty/open_flags.c"
Arnaldo Carvalho de Melo62de3442016-04-26 11:03:03 -0300686#include "trace/beauty/perf_event_open.c"
Arnaldo Carvalho de Meloa3bca912016-04-06 12:51:33 -0300687#include "trace/beauty/sched_policy.c"
Arnaldo Carvalho de Melo12199d82016-05-06 09:58:02 -0300688#include "trace/beauty/signum.c"
Arnaldo Carvalho de Melobbf86c42016-04-14 13:53:10 -0300689#include "trace/beauty/socket_type.c"
Arnaldo Carvalho de Melo7206b902016-04-06 14:11:36 -0300690#include "trace/beauty/waitid_options.c"
Arnaldo Carvalho de Meloa3bca912016-04-06 12:51:33 -0300691
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300692static struct syscall_fmt {
693 const char *name;
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -0300694 const char *alias;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300695 size_t (*arg_scnprintf[6])(char *bf, size_t size, struct syscall_arg *arg);
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300696 void *arg_parm[6];
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300697 bool errmsg;
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -0300698 bool errpid;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300699 bool timeout;
Arnaldo Carvalho de Melo04b34722013-08-26 11:36:30 -0300700 bool hexret;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300701} syscall_fmts[] = {
Arnaldo Carvalho de Melo51108992013-09-04 11:42:27 -0300702 { .name = "access", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300703 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */
704 [1] = SCA_ACCMODE, /* mode */ }, },
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -0300705 { .name = "arch_prctl", .errmsg = true, .alias = "prctl", },
Arnaldo Carvalho de Melo729a7842015-10-29 11:48:18 -0300706 { .name = "bpf", .errmsg = true, STRARRAY(0, cmd, bpf_cmd), },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -0300707 { .name = "brk", .hexret = true,
708 .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300709 { .name = "chdir", .errmsg = true,
710 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
711 { .name = "chmod", .errmsg = true,
712 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
713 { .name = "chroot", .errmsg = true,
714 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
David Ahern4f8c1b72013-09-22 19:45:00 -0600715 { .name = "clock_gettime", .errmsg = true, STRARRAY(0, clk_id, clockid), },
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -0300716 { .name = "clone", .errpid = true, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300717 { .name = "close", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300718 .arg_scnprintf = { [0] = SCA_CLOSE_FD, /* fd */ }, },
Arnaldo Carvalho de Meloa14bb862013-07-30 16:38:23 -0300719 { .name = "connect", .errmsg = true, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300720 { .name = "creat", .errmsg = true,
721 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300722 { .name = "dup", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300723 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300724 { .name = "dup2", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300725 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300726 { .name = "dup3", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300727 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300728 { .name = "epoll_ctl", .errmsg = true, STRARRAY(1, op, epoll_ctl_ops), },
Arnaldo Carvalho de Melo49af9e92013-09-12 12:18:56 -0300729 { .name = "eventfd2", .errmsg = true,
730 .arg_scnprintf = { [1] = SCA_EFD_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300731 { .name = "faccessat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300732 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
733 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300734 { .name = "fadvise64", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300735 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300736 { .name = "fallocate", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300737 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300738 { .name = "fchdir", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300739 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300740 { .name = "fchmod", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300741 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300742 { .name = "fchmodat", .errmsg = true,
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -0300743 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */
744 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300745 { .name = "fchown", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300746 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300747 { .name = "fchownat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300748 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */
749 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300750 { .name = "fcntl", .errmsg = true,
751 .arg_scnprintf = { [0] = SCA_FD, /* fd */
752 [1] = SCA_STRARRAY, /* cmd */ },
753 .arg_parm = { [1] = &strarray__fcntl_cmds, /* cmd */ }, },
754 { .name = "fdatasync", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300755 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo5cea6ff2013-09-20 11:49:50 -0300756 { .name = "flock", .errmsg = true,
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300757 .arg_scnprintf = { [0] = SCA_FD, /* fd */
758 [1] = SCA_FLOCK, /* cmd */ }, },
759 { .name = "fsetxattr", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300760 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300761 { .name = "fstat", .errmsg = true, .alias = "newfstat",
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300762 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300763 { .name = "fstatat", .errmsg = true, .alias = "newfstatat",
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300764 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
765 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300766 { .name = "fstatfs", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300767 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300768 { .name = "fsync", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300769 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300770 { .name = "ftruncate", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300771 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -0300772 { .name = "futex", .errmsg = true,
773 .arg_scnprintf = { [1] = SCA_FUTEX_OP, /* op */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300774 { .name = "futimesat", .errmsg = true,
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -0300775 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */
776 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300777 { .name = "getdents", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300778 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300779 { .name = "getdents64", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300780 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300781 { .name = "getitimer", .errmsg = true, STRARRAY(0, which, itimers), },
Arnaldo Carvalho de Meloc65f1072016-04-06 14:55:18 -0300782 { .name = "getpid", .errpid = true, },
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -0300783 { .name = "getpgid", .errpid = true, },
Arnaldo Carvalho de Meloc65f1072016-04-06 14:55:18 -0300784 { .name = "getppid", .errpid = true, },
Arnaldo Carvalho de Melo39878d42016-03-30 20:02:15 -0300785 { .name = "getrandom", .errmsg = true,
786 .arg_scnprintf = { [2] = SCA_GETRANDOM_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300787 { .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300788 { .name = "getxattr", .errmsg = true,
789 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
790 { .name = "inotify_add_watch", .errmsg = true,
791 .arg_scnprintf = { [1] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -0300792 { .name = "ioctl", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300793 .arg_scnprintf = { [0] = SCA_FD, /* fd */
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -0300794#if defined(__i386__) || defined(__x86_64__)
795/*
796 * FIXME: Make this available to all arches.
797 */
Arnaldo Carvalho de Melo78645cf2013-10-08 17:43:20 -0300798 [1] = SCA_STRHEXARRAY, /* cmd */
799 [2] = SCA_HEX, /* arg */ },
800 .arg_parm = { [1] = &strarray__tioctls, /* cmd */ }, },
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -0300801#else
802 [2] = SCA_HEX, /* arg */ }, },
803#endif
Arnaldo Carvalho de Melob62bee12015-08-11 11:05:36 -0300804 { .name = "keyctl", .errmsg = true, STRARRAY(0, option, keyctl_options), },
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -0300805 { .name = "kill", .errmsg = true,
806 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300807 { .name = "lchown", .errmsg = true,
808 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
809 { .name = "lgetxattr", .errmsg = true,
810 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300811 { .name = "linkat", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300812 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300813 { .name = "listxattr", .errmsg = true,
814 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -0300815 { .name = "llistxattr", .errmsg = true,
816 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
817 { .name = "lremovexattr", .errmsg = true,
818 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300819 { .name = "lseek", .errmsg = true,
820 .arg_scnprintf = { [0] = SCA_FD, /* fd */
821 [2] = SCA_STRARRAY, /* whence */ },
822 .arg_parm = { [2] = &strarray__whences, /* whence */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300823 { .name = "lsetxattr", .errmsg = true,
824 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -0300825 { .name = "lstat", .errmsg = true, .alias = "newlstat",
826 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300827 { .name = "lsxattr", .errmsg = true,
828 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo9e9716d2013-08-23 10:06:41 -0300829 { .name = "madvise", .errmsg = true,
830 .arg_scnprintf = { [0] = SCA_HEX, /* start */
831 [2] = SCA_MADV_BHV, /* behavior */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300832 { .name = "mkdir", .errmsg = true,
833 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300834 { .name = "mkdirat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300835 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */
836 [1] = SCA_FILENAME, /* pathname */ }, },
837 { .name = "mknod", .errmsg = true,
838 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300839 { .name = "mknodat", .errmsg = true,
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -0300840 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */
841 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo3d903aa2013-09-24 00:09:38 -0300842 { .name = "mlock", .errmsg = true,
843 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
844 { .name = "mlockall", .errmsg = true,
845 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -0300846 { .name = "mmap", .hexret = true,
Arnaldo Carvalho de Meloae685382013-08-20 17:44:42 -0300847 .arg_scnprintf = { [0] = SCA_HEX, /* addr */
Arnaldo Carvalho de Melo941557e2013-08-23 10:48:33 -0300848 [2] = SCA_MMAP_PROT, /* prot */
Namhyung Kim73faab32013-11-12 15:24:59 +0900849 [3] = SCA_MMAP_FLAGS, /* flags */
850 [4] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -0300851 { .name = "mprotect", .errmsg = true,
Arnaldo Carvalho de Meloae685382013-08-20 17:44:42 -0300852 .arg_scnprintf = { [0] = SCA_HEX, /* start */
853 [2] = SCA_MMAP_PROT, /* prot */ }, },
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -0300854 { .name = "mq_unlink", .errmsg = true,
855 .arg_scnprintf = { [0] = SCA_FILENAME, /* u_name */ }, },
Arnaldo Carvalho de Meloae685382013-08-20 17:44:42 -0300856 { .name = "mremap", .hexret = true,
857 .arg_scnprintf = { [0] = SCA_HEX, /* addr */
Alex Snast86998dd2014-08-13 18:42:40 +0300858 [3] = SCA_MREMAP_FLAGS, /* flags */
Arnaldo Carvalho de Meloae685382013-08-20 17:44:42 -0300859 [4] = SCA_HEX, /* new_addr */ }, },
Arnaldo Carvalho de Melo3d903aa2013-09-24 00:09:38 -0300860 { .name = "munlock", .errmsg = true,
861 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -0300862 { .name = "munmap", .errmsg = true,
863 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300864 { .name = "name_to_handle_at", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300865 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300866 { .name = "newfstatat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300867 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
868 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melobe65a892013-09-02 16:22:31 -0300869 { .name = "open", .errmsg = true,
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -0300870 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */
871 [1] = SCA_OPEN_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo31cd3852013-09-02 16:40:40 -0300872 { .name = "open_by_handle_at", .errmsg = true,
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300873 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
874 [2] = SCA_OPEN_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo31cd3852013-09-02 16:40:40 -0300875 { .name = "openat", .errmsg = true,
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300876 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300877 [1] = SCA_FILENAME, /* filename */
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300878 [2] = SCA_OPEN_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Meloa1c25522015-06-11 22:47:54 -0300879 { .name = "perf_event_open", .errmsg = true,
Arnaldo Carvalho de Meloccd9b2a2016-04-26 11:40:17 -0300880 .arg_scnprintf = { [2] = SCA_INT, /* cpu */
Arnaldo Carvalho de Meloa1c25522015-06-11 22:47:54 -0300881 [3] = SCA_FD, /* group_fd */
882 [4] = SCA_PERF_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo46cce192013-09-23 12:52:04 -0300883 { .name = "pipe2", .errmsg = true,
884 .arg_scnprintf = { [1] = SCA_PIPE_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -0300885 { .name = "poll", .errmsg = true, .timeout = true, },
886 { .name = "ppoll", .errmsg = true, .timeout = true, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300887 { .name = "pread", .errmsg = true, .alias = "pread64",
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300888 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300889 { .name = "preadv", .errmsg = true, .alias = "pread",
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300890 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300891 { .name = "prlimit64", .errmsg = true, STRARRAY(1, resource, rlimit_resources), },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300892 { .name = "pwrite", .errmsg = true, .alias = "pwrite64",
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300893 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300894 { .name = "pwritev", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300895 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300896 { .name = "read", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300897 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300898 { .name = "readlink", .errmsg = true,
899 .arg_scnprintf = { [0] = SCA_FILENAME, /* path */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300900 { .name = "readlinkat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300901 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
902 [1] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300903 { .name = "readv", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300904 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -0300905 { .name = "recvfrom", .errmsg = true,
Arnaldo Carvalho de Melo8d8c66a2015-08-11 10:57:02 -0300906 .arg_scnprintf = { [0] = SCA_FD, /* fd */
907 [3] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -0300908 { .name = "recvmmsg", .errmsg = true,
Arnaldo Carvalho de Melo8d8c66a2015-08-11 10:57:02 -0300909 .arg_scnprintf = { [0] = SCA_FD, /* fd */
910 [3] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -0300911 { .name = "recvmsg", .errmsg = true,
Arnaldo Carvalho de Melo8d8c66a2015-08-11 10:57:02 -0300912 .arg_scnprintf = { [0] = SCA_FD, /* fd */
913 [2] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300914 { .name = "removexattr", .errmsg = true,
915 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300916 { .name = "renameat", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300917 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300918 { .name = "rmdir", .errmsg = true,
919 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -0300920 { .name = "rt_sigaction", .errmsg = true,
921 .arg_scnprintf = { [0] = SCA_SIGNUM, /* sig */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300922 { .name = "rt_sigprocmask", .errmsg = true, STRARRAY(0, how, sighow), },
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -0300923 { .name = "rt_sigqueueinfo", .errmsg = true,
924 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
925 { .name = "rt_tgsigqueueinfo", .errmsg = true,
926 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
Arnaldo Carvalho de Meloa3bca912016-04-06 12:51:33 -0300927 { .name = "sched_setscheduler", .errmsg = true,
928 .arg_scnprintf = { [1] = SCA_SCHED_POLICY, /* policy */ }, },
Arnaldo Carvalho de Melo997bba82016-03-30 19:43:32 -0300929 { .name = "seccomp", .errmsg = true,
930 .arg_scnprintf = { [0] = SCA_SECCOMP_OP, /* op */
931 [1] = SCA_SECCOMP_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -0300932 { .name = "select", .errmsg = true, .timeout = true, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -0300933 { .name = "sendmmsg", .errmsg = true,
Arnaldo Carvalho de Melo8d8c66a2015-08-11 10:57:02 -0300934 .arg_scnprintf = { [0] = SCA_FD, /* fd */
935 [3] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -0300936 { .name = "sendmsg", .errmsg = true,
Arnaldo Carvalho de Melo8d8c66a2015-08-11 10:57:02 -0300937 .arg_scnprintf = { [0] = SCA_FD, /* fd */
938 [2] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -0300939 { .name = "sendto", .errmsg = true,
Arnaldo Carvalho de Melo8d8c66a2015-08-11 10:57:02 -0300940 .arg_scnprintf = { [0] = SCA_FD, /* fd */
941 [3] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Meloc65f1072016-04-06 14:55:18 -0300942 { .name = "set_tid_address", .errpid = true, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300943 { .name = "setitimer", .errmsg = true, STRARRAY(0, which, itimers), },
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -0300944 { .name = "setpgid", .errmsg = true, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300945 { .name = "setrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300946 { .name = "setxattr", .errmsg = true,
947 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300948 { .name = "shutdown", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300949 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Meloe10bce82013-09-04 10:27:41 -0300950 { .name = "socket", .errmsg = true,
Arnaldo Carvalho de Meloa28b24b2013-09-04 11:00:44 -0300951 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
952 [1] = SCA_SK_TYPE, /* type */ },
Arnaldo Carvalho de Meloe10bce82013-09-04 10:27:41 -0300953 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, },
Arnaldo Carvalho de Melo07120aa2013-09-20 12:24:20 -0300954 { .name = "socketpair", .errmsg = true,
955 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
956 [1] = SCA_SK_TYPE, /* type */ },
957 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, },
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -0300958 { .name = "stat", .errmsg = true, .alias = "newstat",
959 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300960 { .name = "statfs", .errmsg = true,
961 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
962 { .name = "swapoff", .errmsg = true,
963 .arg_scnprintf = { [0] = SCA_FILENAME, /* specialfile */ }, },
964 { .name = "swapon", .errmsg = true,
965 .arg_scnprintf = { [0] = SCA_FILENAME, /* specialfile */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300966 { .name = "symlinkat", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300967 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -0300968 { .name = "tgkill", .errmsg = true,
969 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
970 { .name = "tkill", .errmsg = true,
971 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300972 { .name = "truncate", .errmsg = true,
973 .arg_scnprintf = { [0] = SCA_FILENAME, /* path */ }, },
Arnaldo Carvalho de Meloe5959682013-08-26 12:21:41 -0300974 { .name = "uname", .errmsg = true, .alias = "newuname", },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300975 { .name = "unlinkat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300976 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
977 [1] = SCA_FILENAME, /* pathname */ }, },
978 { .name = "utime", .errmsg = true,
979 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300980 { .name = "utimensat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300981 .arg_scnprintf = { [0] = SCA_FDAT, /* dirfd */
982 [1] = SCA_FILENAME, /* filename */ }, },
983 { .name = "utimes", .errmsg = true,
984 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -0300985 { .name = "vmsplice", .errmsg = true,
986 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -0300987 { .name = "wait4", .errpid = true,
Arnaldo Carvalho de Melo7206b902016-04-06 14:11:36 -0300988 .arg_scnprintf = { [2] = SCA_WAITID_OPTIONS, /* options */ }, },
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -0300989 { .name = "waitid", .errpid = true,
Arnaldo Carvalho de Melo7206b902016-04-06 14:11:36 -0300990 .arg_scnprintf = { [3] = SCA_WAITID_OPTIONS, /* options */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300991 { .name = "write", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300992 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300993 { .name = "writev", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300994 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300995};
996
997static int syscall_fmt__cmp(const void *name, const void *fmtp)
998{
999 const struct syscall_fmt *fmt = fmtp;
1000 return strcmp(name, fmt->name);
1001}
1002
1003static struct syscall_fmt *syscall_fmt__find(const char *name)
1004{
1005 const int nmemb = ARRAY_SIZE(syscall_fmts);
1006 return bsearch(name, syscall_fmts, nmemb, sizeof(struct syscall_fmt), syscall_fmt__cmp);
1007}
1008
1009struct syscall {
1010 struct event_format *tp_format;
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001011 int nr_args;
1012 struct format_field *args;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001013 const char *name;
Arnaldo Carvalho de Melo5089f202014-06-17 14:29:24 -03001014 bool is_exit;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001015 struct syscall_fmt *fmt;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001016 size_t (**arg_scnprintf)(char *bf, size_t size, struct syscall_arg *arg);
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -03001017 void **arg_parm;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001018};
1019
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001020static size_t fprintf_duration(unsigned long t, FILE *fp)
1021{
1022 double duration = (double)t / NSEC_PER_MSEC;
1023 size_t printed = fprintf(fp, "(");
1024
1025 if (duration >= 1.0)
1026 printed += color_fprintf(fp, PERF_COLOR_RED, "%6.3f ms", duration);
1027 else if (duration >= 0.01)
1028 printed += color_fprintf(fp, PERF_COLOR_YELLOW, "%6.3f ms", duration);
1029 else
1030 printed += color_fprintf(fp, PERF_COLOR_NORMAL, "%6.3f ms", duration);
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001031 return printed + fprintf(fp, "): ");
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001032}
1033
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001034/**
1035 * filename.ptr: The filename char pointer that will be vfs_getname'd
1036 * filename.entry_str_pos: Where to insert the string translated from
1037 * filename.ptr by the vfs_getname tracepoint/kprobe.
1038 */
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001039struct thread_trace {
1040 u64 entry_time;
1041 u64 exit_time;
1042 bool entry_pending;
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03001043 unsigned long nr_events;
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04001044 unsigned long pfmaj, pfmin;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001045 char *entry_str;
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001046 double runtime_ms;
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001047 struct {
1048 unsigned long ptr;
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03001049 short int entry_str_pos;
1050 bool pending_open;
1051 unsigned int namelen;
1052 char *name;
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001053 } filename;
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001054 struct {
1055 int max;
1056 char **table;
1057 } paths;
David Ahernbf2575c2013-10-08 21:26:53 -06001058
1059 struct intlist *syscall_stats;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001060};
1061
1062static struct thread_trace *thread_trace__new(void)
1063{
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001064 struct thread_trace *ttrace = zalloc(sizeof(struct thread_trace));
1065
1066 if (ttrace)
1067 ttrace->paths.max = -1;
1068
David Ahernbf2575c2013-10-08 21:26:53 -06001069 ttrace->syscall_stats = intlist__new(NULL);
1070
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001071 return ttrace;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001072}
1073
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001074static struct thread_trace *thread__trace(struct thread *thread, FILE *fp)
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001075{
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03001076 struct thread_trace *ttrace;
1077
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001078 if (thread == NULL)
1079 goto fail;
1080
Namhyung Kim89dceb22014-10-06 09:46:03 +09001081 if (thread__priv(thread) == NULL)
1082 thread__set_priv(thread, thread_trace__new());
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001083
Namhyung Kim89dceb22014-10-06 09:46:03 +09001084 if (thread__priv(thread) == NULL)
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001085 goto fail;
1086
Namhyung Kim89dceb22014-10-06 09:46:03 +09001087 ttrace = thread__priv(thread);
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03001088 ++ttrace->nr_events;
1089
1090 return ttrace;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001091fail:
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001092 color_fprintf(fp, PERF_COLOR_RED,
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001093 "WARNING: not enough memory, dropping samples!\n");
1094 return NULL;
1095}
1096
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04001097#define TRACE_PFMAJ (1 << 0)
1098#define TRACE_PFMIN (1 << 1)
1099
Arnaldo Carvalho de Meloe4d44e82015-08-04 22:17:29 -03001100static const size_t trace__entry_str_size = 2048;
1101
Arnaldo Carvalho de Melo97119f32013-09-27 17:34:10 -03001102static int trace__set_fd_pathname(struct thread *thread, int fd, const char *pathname)
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001103{
Namhyung Kim89dceb22014-10-06 09:46:03 +09001104 struct thread_trace *ttrace = thread__priv(thread);
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001105
1106 if (fd > ttrace->paths.max) {
1107 char **npath = realloc(ttrace->paths.table, (fd + 1) * sizeof(char *));
1108
1109 if (npath == NULL)
1110 return -1;
1111
1112 if (ttrace->paths.max != -1) {
1113 memset(npath + ttrace->paths.max + 1, 0,
1114 (fd - ttrace->paths.max) * sizeof(char *));
1115 } else {
1116 memset(npath, 0, (fd + 1) * sizeof(char *));
1117 }
1118
1119 ttrace->paths.table = npath;
1120 ttrace->paths.max = fd;
1121 }
1122
1123 ttrace->paths.table[fd] = strdup(pathname);
1124
1125 return ttrace->paths.table[fd] != NULL ? 0 : -1;
1126}
1127
Arnaldo Carvalho de Melo97119f32013-09-27 17:34:10 -03001128static int thread__read_fd_path(struct thread *thread, int fd)
1129{
1130 char linkname[PATH_MAX], pathname[PATH_MAX];
1131 struct stat st;
1132 int ret;
1133
1134 if (thread->pid_ == thread->tid) {
1135 scnprintf(linkname, sizeof(linkname),
1136 "/proc/%d/fd/%d", thread->pid_, fd);
1137 } else {
1138 scnprintf(linkname, sizeof(linkname),
1139 "/proc/%d/task/%d/fd/%d", thread->pid_, thread->tid, fd);
1140 }
1141
1142 if (lstat(linkname, &st) < 0 || st.st_size + 1 > (off_t)sizeof(pathname))
1143 return -1;
1144
1145 ret = readlink(linkname, pathname, sizeof(pathname));
1146
1147 if (ret < 0 || ret > st.st_size)
1148 return -1;
1149
1150 pathname[ret] = '\0';
1151 return trace__set_fd_pathname(thread, fd, pathname);
1152}
1153
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001154static const char *thread__fd_path(struct thread *thread, int fd,
1155 struct trace *trace)
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001156{
Namhyung Kim89dceb22014-10-06 09:46:03 +09001157 struct thread_trace *ttrace = thread__priv(thread);
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001158
1159 if (ttrace == NULL)
1160 return NULL;
1161
1162 if (fd < 0)
1163 return NULL;
1164
Arnaldo Carvalho de Melocdcd1e62014-06-10 16:00:18 -03001165 if ((fd > ttrace->paths.max || ttrace->paths.table[fd] == NULL)) {
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001166 if (!trace->live)
1167 return NULL;
1168 ++trace->stats.proc_getname;
Arnaldo Carvalho de Melocdcd1e62014-06-10 16:00:18 -03001169 if (thread__read_fd_path(thread, fd))
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001170 return NULL;
1171 }
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001172
1173 return ttrace->paths.table[fd];
1174}
1175
1176static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
1177 struct syscall_arg *arg)
1178{
1179 int fd = arg->val;
1180 size_t printed = scnprintf(bf, size, "%d", fd);
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001181 const char *path = thread__fd_path(arg->thread, fd, arg->trace);
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001182
1183 if (path)
1184 printed += scnprintf(bf + printed, size - printed, "<%s>", path);
1185
1186 return printed;
1187}
1188
1189static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
1190 struct syscall_arg *arg)
1191{
1192 int fd = arg->val;
1193 size_t printed = syscall_arg__scnprintf_fd(bf, size, arg);
Namhyung Kim89dceb22014-10-06 09:46:03 +09001194 struct thread_trace *ttrace = thread__priv(arg->thread);
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001195
Arnaldo Carvalho de Melo04662522013-12-26 17:41:15 -03001196 if (ttrace && fd >= 0 && fd <= ttrace->paths.max)
1197 zfree(&ttrace->paths.table[fd]);
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001198
1199 return printed;
1200}
1201
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001202static void thread__set_filename_pos(struct thread *thread, const char *bf,
1203 unsigned long ptr)
1204{
1205 struct thread_trace *ttrace = thread__priv(thread);
1206
1207 ttrace->filename.ptr = ptr;
1208 ttrace->filename.entry_str_pos = bf - ttrace->entry_str;
1209}
1210
1211static size_t syscall_arg__scnprintf_filename(char *bf, size_t size,
1212 struct syscall_arg *arg)
1213{
1214 unsigned long ptr = arg->val;
1215
1216 if (!arg->trace->vfs_getname)
1217 return scnprintf(bf, size, "%#x", ptr);
1218
1219 thread__set_filename_pos(arg->thread, bf, ptr);
1220 return 0;
1221}
1222
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001223static bool trace__filter_duration(struct trace *trace, double t)
1224{
1225 return t < (trace->duration_filter * NSEC_PER_MSEC);
1226}
1227
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001228static size_t trace__fprintf_tstamp(struct trace *trace, u64 tstamp, FILE *fp)
1229{
1230 double ts = (double)(tstamp - trace->base_time) / NSEC_PER_MSEC;
1231
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001232 return fprintf(fp, "%10.3f ", ts);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001233}
1234
Namhyung Kimf15eb532012-10-05 14:02:16 +09001235static bool done = false;
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03001236static bool interrupted = false;
Namhyung Kimf15eb532012-10-05 14:02:16 +09001237
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03001238static void sig_handler(int sig)
Namhyung Kimf15eb532012-10-05 14:02:16 +09001239{
1240 done = true;
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03001241 interrupted = sig == SIGINT;
Namhyung Kimf15eb532012-10-05 14:02:16 +09001242}
1243
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001244static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thread,
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001245 u64 duration, u64 tstamp, FILE *fp)
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001246{
1247 size_t printed = trace__fprintf_tstamp(trace, tstamp, fp);
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001248 printed += fprintf_duration(duration, fp);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001249
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -03001250 if (trace->multiple_threads) {
1251 if (trace->show_comm)
Frederic Weisbecker1902efe2013-09-11 16:56:44 +02001252 printed += fprintf(fp, "%.14s/", thread__comm_str(thread));
Adrian Hunter38051232013-07-04 16:20:31 +03001253 printed += fprintf(fp, "%d ", thread->tid);
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -03001254 }
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001255
1256 return printed;
1257}
1258
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001259static int trace__process_event(struct trace *trace, struct machine *machine,
Frederic Weisbecker162f0be2013-09-11 16:18:24 +02001260 union perf_event *event, struct perf_sample *sample)
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001261{
1262 int ret = 0;
1263
1264 switch (event->header.type) {
1265 case PERF_RECORD_LOST:
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001266 color_fprintf(trace->output, PERF_COLOR_RED,
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001267 "LOST %" PRIu64 " events!\n", event->lost.lost);
Frederic Weisbecker162f0be2013-09-11 16:18:24 +02001268 ret = machine__process_lost_event(machine, event, sample);
Arnaldo Carvalho de Melo3ed5ca22016-03-30 16:51:17 -03001269 break;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001270 default:
Frederic Weisbecker162f0be2013-09-11 16:18:24 +02001271 ret = machine__process_event(machine, event, sample);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001272 break;
1273 }
1274
1275 return ret;
1276}
1277
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001278static int trace__tool_process(struct perf_tool *tool,
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001279 union perf_event *event,
Frederic Weisbecker162f0be2013-09-11 16:18:24 +02001280 struct perf_sample *sample,
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001281 struct machine *machine)
1282{
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001283 struct trace *trace = container_of(tool, struct trace, tool);
Frederic Weisbecker162f0be2013-09-11 16:18:24 +02001284 return trace__process_event(trace, machine, event, sample);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001285}
1286
1287static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
1288{
Namhyung Kim0a7e6d12014-08-12 15:40:45 +09001289 int err = symbol__init(NULL);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001290
1291 if (err)
1292 return err;
1293
David Ahern8fb598e2013-09-28 13:13:00 -06001294 trace->host = machine__new_host();
1295 if (trace->host == NULL)
1296 return -ENOMEM;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001297
Arnaldo Carvalho de Melo959c2192015-07-24 12:13:05 -03001298 if (trace_event__register_resolver(trace->host, machine__resolve_kernel_addr) < 0)
Arnaldo Carvalho de Melo706c3da2015-07-22 16:16:16 -03001299 return -errno;
1300
Arnaldo Carvalho de Meloa33fbd52013-11-11 11:36:12 -03001301 err = __machine__synthesize_threads(trace->host, &trace->tool, &trace->opts.target,
Kan Liang9d9cad72015-06-17 09:51:11 -04001302 evlist->threads, trace__tool_process, false,
1303 trace->opts.proc_map_timeout);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001304 if (err)
1305 symbol__exit();
1306
1307 return err;
1308}
1309
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001310static int syscall__set_arg_fmts(struct syscall *sc)
1311{
1312 struct format_field *field;
1313 int idx = 0;
1314
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001315 sc->arg_scnprintf = calloc(sc->nr_args, sizeof(void *));
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001316 if (sc->arg_scnprintf == NULL)
1317 return -1;
1318
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -03001319 if (sc->fmt)
1320 sc->arg_parm = sc->fmt->arg_parm;
1321
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001322 for (field = sc->args; field; field = field->next) {
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -03001323 if (sc->fmt && sc->fmt->arg_scnprintf[idx])
1324 sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx];
1325 else if (field->flags & FIELD_IS_POINTER)
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001326 sc->arg_scnprintf[idx] = syscall_arg__scnprintf_hex;
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -03001327 else if (strcmp(field->type, "pid_t") == 0)
1328 sc->arg_scnprintf[idx] = SCA_PID;
Arnaldo Carvalho de Meloba2f22c2016-04-07 12:05:51 -03001329 else if (strcmp(field->type, "umode_t") == 0)
1330 sc->arg_scnprintf[idx] = SCA_MODE_T;
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001331 ++idx;
1332 }
1333
1334 return 0;
1335}
1336
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001337static int trace__read_syscall_info(struct trace *trace, int id)
1338{
1339 char tp_name[128];
1340 struct syscall *sc;
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03001341 const char *name = syscalltbl__name(trace->sctbl, id);
Arnaldo Carvalho de Melo3a531262012-10-20 12:39:03 -03001342
1343 if (name == NULL)
1344 return -1;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001345
1346 if (id > trace->syscalls.max) {
1347 struct syscall *nsyscalls = realloc(trace->syscalls.table, (id + 1) * sizeof(*sc));
1348
1349 if (nsyscalls == NULL)
1350 return -1;
1351
1352 if (trace->syscalls.max != -1) {
1353 memset(nsyscalls + trace->syscalls.max + 1, 0,
1354 (id - trace->syscalls.max) * sizeof(*sc));
1355 } else {
1356 memset(nsyscalls, 0, (id + 1) * sizeof(*sc));
1357 }
1358
1359 trace->syscalls.table = nsyscalls;
1360 trace->syscalls.max = id;
1361 }
1362
1363 sc = trace->syscalls.table + id;
Arnaldo Carvalho de Melo3a531262012-10-20 12:39:03 -03001364 sc->name = name;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001365
Arnaldo Carvalho de Melo3a531262012-10-20 12:39:03 -03001366 sc->fmt = syscall_fmt__find(sc->name);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001367
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -03001368 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name);
Jiri Olsa97978b32013-12-03 14:09:24 +01001369 sc->tp_format = trace_event__tp_format("syscalls", tp_name);
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -03001370
Jiri Olsa8dd2a132015-09-07 10:38:06 +02001371 if (IS_ERR(sc->tp_format) && sc->fmt && sc->fmt->alias) {
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -03001372 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->fmt->alias);
Jiri Olsa97978b32013-12-03 14:09:24 +01001373 sc->tp_format = trace_event__tp_format("syscalls", tp_name);
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -03001374 }
1375
Jiri Olsa8dd2a132015-09-07 10:38:06 +02001376 if (IS_ERR(sc->tp_format))
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001377 return -1;
1378
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001379 sc->args = sc->tp_format->format.fields;
1380 sc->nr_args = sc->tp_format->format.nr_fields;
Taeung Songc42de702016-02-26 22:14:25 +09001381 /*
1382 * We need to check and discard the first variable '__syscall_nr'
1383 * or 'nr' that mean the syscall number. It is needless here.
1384 * So drop '__syscall_nr' or 'nr' field but does not exist on older kernels.
1385 */
1386 if (sc->args && (!strcmp(sc->args->name, "__syscall_nr") || !strcmp(sc->args->name, "nr"))) {
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001387 sc->args = sc->args->next;
1388 --sc->nr_args;
1389 }
1390
Arnaldo Carvalho de Melo5089f202014-06-17 14:29:24 -03001391 sc->is_exit = !strcmp(name, "exit_group") || !strcmp(name, "exit");
1392
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001393 return syscall__set_arg_fmts(sc);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001394}
1395
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001396static int trace__validate_ev_qualifier(struct trace *trace)
1397{
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001398 int err = 0, i;
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001399 struct str_node *pos;
1400
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001401 trace->ev_qualifier_ids.nr = strlist__nr_entries(trace->ev_qualifier);
1402 trace->ev_qualifier_ids.entries = malloc(trace->ev_qualifier_ids.nr *
1403 sizeof(trace->ev_qualifier_ids.entries[0]));
1404
1405 if (trace->ev_qualifier_ids.entries == NULL) {
1406 fputs("Error:\tNot enough memory for allocating events qualifier ids\n",
1407 trace->output);
1408 err = -EINVAL;
1409 goto out;
1410 }
1411
1412 i = 0;
1413
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001414 strlist__for_each(pos, trace->ev_qualifier) {
1415 const char *sc = pos->s;
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03001416 int id = syscalltbl__id(trace->sctbl, sc);
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001417
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001418 if (id < 0) {
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001419 if (err == 0) {
1420 fputs("Error:\tInvalid syscall ", trace->output);
1421 err = -EINVAL;
1422 } else {
1423 fputs(", ", trace->output);
1424 }
1425
1426 fputs(sc, trace->output);
1427 }
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001428
1429 trace->ev_qualifier_ids.entries[i++] = id;
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001430 }
1431
1432 if (err < 0) {
1433 fputs("\nHint:\ttry 'perf list syscalls:sys_enter_*'"
1434 "\nHint:\tand: 'man syscalls'\n", trace->output);
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001435 zfree(&trace->ev_qualifier_ids.entries);
1436 trace->ev_qualifier_ids.nr = 0;
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001437 }
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001438out:
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001439 return err;
1440}
1441
David Ahern55d43bc2015-02-19 15:00:22 -05001442/*
1443 * args is to be interpreted as a series of longs but we need to handle
1444 * 8-byte unaligned accesses. args points to raw_data within the event
1445 * and raw_data is guaranteed to be 8-byte unaligned because it is
1446 * preceded by raw_size which is a u32. So we need to copy args to a temp
1447 * variable to read it. Most notably this avoids extended load instructions
1448 * on unaligned addresses
1449 */
1450
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001451static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
David Ahern55d43bc2015-02-19 15:00:22 -05001452 unsigned char *args, struct trace *trace,
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001453 struct thread *thread)
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001454{
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001455 size_t printed = 0;
David Ahern55d43bc2015-02-19 15:00:22 -05001456 unsigned char *p;
1457 unsigned long val;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001458
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001459 if (sc->args != NULL) {
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001460 struct format_field *field;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001461 u8 bit = 1;
1462 struct syscall_arg arg = {
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001463 .idx = 0,
1464 .mask = 0,
1465 .trace = trace,
1466 .thread = thread,
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001467 };
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001468
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001469 for (field = sc->args; field;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001470 field = field->next, ++arg.idx, bit <<= 1) {
1471 if (arg.mask & bit)
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -03001472 continue;
David Ahern55d43bc2015-02-19 15:00:22 -05001473
1474 /* special care for unaligned accesses */
1475 p = args + sizeof(unsigned long) * arg.idx;
1476 memcpy(&val, p, sizeof(val));
1477
Arnaldo Carvalho de Melo4aa58232013-09-20 12:19:41 -03001478 /*
1479 * Suppress this argument if its value is zero and
1480 * and we don't have a string associated in an
1481 * strarray for it.
1482 */
David Ahern55d43bc2015-02-19 15:00:22 -05001483 if (val == 0 &&
Arnaldo Carvalho de Melo4aa58232013-09-20 12:19:41 -03001484 !(sc->arg_scnprintf &&
1485 sc->arg_scnprintf[arg.idx] == SCA_STRARRAY &&
1486 sc->arg_parm[arg.idx]))
Arnaldo Carvalho de Melo22ae5cf12013-09-12 11:27:34 -03001487 continue;
1488
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001489 printed += scnprintf(bf + printed, size - printed,
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001490 "%s%s: ", printed ? ", " : "", field->name);
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001491 if (sc->arg_scnprintf && sc->arg_scnprintf[arg.idx]) {
David Ahern55d43bc2015-02-19 15:00:22 -05001492 arg.val = val;
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -03001493 if (sc->arg_parm)
1494 arg.parm = sc->arg_parm[arg.idx];
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001495 printed += sc->arg_scnprintf[arg.idx](bf + printed,
1496 size - printed, &arg);
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -03001497 } else {
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001498 printed += scnprintf(bf + printed, size - printed,
David Ahern55d43bc2015-02-19 15:00:22 -05001499 "%ld", val);
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -03001500 }
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001501 }
Arnaldo Carvalho de Melo4c4d6e52016-05-05 23:38:05 -03001502 } else if (IS_ERR(sc->tp_format)) {
1503 /*
1504 * If we managed to read the tracepoint /format file, then we
1505 * may end up not having any args, like with gettid(), so only
1506 * print the raw args when we didn't manage to read it.
1507 */
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001508 int i = 0;
1509
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001510 while (i < 6) {
David Ahern55d43bc2015-02-19 15:00:22 -05001511 /* special care for unaligned accesses */
1512 p = args + sizeof(unsigned long) * i;
1513 memcpy(&val, p, sizeof(val));
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001514 printed += scnprintf(bf + printed, size - printed,
1515 "%sarg%d: %ld",
David Ahern55d43bc2015-02-19 15:00:22 -05001516 printed ? ", " : "", i, val);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001517 ++i;
1518 }
1519 }
1520
1521 return printed;
1522}
1523
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001524typedef int (*tracepoint_handler)(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04001525 union perf_event *event,
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001526 struct perf_sample *sample);
1527
1528static struct syscall *trace__syscall_info(struct trace *trace,
David Ahernbf2575c2013-10-08 21:26:53 -06001529 struct perf_evsel *evsel, int id)
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001530{
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001531
1532 if (id < 0) {
Arnaldo Carvalho de Meloadaa18b2013-08-22 17:55:25 -03001533
1534 /*
1535 * XXX: Noticed on x86_64, reproduced as far back as 3.0.36, haven't tried
1536 * before that, leaving at a higher verbosity level till that is
1537 * explained. Reproduced with plain ftrace with:
1538 *
1539 * echo 1 > /t/events/raw_syscalls/sys_exit/enable
1540 * grep "NR -1 " /t/trace_pipe
1541 *
1542 * After generating some load on the machine.
1543 */
1544 if (verbose > 1) {
1545 static u64 n;
1546 fprintf(trace->output, "Invalid syscall %d id, skipping (%s, %" PRIu64 ") ...\n",
1547 id, perf_evsel__name(evsel), ++n);
1548 }
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001549 return NULL;
1550 }
1551
1552 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL) &&
1553 trace__read_syscall_info(trace, id))
1554 goto out_cant_read;
1555
1556 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL))
1557 goto out_cant_read;
1558
1559 return &trace->syscalls.table[id];
1560
1561out_cant_read:
Arnaldo Carvalho de Melo7c304ee02013-08-22 16:49:54 -03001562 if (verbose) {
1563 fprintf(trace->output, "Problems reading syscall %d", id);
1564 if (id <= trace->syscalls.max && trace->syscalls.table[id].name != NULL)
1565 fprintf(trace->output, "(%s)", trace->syscalls.table[id].name);
1566 fputs(" information\n", trace->output);
1567 }
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001568 return NULL;
1569}
1570
David Ahernbf2575c2013-10-08 21:26:53 -06001571static void thread__update_stats(struct thread_trace *ttrace,
1572 int id, struct perf_sample *sample)
1573{
1574 struct int_node *inode;
1575 struct stats *stats;
1576 u64 duration = 0;
1577
1578 inode = intlist__findnew(ttrace->syscall_stats, id);
1579 if (inode == NULL)
1580 return;
1581
1582 stats = inode->priv;
1583 if (stats == NULL) {
1584 stats = malloc(sizeof(struct stats));
1585 if (stats == NULL)
1586 return;
1587 init_stats(stats);
1588 inode->priv = stats;
1589 }
1590
1591 if (ttrace->entry_time && sample->time > ttrace->entry_time)
1592 duration = sample->time - ttrace->entry_time;
1593
1594 update_stats(stats, duration);
1595}
1596
Arnaldo Carvalho de Meloe5966632015-02-13 13:22:21 -03001597static int trace__printf_interrupted_entry(struct trace *trace, struct perf_sample *sample)
1598{
1599 struct thread_trace *ttrace;
1600 u64 duration;
1601 size_t printed;
1602
1603 if (trace->current == NULL)
1604 return 0;
1605
1606 ttrace = thread__priv(trace->current);
1607
1608 if (!ttrace->entry_pending)
1609 return 0;
1610
1611 duration = sample->time - ttrace->entry_time;
1612
1613 printed = trace__fprintf_entry_head(trace, trace->current, duration, sample->time, trace->output);
1614 printed += fprintf(trace->output, "%-70s) ...\n", ttrace->entry_str);
1615 ttrace->entry_pending = false;
1616
1617 return printed;
1618}
1619
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001620static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04001621 union perf_event *event __maybe_unused,
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001622 struct perf_sample *sample)
1623{
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001624 char *msg;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001625 void *args;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001626 size_t printed = 0;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001627 struct thread *thread;
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001628 int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
David Ahernbf2575c2013-10-08 21:26:53 -06001629 struct syscall *sc = trace__syscall_info(trace, evsel, id);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001630 struct thread_trace *ttrace;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001631
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001632 if (sc == NULL)
1633 return -1;
1634
David Ahern8fb598e2013-09-28 13:13:00 -06001635 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001636 ttrace = thread__trace(thread, trace->output);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001637 if (ttrace == NULL)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001638 goto out_put;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001639
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -03001640 args = perf_evsel__sc_tp_ptr(evsel, args, sample);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001641
1642 if (ttrace->entry_str == NULL) {
Arnaldo Carvalho de Meloe4d44e82015-08-04 22:17:29 -03001643 ttrace->entry_str = malloc(trace__entry_str_size);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001644 if (!ttrace->entry_str)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001645 goto out_put;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001646 }
1647
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -03001648 if (!(trace->duration_filter || trace->summary_only || trace->min_stack))
Arnaldo Carvalho de Melo6ebad5c2015-03-25 18:01:15 -03001649 trace__printf_interrupted_entry(trace, sample);
Arnaldo Carvalho de Meloe5966632015-02-13 13:22:21 -03001650
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001651 ttrace->entry_time = sample->time;
1652 msg = ttrace->entry_str;
Arnaldo Carvalho de Meloe4d44e82015-08-04 22:17:29 -03001653 printed += scnprintf(msg + printed, trace__entry_str_size - printed, "%s(", sc->name);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001654
Arnaldo Carvalho de Meloe4d44e82015-08-04 22:17:29 -03001655 printed += syscall__scnprintf_args(sc, msg + printed, trace__entry_str_size - printed,
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001656 args, trace, thread);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001657
Arnaldo Carvalho de Melo5089f202014-06-17 14:29:24 -03001658 if (sc->is_exit) {
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -03001659 if (!(trace->duration_filter || trace->summary_only || trace->min_stack)) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001660 trace__fprintf_entry_head(trace, thread, 1, sample->time, trace->output);
1661 fprintf(trace->output, "%-70s\n", ttrace->entry_str);
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001662 }
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03001663 } else {
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001664 ttrace->entry_pending = true;
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03001665 /* See trace__vfs_getname & trace__sys_exit */
1666 ttrace->filename.pending_open = false;
1667 }
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001668
Arnaldo Carvalho de Melof3b623b2015-03-02 22:21:35 -03001669 if (trace->current != thread) {
1670 thread__put(trace->current);
1671 trace->current = thread__get(thread);
1672 }
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001673 err = 0;
1674out_put:
1675 thread__put(thread);
1676 return err;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001677}
1678
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -03001679static int trace__resolve_callchain(struct trace *trace, struct perf_evsel *evsel,
1680 struct perf_sample *sample,
1681 struct callchain_cursor *cursor)
Arnaldo Carvalho de Melo202ff962016-04-12 10:11:07 -03001682{
1683 struct addr_location al;
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -03001684
1685 if (machine__resolve(trace->host, &al, sample) < 0 ||
1686 thread__resolve_callchain(al.thread, cursor, evsel, sample, NULL, NULL, trace->max_stack))
1687 return -1;
1688
1689 return 0;
1690}
1691
1692static int trace__fprintf_callchain(struct trace *trace, struct perf_sample *sample)
1693{
Arnaldo Carvalho de Melo202ff962016-04-12 10:11:07 -03001694 /* TODO: user-configurable print_opts */
Arnaldo Carvalho de Meloe20ab862016-04-12 15:16:15 -03001695 const unsigned int print_opts = EVSEL__PRINT_SYM |
1696 EVSEL__PRINT_DSO |
1697 EVSEL__PRINT_UNKNOWN_AS_ADDR;
Arnaldo Carvalho de Melo202ff962016-04-12 10:11:07 -03001698
Arnaldo Carvalho de Melod327e602016-04-14 17:53:49 -03001699 return sample__fprintf_callchain(sample, 38, print_opts, &callchain_cursor, trace->output);
Arnaldo Carvalho de Melo202ff962016-04-12 10:11:07 -03001700}
1701
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001702static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04001703 union perf_event *event __maybe_unused,
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001704 struct perf_sample *sample)
1705{
Chang Hyun Park2c82c3a2014-09-26 21:54:01 +09001706 long ret;
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001707 u64 duration = 0;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001708 struct thread *thread;
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -03001709 int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1, callchain_ret = 0;
David Ahernbf2575c2013-10-08 21:26:53 -06001710 struct syscall *sc = trace__syscall_info(trace, evsel, id);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001711 struct thread_trace *ttrace;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001712
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001713 if (sc == NULL)
1714 return -1;
1715
David Ahern8fb598e2013-09-28 13:13:00 -06001716 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001717 ttrace = thread__trace(thread, trace->output);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001718 if (ttrace == NULL)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001719 goto out_put;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001720
David Ahernbf2575c2013-10-08 21:26:53 -06001721 if (trace->summary)
1722 thread__update_stats(ttrace, id, sample);
1723
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -03001724 ret = perf_evsel__sc_tp_uint(evsel, ret, sample);
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001725
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03001726 if (id == trace->open_id && ret >= 0 && ttrace->filename.pending_open) {
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03001727 trace__set_fd_pathname(thread, ret, ttrace->filename.name);
1728 ttrace->filename.pending_open = false;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001729 ++trace->stats.vfs_getname;
1730 }
1731
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001732 ttrace->exit_time = sample->time;
1733
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001734 if (ttrace->entry_time) {
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001735 duration = sample->time - ttrace->entry_time;
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001736 if (trace__filter_duration(trace, duration))
1737 goto out;
1738 } else if (trace->duration_filter)
1739 goto out;
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001740
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -03001741 if (sample->callchain) {
1742 callchain_ret = trace__resolve_callchain(trace, evsel, sample, &callchain_cursor);
1743 if (callchain_ret == 0) {
1744 if (callchain_cursor.nr < trace->min_stack)
1745 goto out;
1746 callchain_ret = 1;
1747 }
1748 }
1749
David Ahernfd2eaba2013-11-12 09:31:15 -07001750 if (trace->summary_only)
1751 goto out;
1752
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001753 trace__fprintf_entry_head(trace, thread, duration, sample->time, trace->output);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001754
1755 if (ttrace->entry_pending) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001756 fprintf(trace->output, "%-70s", ttrace->entry_str);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001757 } else {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001758 fprintf(trace->output, " ... [");
1759 color_fprintf(trace->output, PERF_COLOR_YELLOW, "continued");
1760 fprintf(trace->output, "]: %s()", sc->name);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001761 }
1762
Arnaldo Carvalho de Meloda3c9a42013-08-26 11:28:34 -03001763 if (sc->fmt == NULL) {
1764signed_print:
Chang Hyun Park2c82c3a2014-09-26 21:54:01 +09001765 fprintf(trace->output, ") = %ld", ret);
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -03001766 } else if (ret < 0 && (sc->fmt->errmsg || sc->fmt->errpid)) {
Masami Hiramatsu942a91e2014-08-14 02:22:41 +00001767 char bf[STRERR_BUFSIZE];
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001768 const char *emsg = strerror_r(-ret, bf, sizeof(bf)),
1769 *e = audit_errno_to_name(-ret);
1770
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001771 fprintf(trace->output, ") = -1 %s %s", e, emsg);
Arnaldo Carvalho de Meloda3c9a42013-08-26 11:28:34 -03001772 } else if (ret == 0 && sc->fmt->timeout)
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001773 fprintf(trace->output, ") = 0 Timeout");
Arnaldo Carvalho de Melo04b34722013-08-26 11:36:30 -03001774 else if (sc->fmt->hexret)
Chang Hyun Park2c82c3a2014-09-26 21:54:01 +09001775 fprintf(trace->output, ") = %#lx", ret);
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -03001776 else if (sc->fmt->errpid) {
1777 struct thread *child = machine__find_thread(trace->host, ret, ret);
1778
1779 if (child != NULL) {
1780 fprintf(trace->output, ") = %ld", ret);
1781 if (child->comm_set)
1782 fprintf(trace->output, " (%s)", thread__comm_str(child));
1783 thread__put(child);
1784 }
1785 } else
Arnaldo Carvalho de Meloda3c9a42013-08-26 11:28:34 -03001786 goto signed_print;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001787
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001788 fputc('\n', trace->output);
Milian Wolff566a0882016-04-08 13:34:15 +02001789
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -03001790 if (callchain_ret > 0)
1791 trace__fprintf_callchain(trace, sample);
1792 else if (callchain_ret < 0)
1793 pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel));
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001794out:
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001795 ttrace->entry_pending = false;
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001796 err = 0;
1797out_put:
1798 thread__put(thread);
1799 return err;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001800}
1801
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001802static int trace__vfs_getname(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04001803 union perf_event *event __maybe_unused,
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001804 struct perf_sample *sample)
1805{
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001806 struct thread *thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
1807 struct thread_trace *ttrace;
1808 size_t filename_len, entry_str_len, to_move;
1809 ssize_t remaining_space;
1810 char *pos;
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03001811 const char *filename = perf_evsel__rawptr(evsel, sample, "pathname");
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001812
1813 if (!thread)
1814 goto out;
1815
1816 ttrace = thread__priv(thread);
1817 if (!ttrace)
1818 goto out;
1819
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03001820 filename_len = strlen(filename);
1821
1822 if (ttrace->filename.namelen < filename_len) {
1823 char *f = realloc(ttrace->filename.name, filename_len + 1);
1824
1825 if (f == NULL)
1826 goto out;
1827
1828 ttrace->filename.namelen = filename_len;
1829 ttrace->filename.name = f;
1830 }
1831
1832 strcpy(ttrace->filename.name, filename);
1833 ttrace->filename.pending_open = true;
1834
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001835 if (!ttrace->filename.ptr)
1836 goto out;
1837
1838 entry_str_len = strlen(ttrace->entry_str);
1839 remaining_space = trace__entry_str_size - entry_str_len - 1; /* \0 */
1840 if (remaining_space <= 0)
1841 goto out;
1842
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001843 if (filename_len > (size_t)remaining_space) {
1844 filename += filename_len - remaining_space;
1845 filename_len = remaining_space;
1846 }
1847
1848 to_move = entry_str_len - ttrace->filename.entry_str_pos + 1; /* \0 */
1849 pos = ttrace->entry_str + ttrace->filename.entry_str_pos;
1850 memmove(pos + filename_len, pos, to_move);
1851 memcpy(pos, filename, filename_len);
1852
1853 ttrace->filename.ptr = 0;
1854 ttrace->filename.entry_str_pos = 0;
1855out:
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001856 return 0;
1857}
1858
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001859static int trace__sched_stat_runtime(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04001860 union perf_event *event __maybe_unused,
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001861 struct perf_sample *sample)
1862{
1863 u64 runtime = perf_evsel__intval(evsel, sample, "runtime");
1864 double runtime_ms = (double)runtime / NSEC_PER_MSEC;
David Ahern8fb598e2013-09-28 13:13:00 -06001865 struct thread *thread = machine__findnew_thread(trace->host,
Adrian Hunter314add62013-08-27 11:23:03 +03001866 sample->pid,
1867 sample->tid);
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001868 struct thread_trace *ttrace = thread__trace(thread, trace->output);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001869
1870 if (ttrace == NULL)
1871 goto out_dump;
1872
1873 ttrace->runtime_ms += runtime_ms;
1874 trace->runtime_ms += runtime_ms;
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001875 thread__put(thread);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001876 return 0;
1877
1878out_dump:
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001879 fprintf(trace->output, "%s: comm=%s,pid=%u,runtime=%" PRIu64 ",vruntime=%" PRIu64 ")\n",
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001880 evsel->name,
1881 perf_evsel__strval(evsel, sample, "comm"),
1882 (pid_t)perf_evsel__intval(evsel, sample, "pid"),
1883 runtime,
1884 perf_evsel__intval(evsel, sample, "vruntime"));
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001885 thread__put(thread);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001886 return 0;
1887}
1888
Wang Nan1d6c9402016-02-26 09:31:55 +00001889static void bpf_output__printer(enum binary_printer_ops op,
1890 unsigned int val, void *extra)
1891{
1892 FILE *output = extra;
1893 unsigned char ch = (unsigned char)val;
1894
1895 switch (op) {
1896 case BINARY_PRINT_CHAR_DATA:
1897 fprintf(output, "%c", isprint(ch) ? ch : '.');
1898 break;
1899 case BINARY_PRINT_DATA_BEGIN:
1900 case BINARY_PRINT_LINE_BEGIN:
1901 case BINARY_PRINT_ADDR:
1902 case BINARY_PRINT_NUM_DATA:
1903 case BINARY_PRINT_NUM_PAD:
1904 case BINARY_PRINT_SEP:
1905 case BINARY_PRINT_CHAR_PAD:
1906 case BINARY_PRINT_LINE_END:
1907 case BINARY_PRINT_DATA_END:
1908 default:
1909 break;
1910 }
1911}
1912
1913static void bpf_output__fprintf(struct trace *trace,
1914 struct perf_sample *sample)
1915{
1916 print_binary(sample->raw_data, sample->raw_size, 8,
1917 bpf_output__printer, trace->output);
1918}
1919
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03001920static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
1921 union perf_event *event __maybe_unused,
1922 struct perf_sample *sample)
1923{
Arnaldo Carvalho de Melo7ad35612016-04-20 19:55:48 -03001924 int callchain_ret = 0;
1925
1926 if (sample->callchain) {
1927 callchain_ret = trace__resolve_callchain(trace, evsel, sample, &callchain_cursor);
1928 if (callchain_ret == 0) {
1929 if (callchain_cursor.nr < trace->min_stack)
1930 goto out;
1931 callchain_ret = 1;
1932 }
1933 }
1934
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03001935 trace__printf_interrupted_entry(trace, sample);
1936 trace__fprintf_tstamp(trace, sample->time, trace->output);
Arnaldo Carvalho de Melo08089212015-02-19 21:51:50 -08001937
1938 if (trace->trace_syscalls)
1939 fprintf(trace->output, "( ): ");
1940
1941 fprintf(trace->output, "%s:", evsel->name);
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03001942
Wang Nan1d6c9402016-02-26 09:31:55 +00001943 if (perf_evsel__is_bpf_output(evsel)) {
1944 bpf_output__fprintf(trace, sample);
1945 } else if (evsel->tp_format) {
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03001946 event_format__fprintf(evsel->tp_format, sample->cpu,
1947 sample->raw_data, sample->raw_size,
1948 trace->output);
1949 }
1950
1951 fprintf(trace->output, ")\n");
Arnaldo Carvalho de Melo202ff962016-04-12 10:11:07 -03001952
Arnaldo Carvalho de Melo7ad35612016-04-20 19:55:48 -03001953 if (callchain_ret > 0)
1954 trace__fprintf_callchain(trace, sample);
1955 else if (callchain_ret < 0)
1956 pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel));
1957out:
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03001958 return 0;
1959}
1960
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04001961static void print_location(FILE *f, struct perf_sample *sample,
1962 struct addr_location *al,
1963 bool print_dso, bool print_sym)
1964{
1965
1966 if ((verbose || print_dso) && al->map)
1967 fprintf(f, "%s@", al->map->dso->long_name);
1968
1969 if ((verbose || print_sym) && al->sym)
Arnaldo Carvalho de Melo4414a3c2014-07-08 15:39:21 -03001970 fprintf(f, "%s+0x%" PRIx64, al->sym->name,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04001971 al->addr - al->sym->start);
1972 else if (al->map)
Arnaldo Carvalho de Melo4414a3c2014-07-08 15:39:21 -03001973 fprintf(f, "0x%" PRIx64, al->addr);
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04001974 else
Arnaldo Carvalho de Melo4414a3c2014-07-08 15:39:21 -03001975 fprintf(f, "0x%" PRIx64, sample->addr);
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04001976}
1977
1978static int trace__pgfault(struct trace *trace,
1979 struct perf_evsel *evsel,
Arnaldo Carvalho de Melo473398a2016-03-22 18:23:43 -03001980 union perf_event *event __maybe_unused,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04001981 struct perf_sample *sample)
1982{
1983 struct thread *thread;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04001984 struct addr_location al;
1985 char map_type = 'd';
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04001986 struct thread_trace *ttrace;
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001987 int err = -1;
Arnaldo Carvalho de Melo1df54292016-04-20 20:06:02 -03001988 int callchain_ret = 0;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04001989
1990 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
Arnaldo Carvalho de Melo1df54292016-04-20 20:06:02 -03001991
1992 if (sample->callchain) {
1993 callchain_ret = trace__resolve_callchain(trace, evsel, sample, &callchain_cursor);
1994 if (callchain_ret == 0) {
1995 if (callchain_cursor.nr < trace->min_stack)
1996 goto out_put;
1997 callchain_ret = 1;
1998 }
1999 }
2000
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04002001 ttrace = thread__trace(thread, trace->output);
2002 if (ttrace == NULL)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002003 goto out_put;
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04002004
2005 if (evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ)
2006 ttrace->pfmaj++;
2007 else
2008 ttrace->pfmin++;
2009
2010 if (trace->summary_only)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002011 goto out;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002012
Arnaldo Carvalho de Melo473398a2016-03-22 18:23:43 -03002013 thread__find_addr_location(thread, sample->cpumode, MAP__FUNCTION,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002014 sample->ip, &al);
2015
2016 trace__fprintf_entry_head(trace, thread, 0, sample->time, trace->output);
2017
2018 fprintf(trace->output, "%sfault [",
2019 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ?
2020 "maj" : "min");
2021
2022 print_location(trace->output, sample, &al, false, true);
2023
2024 fprintf(trace->output, "] => ");
2025
Arnaldo Carvalho de Melo473398a2016-03-22 18:23:43 -03002026 thread__find_addr_location(thread, sample->cpumode, MAP__VARIABLE,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002027 sample->addr, &al);
2028
2029 if (!al.map) {
Arnaldo Carvalho de Melo473398a2016-03-22 18:23:43 -03002030 thread__find_addr_location(thread, sample->cpumode,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002031 MAP__FUNCTION, sample->addr, &al);
2032
2033 if (al.map)
2034 map_type = 'x';
2035 else
2036 map_type = '?';
2037 }
2038
2039 print_location(trace->output, sample, &al, true, false);
2040
2041 fprintf(trace->output, " (%c%c)\n", map_type, al.level);
Arnaldo Carvalho de Melo0c3a6ef2016-04-19 16:31:12 -03002042
Arnaldo Carvalho de Melo1df54292016-04-20 20:06:02 -03002043 if (callchain_ret > 0)
2044 trace__fprintf_callchain(trace, sample);
2045 else if (callchain_ret < 0)
2046 pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel));
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002047out:
2048 err = 0;
2049out_put:
2050 thread__put(thread);
2051 return err;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002052}
2053
David Ahernbdc89662013-08-28 22:29:53 -06002054static bool skip_sample(struct trace *trace, struct perf_sample *sample)
2055{
2056 if ((trace->pid_list && intlist__find(trace->pid_list, sample->pid)) ||
2057 (trace->tid_list && intlist__find(trace->tid_list, sample->tid)))
2058 return false;
2059
2060 if (trace->pid_list || trace->tid_list)
2061 return true;
2062
2063 return false;
2064}
2065
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03002066static void trace__set_base_time(struct trace *trace,
Arnaldo Carvalho de Melo8a07a802016-03-31 15:19:39 -03002067 struct perf_evsel *evsel,
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03002068 struct perf_sample *sample)
2069{
Arnaldo Carvalho de Melo8a07a802016-03-31 15:19:39 -03002070 /*
2071 * BPF events were not setting PERF_SAMPLE_TIME, so be more robust
2072 * and don't use sample->time unconditionally, we may end up having
2073 * some other event in the future without PERF_SAMPLE_TIME for good
2074 * reason, i.e. we may not be interested in its timestamps, just in
2075 * it taking place, picking some piece of information when it
2076 * appears in our event stream (vfs_getname comes to mind).
2077 */
2078 if (trace->base_time == 0 && !trace->full_time &&
2079 (evsel->attr.sample_type & PERF_SAMPLE_TIME))
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03002080 trace->base_time = sample->time;
2081}
2082
David Ahern6810fc92013-08-28 22:29:52 -06002083static int trace__process_sample(struct perf_tool *tool,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04002084 union perf_event *event,
David Ahern6810fc92013-08-28 22:29:52 -06002085 struct perf_sample *sample,
2086 struct perf_evsel *evsel,
2087 struct machine *machine __maybe_unused)
2088{
2089 struct trace *trace = container_of(tool, struct trace, tool);
2090 int err = 0;
2091
Arnaldo Carvalho de Melo744a9712013-11-06 10:17:38 -03002092 tracepoint_handler handler = evsel->handler;
David Ahern6810fc92013-08-28 22:29:52 -06002093
David Ahernbdc89662013-08-28 22:29:53 -06002094 if (skip_sample(trace, sample))
2095 return 0;
2096
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03002097 trace__set_base_time(trace, evsel, sample);
David Ahern6810fc92013-08-28 22:29:52 -06002098
David Ahern31605652013-12-04 19:41:41 -07002099 if (handler) {
2100 ++trace->nr_events;
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04002101 handler(trace, evsel, event, sample);
David Ahern31605652013-12-04 19:41:41 -07002102 }
David Ahern6810fc92013-08-28 22:29:52 -06002103
2104 return err;
2105}
2106
David Ahernbdc89662013-08-28 22:29:53 -06002107static int parse_target_str(struct trace *trace)
2108{
2109 if (trace->opts.target.pid) {
2110 trace->pid_list = intlist__new(trace->opts.target.pid);
2111 if (trace->pid_list == NULL) {
2112 pr_err("Error parsing process id string\n");
2113 return -EINVAL;
2114 }
2115 }
2116
2117 if (trace->opts.target.tid) {
2118 trace->tid_list = intlist__new(trace->opts.target.tid);
2119 if (trace->tid_list == NULL) {
2120 pr_err("Error parsing thread id string\n");
2121 return -EINVAL;
2122 }
2123 }
2124
2125 return 0;
2126}
2127
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002128static int trace__record(struct trace *trace, int argc, const char **argv)
David Ahern5e2485b2013-09-28 13:13:01 -06002129{
2130 unsigned int rec_argc, i, j;
2131 const char **rec_argv;
2132 const char * const record_args[] = {
2133 "record",
2134 "-R",
2135 "-m", "1024",
2136 "-c", "1",
David Ahern5e2485b2013-09-28 13:13:01 -06002137 };
2138
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002139 const char * const sc_args[] = { "-e", };
2140 unsigned int sc_args_nr = ARRAY_SIZE(sc_args);
2141 const char * const majpf_args[] = { "-e", "major-faults" };
2142 unsigned int majpf_args_nr = ARRAY_SIZE(majpf_args);
2143 const char * const minpf_args[] = { "-e", "minor-faults" };
2144 unsigned int minpf_args_nr = ARRAY_SIZE(minpf_args);
2145
David Ahern9aca7f12013-12-04 19:41:39 -07002146 /* +1 is for the event string below */
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002147 rec_argc = ARRAY_SIZE(record_args) + sc_args_nr + 1 +
2148 majpf_args_nr + minpf_args_nr + argc;
David Ahern5e2485b2013-09-28 13:13:01 -06002149 rec_argv = calloc(rec_argc + 1, sizeof(char *));
2150
2151 if (rec_argv == NULL)
2152 return -ENOMEM;
2153
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002154 j = 0;
David Ahern5e2485b2013-09-28 13:13:01 -06002155 for (i = 0; i < ARRAY_SIZE(record_args); i++)
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002156 rec_argv[j++] = record_args[i];
2157
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002158 if (trace->trace_syscalls) {
2159 for (i = 0; i < sc_args_nr; i++)
2160 rec_argv[j++] = sc_args[i];
David Ahern5e2485b2013-09-28 13:13:01 -06002161
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002162 /* event string may be different for older kernels - e.g., RHEL6 */
2163 if (is_valid_tracepoint("raw_syscalls:sys_enter"))
2164 rec_argv[j++] = "raw_syscalls:sys_enter,raw_syscalls:sys_exit";
2165 else if (is_valid_tracepoint("syscalls:sys_enter"))
2166 rec_argv[j++] = "syscalls:sys_enter,syscalls:sys_exit";
2167 else {
2168 pr_err("Neither raw_syscalls nor syscalls events exist.\n");
2169 return -1;
2170 }
David Ahern9aca7f12013-12-04 19:41:39 -07002171 }
David Ahern9aca7f12013-12-04 19:41:39 -07002172
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002173 if (trace->trace_pgfaults & TRACE_PFMAJ)
2174 for (i = 0; i < majpf_args_nr; i++)
2175 rec_argv[j++] = majpf_args[i];
David Ahern5e2485b2013-09-28 13:13:01 -06002176
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002177 if (trace->trace_pgfaults & TRACE_PFMIN)
2178 for (i = 0; i < minpf_args_nr; i++)
2179 rec_argv[j++] = minpf_args[i];
2180
2181 for (i = 0; i < (unsigned int)argc; i++)
2182 rec_argv[j++] = argv[i];
2183
2184 return cmd_record(j, rec_argv, NULL);
David Ahern5e2485b2013-09-28 13:13:01 -06002185}
2186
David Ahernbf2575c2013-10-08 21:26:53 -06002187static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp);
2188
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002189static bool perf_evlist__add_vfs_getname(struct perf_evlist *evlist)
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002190{
Arnaldo Carvalho de Meloef503832013-11-07 16:41:19 -03002191 struct perf_evsel *evsel = perf_evsel__newtp("probe", "vfs_getname");
Jiri Olsa8dd2a132015-09-07 10:38:06 +02002192
2193 if (IS_ERR(evsel))
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002194 return false;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002195
2196 if (perf_evsel__field(evsel, "pathname") == NULL) {
2197 perf_evsel__delete(evsel);
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002198 return false;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002199 }
2200
Arnaldo Carvalho de Melo744a9712013-11-06 10:17:38 -03002201 evsel->handler = trace__vfs_getname;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002202 perf_evlist__add(evlist, evsel);
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002203 return true;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002204}
2205
Arnaldo Carvalho de Melo0ae537c2016-04-19 16:00:01 -03002206static struct perf_evsel *perf_evsel__new_pgfault(u64 config)
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002207{
2208 struct perf_evsel *evsel;
2209 struct perf_event_attr attr = {
2210 .type = PERF_TYPE_SOFTWARE,
2211 .mmap_data = 1,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002212 };
2213
2214 attr.config = config;
Arnaldo Carvalho de Melo05247982014-07-23 18:15:09 -03002215 attr.sample_period = 1;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002216
2217 event_attr_init(&attr);
2218
2219 evsel = perf_evsel__new(&attr);
Arnaldo Carvalho de Melo0ae537c2016-04-19 16:00:01 -03002220 if (evsel)
2221 evsel->handler = trace__pgfault;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002222
Arnaldo Carvalho de Melo0ae537c2016-04-19 16:00:01 -03002223 return evsel;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002224}
2225
Arnaldo Carvalho de Meloddbb1b12015-02-21 12:10:29 -08002226static void trace__handle_event(struct trace *trace, union perf_event *event, struct perf_sample *sample)
2227{
2228 const u32 type = event->header.type;
2229 struct perf_evsel *evsel;
2230
Arnaldo Carvalho de Meloddbb1b12015-02-21 12:10:29 -08002231 if (type != PERF_RECORD_SAMPLE) {
2232 trace__process_event(trace, trace->host, event, sample);
2233 return;
2234 }
2235
2236 evsel = perf_evlist__id2evsel(trace->evlist, sample->id);
2237 if (evsel == NULL) {
2238 fprintf(trace->output, "Unknown tp ID %" PRIu64 ", skipping...\n", sample->id);
2239 return;
2240 }
2241
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03002242 trace__set_base_time(trace, evsel, sample);
2243
Arnaldo Carvalho de Meloddbb1b12015-02-21 12:10:29 -08002244 if (evsel->attr.type == PERF_TYPE_TRACEPOINT &&
2245 sample->raw_data == NULL) {
2246 fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n",
2247 perf_evsel__name(evsel), sample->tid,
2248 sample->cpu, sample->raw_size);
2249 } else {
2250 tracepoint_handler handler = evsel->handler;
2251 handler(trace, evsel, event, sample);
2252 }
2253}
2254
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03002255static int trace__add_syscall_newtp(struct trace *trace)
2256{
2257 int ret = -1;
2258 struct perf_evlist *evlist = trace->evlist;
2259 struct perf_evsel *sys_enter, *sys_exit;
2260
2261 sys_enter = perf_evsel__syscall_newtp("sys_enter", trace__sys_enter);
2262 if (sys_enter == NULL)
2263 goto out;
2264
2265 if (perf_evsel__init_sc_tp_ptr_field(sys_enter, args))
2266 goto out_delete_sys_enter;
2267
2268 sys_exit = perf_evsel__syscall_newtp("sys_exit", trace__sys_exit);
2269 if (sys_exit == NULL)
2270 goto out_delete_sys_enter;
2271
2272 if (perf_evsel__init_sc_tp_uint_field(sys_exit, ret))
2273 goto out_delete_sys_exit;
2274
2275 perf_evlist__add(evlist, sys_enter);
2276 perf_evlist__add(evlist, sys_exit);
2277
Arnaldo Carvalho de Melo2ddd5c02016-04-18 12:09:08 -03002278 if (callchain_param.enabled && !trace->kernel_syscallchains) {
Arnaldo Carvalho de Melo44621812016-04-11 15:49:11 -03002279 /*
2280 * We're interested only in the user space callchain
2281 * leading to the syscall, allow overriding that for
2282 * debugging reasons using --kernel_syscall_callchains
2283 */
2284 sys_exit->attr.exclude_callchain_kernel = 1;
2285 }
2286
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03002287 trace->syscalls.events.sys_enter = sys_enter;
2288 trace->syscalls.events.sys_exit = sys_exit;
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03002289
2290 ret = 0;
2291out:
2292 return ret;
2293
2294out_delete_sys_exit:
2295 perf_evsel__delete_priv(sys_exit);
2296out_delete_sys_enter:
2297 perf_evsel__delete_priv(sys_enter);
2298 goto out;
2299}
2300
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002301static int trace__set_ev_qualifier_filter(struct trace *trace)
2302{
2303 int err = -1;
2304 char *filter = asprintf_expr_inout_ints("id", !trace->not_ev_qualifier,
2305 trace->ev_qualifier_ids.nr,
2306 trace->ev_qualifier_ids.entries);
2307
2308 if (filter == NULL)
2309 goto out_enomem;
2310
2311 if (!perf_evsel__append_filter(trace->syscalls.events.sys_enter, "&&", filter))
2312 err = perf_evsel__append_filter(trace->syscalls.events.sys_exit, "&&", filter);
2313
2314 free(filter);
2315out:
2316 return err;
2317out_enomem:
2318 errno = ENOMEM;
2319 goto out;
2320}
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03002321
Namhyung Kimf15eb532012-10-05 14:02:16 +09002322static int trace__run(struct trace *trace, int argc, const char **argv)
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002323{
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002324 struct perf_evlist *evlist = trace->evlist;
Arnaldo Carvalho de Melo0ae537c2016-04-19 16:00:01 -03002325 struct perf_evsel *evsel, *pgfault_maj = NULL, *pgfault_min = NULL;
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03002326 int err = -1, i;
2327 unsigned long before;
Namhyung Kimf15eb532012-10-05 14:02:16 +09002328 const bool forks = argc > 0;
Arnaldo Carvalho de Melo46fb3c22014-09-22 14:39:48 -03002329 bool draining = false;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002330
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03002331 trace->live = true;
2332
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03002333 if (trace->trace_syscalls && trace__add_syscall_newtp(trace))
Arnaldo Carvalho de Melo801c67b2015-01-22 10:52:55 -03002334 goto out_error_raw_syscalls;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002335
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002336 if (trace->trace_syscalls)
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002337 trace->vfs_getname = perf_evlist__add_vfs_getname(evlist);
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002338
Arnaldo Carvalho de Melo0ae537c2016-04-19 16:00:01 -03002339 if ((trace->trace_pgfaults & TRACE_PFMAJ)) {
2340 pgfault_maj = perf_evsel__new_pgfault(PERF_COUNT_SW_PAGE_FAULTS_MAJ);
2341 if (pgfault_maj == NULL)
2342 goto out_error_mem;
2343 perf_evlist__add(evlist, pgfault_maj);
Arnaldo Carvalho de Meloe2726d92015-01-22 10:34:22 -03002344 }
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002345
Arnaldo Carvalho de Melo0ae537c2016-04-19 16:00:01 -03002346 if ((trace->trace_pgfaults & TRACE_PFMIN)) {
2347 pgfault_min = perf_evsel__new_pgfault(PERF_COUNT_SW_PAGE_FAULTS_MIN);
2348 if (pgfault_min == NULL)
2349 goto out_error_mem;
2350 perf_evlist__add(evlist, pgfault_min);
2351 }
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002352
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002353 if (trace->sched &&
Arnaldo Carvalho de Melo2cc990b2015-01-22 11:13:43 -03002354 perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime",
2355 trace__sched_stat_runtime))
2356 goto out_error_sched_stat_runtime;
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002357
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002358 err = perf_evlist__create_maps(evlist, &trace->opts.target);
2359 if (err < 0) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002360 fprintf(trace->output, "Problems parsing the target to trace, check your options!\n");
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002361 goto out_delete_evlist;
2362 }
2363
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03002364 err = trace__symbols_init(trace, evlist);
2365 if (err < 0) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002366 fprintf(trace->output, "Problems initializing symbol libraries!\n");
Arnaldo Carvalho de Melo03ad9742014-01-03 15:56:06 -03002367 goto out_delete_evlist;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03002368 }
2369
Arnaldo Carvalho de Melofde54b72016-04-11 18:42:37 -03002370 perf_evlist__config(evlist, &trace->opts, NULL);
2371
Arnaldo Carvalho de Melo0c3a6ef2016-04-19 16:31:12 -03002372 if (callchain_param.enabled) {
2373 bool use_identifier = false;
2374
2375 if (trace->syscalls.events.sys_exit) {
2376 perf_evsel__config_callchain(trace->syscalls.events.sys_exit,
2377 &trace->opts, &callchain_param);
2378 use_identifier = true;
2379 }
2380
2381 if (pgfault_maj) {
2382 perf_evsel__config_callchain(pgfault_maj, &trace->opts, &callchain_param);
2383 use_identifier = true;
2384 }
2385
2386 if (pgfault_min) {
2387 perf_evsel__config_callchain(pgfault_min, &trace->opts, &callchain_param);
2388 use_identifier = true;
2389 }
2390
2391 if (use_identifier) {
2392 /*
2393 * Now we have evsels with different sample_ids, use
2394 * PERF_SAMPLE_IDENTIFIER to map from sample to evsel
2395 * from a fixed position in each ring buffer record.
2396 *
2397 * As of this the changeset introducing this comment, this
2398 * isn't strictly needed, as the fields that can come before
2399 * PERF_SAMPLE_ID are all used, but we'll probably disable
2400 * some of those for things like copying the payload of
2401 * pointer syscall arguments, and for vfs_getname we don't
2402 * need PERF_SAMPLE_ADDR and PERF_SAMPLE_IP, so do this
2403 * here as a warning we need to use PERF_SAMPLE_IDENTIFIER.
2404 */
2405 perf_evlist__set_sample_bit(evlist, IDENTIFIER);
2406 perf_evlist__reset_sample_bit(evlist, ID);
2407 }
Arnaldo Carvalho de Melofde54b72016-04-11 18:42:37 -03002408 }
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002409
Namhyung Kimf15eb532012-10-05 14:02:16 +09002410 signal(SIGCHLD, sig_handler);
2411 signal(SIGINT, sig_handler);
2412
2413 if (forks) {
Namhyung Kim6ef73ec2013-03-11 16:43:15 +09002414 err = perf_evlist__prepare_workload(evlist, &trace->opts.target,
Arnaldo Carvalho de Melo735f7e02014-01-03 14:56:49 -03002415 argv, false, NULL);
Namhyung Kimf15eb532012-10-05 14:02:16 +09002416 if (err < 0) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002417 fprintf(trace->output, "Couldn't run the workload!\n");
Arnaldo Carvalho de Melo03ad9742014-01-03 15:56:06 -03002418 goto out_delete_evlist;
Namhyung Kimf15eb532012-10-05 14:02:16 +09002419 }
2420 }
2421
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002422 err = perf_evlist__open(evlist);
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002423 if (err < 0)
2424 goto out_error_open;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002425
Wang Nanba504232016-02-26 09:31:54 +00002426 err = bpf__apply_obj_config();
2427 if (err) {
2428 char errbuf[BUFSIZ];
2429
2430 bpf__strerror_apply_obj_config(err, errbuf, sizeof(errbuf));
2431 pr_err("ERROR: Apply config to BPF failed: %s\n",
2432 errbuf);
2433 goto out_error_open;
2434 }
2435
Arnaldo Carvalho de Melo241b0572015-02-21 10:15:21 -08002436 /*
2437 * Better not use !target__has_task() here because we need to cover the
2438 * case where no threads were specified in the command line, but a
2439 * workload was, and in that case we will fill in the thread_map when
2440 * we fork the workload in perf_evlist__prepare_workload.
2441 */
Arnaldo Carvalho de Melof078c382015-02-21 11:36:52 -08002442 if (trace->filter_pids.nr > 0)
2443 err = perf_evlist__set_filter_pids(evlist, trace->filter_pids.nr, trace->filter_pids.entries);
Jiri Olsae13798c2015-06-23 00:36:02 +02002444 else if (thread_map__pid(evlist->threads, 0) == -1)
Arnaldo Carvalho de Melof078c382015-02-21 11:36:52 -08002445 err = perf_evlist__set_filter_pid(evlist, getpid());
2446
Arnaldo Carvalho de Melo94ad89b2015-07-03 17:42:03 -03002447 if (err < 0)
2448 goto out_error_mem;
2449
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002450 if (trace->ev_qualifier_ids.nr > 0) {
2451 err = trace__set_ev_qualifier_filter(trace);
2452 if (err < 0)
2453 goto out_errno;
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002454
Arnaldo Carvalho de Melo2e5e5f82015-08-03 17:12:29 -03002455 pr_debug("event qualifier tracepoint filter: %s\n",
2456 trace->syscalls.events.sys_exit->filter);
2457 }
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002458
Arnaldo Carvalho de Melo94ad89b2015-07-03 17:42:03 -03002459 err = perf_evlist__apply_filters(evlist, &evsel);
2460 if (err < 0)
2461 goto out_error_apply_filters;
Arnaldo Carvalho de Melo241b0572015-02-21 10:15:21 -08002462
Jiri Olsaf8850372013-11-28 17:57:22 +01002463 err = perf_evlist__mmap(evlist, trace->opts.mmap_pages, false);
Arnaldo Carvalho de Meloe09b18d2014-12-11 18:04:10 -03002464 if (err < 0)
2465 goto out_error_mmap;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002466
Arnaldo Carvalho de Melocb24d012015-04-22 10:04:23 -03002467 if (!target__none(&trace->opts.target))
2468 perf_evlist__enable(evlist);
2469
Namhyung Kimf15eb532012-10-05 14:02:16 +09002470 if (forks)
2471 perf_evlist__start_workload(evlist);
2472
Jiri Olsae13798c2015-06-23 00:36:02 +02002473 trace->multiple_threads = thread_map__pid(evlist->threads, 0) == -1 ||
Arnaldo Carvalho de Melo42052be2015-02-13 12:32:45 -03002474 evlist->threads->nr > 1 ||
2475 perf_evlist__first(evlist)->attr.inherit;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002476again:
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03002477 before = trace->nr_events;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002478
2479 for (i = 0; i < evlist->nr_mmaps; i++) {
2480 union perf_event *event;
2481
2482 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002483 struct perf_sample sample;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002484
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03002485 ++trace->nr_events;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002486
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002487 err = perf_evlist__parse_sample(evlist, event, &sample);
2488 if (err) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002489 fprintf(trace->output, "Can't parse sample, err = %d, skipping...\n", err);
Zhouyi Zhou8e50d382013-10-24 15:43:33 +08002490 goto next_event;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002491 }
2492
Arnaldo Carvalho de Meloddbb1b12015-02-21 12:10:29 -08002493 trace__handle_event(trace, event, &sample);
Zhouyi Zhou8e50d382013-10-24 15:43:33 +08002494next_event:
2495 perf_evlist__mmap_consume(evlist, i);
Arnaldo Carvalho de Melo20c5f102013-09-03 11:55:07 -03002496
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002497 if (interrupted)
2498 goto out_disable;
Arnaldo Carvalho de Melo02ac5422015-04-22 11:11:57 -03002499
2500 if (done && !draining) {
2501 perf_evlist__disable(evlist);
2502 draining = true;
2503 }
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002504 }
2505 }
2506
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03002507 if (trace->nr_events == before) {
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002508 int timeout = done ? 100 : -1;
Namhyung Kimf15eb532012-10-05 14:02:16 +09002509
Arnaldo Carvalho de Melo46fb3c22014-09-22 14:39:48 -03002510 if (!draining && perf_evlist__poll(evlist, timeout) > 0) {
2511 if (perf_evlist__filter_pollfd(evlist, POLLERR | POLLHUP) == 0)
2512 draining = true;
2513
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002514 goto again;
Arnaldo Carvalho de Melo46fb3c22014-09-22 14:39:48 -03002515 }
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002516 } else {
2517 goto again;
Namhyung Kimf15eb532012-10-05 14:02:16 +09002518 }
2519
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002520out_disable:
Arnaldo Carvalho de Melof3b623b2015-03-02 22:21:35 -03002521 thread__zput(trace->current);
2522
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002523 perf_evlist__disable(evlist);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002524
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002525 if (!err) {
2526 if (trace->summary)
2527 trace__fprintf_thread_summary(trace, trace->output);
2528
2529 if (trace->show_tool_stats) {
2530 fprintf(trace->output, "Stats:\n "
2531 " vfs_getname : %" PRIu64 "\n"
2532 " proc_getname: %" PRIu64 "\n",
2533 trace->stats.vfs_getname,
2534 trace->stats.proc_getname);
2535 }
2536 }
David Ahernbf2575c2013-10-08 21:26:53 -06002537
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002538out_delete_evlist:
2539 perf_evlist__delete(evlist);
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002540 trace->evlist = NULL;
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03002541 trace->live = false;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002542 return err;
Arnaldo Carvalho de Melo6ef068c2013-10-17 12:07:58 -03002543{
2544 char errbuf[BUFSIZ];
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002545
Arnaldo Carvalho de Melo2cc990b2015-01-22 11:13:43 -03002546out_error_sched_stat_runtime:
Jiri Olsa988bdb32015-09-02 09:56:35 +02002547 tracing_path__strerror_open_tp(errno, errbuf, sizeof(errbuf), "sched", "sched_stat_runtime");
Arnaldo Carvalho de Melo2cc990b2015-01-22 11:13:43 -03002548 goto out_error;
2549
Arnaldo Carvalho de Melo801c67b2015-01-22 10:52:55 -03002550out_error_raw_syscalls:
Jiri Olsa988bdb32015-09-02 09:56:35 +02002551 tracing_path__strerror_open_tp(errno, errbuf, sizeof(errbuf), "raw_syscalls", "sys_(enter|exit)");
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002552 goto out_error;
2553
Arnaldo Carvalho de Meloe09b18d2014-12-11 18:04:10 -03002554out_error_mmap:
2555 perf_evlist__strerror_mmap(evlist, errno, errbuf, sizeof(errbuf));
2556 goto out_error;
2557
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002558out_error_open:
2559 perf_evlist__strerror_open(evlist, errno, errbuf, sizeof(errbuf));
2560
2561out_error:
Arnaldo Carvalho de Melo6ef068c2013-10-17 12:07:58 -03002562 fprintf(trace->output, "%s\n", errbuf);
Ramkumar Ramachandra87f91862013-10-04 10:47:31 +05302563 goto out_delete_evlist;
Arnaldo Carvalho de Melo94ad89b2015-07-03 17:42:03 -03002564
2565out_error_apply_filters:
2566 fprintf(trace->output,
2567 "Failed to set filter \"%s\" on event %s with %d (%s)\n",
2568 evsel->filter, perf_evsel__name(evsel), errno,
2569 strerror_r(errno, errbuf, sizeof(errbuf)));
2570 goto out_delete_evlist;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002571}
Arnaldo Carvalho de Melo5ed08da2015-01-22 11:08:04 -03002572out_error_mem:
2573 fprintf(trace->output, "Not enough memory to run!\n");
2574 goto out_delete_evlist;
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002575
2576out_errno:
2577 fprintf(trace->output, "errno=%d,%s\n", errno, strerror(errno));
2578 goto out_delete_evlist;
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002579}
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002580
David Ahern6810fc92013-08-28 22:29:52 -06002581static int trace__replay(struct trace *trace)
2582{
2583 const struct perf_evsel_str_handler handlers[] = {
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002584 { "probe:vfs_getname", trace__vfs_getname, },
David Ahern6810fc92013-08-28 22:29:52 -06002585 };
Jiri Olsaf5fc14122013-10-15 16:27:32 +02002586 struct perf_data_file file = {
2587 .path = input_name,
2588 .mode = PERF_DATA_MODE_READ,
Yunlong Songe366a6d2015-04-02 21:47:18 +08002589 .force = trace->force,
Jiri Olsaf5fc14122013-10-15 16:27:32 +02002590 };
David Ahern6810fc92013-08-28 22:29:52 -06002591 struct perf_session *session;
Namhyung Kim003824e2013-11-12 15:25:00 +09002592 struct perf_evsel *evsel;
David Ahern6810fc92013-08-28 22:29:52 -06002593 int err = -1;
2594
2595 trace->tool.sample = trace__process_sample;
2596 trace->tool.mmap = perf_event__process_mmap;
David Ahern384c6712013-09-22 19:44:58 -06002597 trace->tool.mmap2 = perf_event__process_mmap2;
David Ahern6810fc92013-08-28 22:29:52 -06002598 trace->tool.comm = perf_event__process_comm;
2599 trace->tool.exit = perf_event__process_exit;
2600 trace->tool.fork = perf_event__process_fork;
2601 trace->tool.attr = perf_event__process_attr;
2602 trace->tool.tracing_data = perf_event__process_tracing_data;
2603 trace->tool.build_id = perf_event__process_build_id;
2604
Jiri Olsa0a8cb852014-07-06 14:18:21 +02002605 trace->tool.ordered_events = true;
David Ahern6810fc92013-08-28 22:29:52 -06002606 trace->tool.ordering_requires_timestamps = true;
2607
2608 /* add tid to output */
2609 trace->multiple_threads = true;
2610
Jiri Olsaf5fc14122013-10-15 16:27:32 +02002611 session = perf_session__new(&file, false, &trace->tool);
David Ahern6810fc92013-08-28 22:29:52 -06002612 if (session == NULL)
Taeung Song52e028342014-09-24 10:33:37 +09002613 return -1;
David Ahern6810fc92013-08-28 22:29:52 -06002614
Namhyung Kim0a7e6d12014-08-12 15:40:45 +09002615 if (symbol__init(&session->header.env) < 0)
Namhyung Kimcb2ffae2014-08-12 15:40:44 +09002616 goto out;
2617
David Ahern8fb598e2013-09-28 13:13:00 -06002618 trace->host = &session->machines.host;
2619
David Ahern6810fc92013-08-28 22:29:52 -06002620 err = perf_session__set_tracepoints_handlers(session, handlers);
2621 if (err)
2622 goto out;
2623
Namhyung Kim003824e2013-11-12 15:25:00 +09002624 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2625 "raw_syscalls:sys_enter");
David Ahern9aca7f12013-12-04 19:41:39 -07002626 /* older kernels have syscalls tp versus raw_syscalls */
2627 if (evsel == NULL)
2628 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2629 "syscalls:sys_enter");
David Ahern6810fc92013-08-28 22:29:52 -06002630
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002631 if (evsel &&
2632 (perf_evsel__init_syscall_tp(evsel, trace__sys_enter) < 0 ||
2633 perf_evsel__init_sc_tp_ptr_field(evsel, args))) {
Namhyung Kim003824e2013-11-12 15:25:00 +09002634 pr_err("Error during initialize raw_syscalls:sys_enter event\n");
2635 goto out;
2636 }
2637
2638 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2639 "raw_syscalls:sys_exit");
David Ahern9aca7f12013-12-04 19:41:39 -07002640 if (evsel == NULL)
2641 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2642 "syscalls:sys_exit");
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002643 if (evsel &&
2644 (perf_evsel__init_syscall_tp(evsel, trace__sys_exit) < 0 ||
2645 perf_evsel__init_sc_tp_uint_field(evsel, ret))) {
Namhyung Kim003824e2013-11-12 15:25:00 +09002646 pr_err("Error during initialize raw_syscalls:sys_exit event\n");
David Ahern6810fc92013-08-28 22:29:52 -06002647 goto out;
2648 }
2649
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002650 evlist__for_each(session->evlist, evsel) {
2651 if (evsel->attr.type == PERF_TYPE_SOFTWARE &&
2652 (evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ||
2653 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MIN ||
2654 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS))
2655 evsel->handler = trace__pgfault;
2656 }
2657
David Ahernbdc89662013-08-28 22:29:53 -06002658 err = parse_target_str(trace);
2659 if (err != 0)
2660 goto out;
2661
David Ahern6810fc92013-08-28 22:29:52 -06002662 setup_pager();
2663
Arnaldo Carvalho de Melob7b61cb2015-03-03 11:58:45 -03002664 err = perf_session__process_events(session);
David Ahern6810fc92013-08-28 22:29:52 -06002665 if (err)
2666 pr_err("Failed to process events, error %d", err);
2667
David Ahernbf2575c2013-10-08 21:26:53 -06002668 else if (trace->summary)
2669 trace__fprintf_thread_summary(trace, trace->output);
2670
David Ahern6810fc92013-08-28 22:29:52 -06002671out:
2672 perf_session__delete(session);
2673
2674 return err;
2675}
2676
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002677static size_t trace__fprintf_threads_header(FILE *fp)
2678{
2679 size_t printed;
2680
Pekka Enberg99ff7152013-11-12 16:42:14 +02002681 printed = fprintf(fp, "\n Summary of events:\n\n");
David Ahernbf2575c2013-10-08 21:26:53 -06002682
2683 return printed;
2684}
2685
Arnaldo Carvalho de Melob535d522016-05-04 16:06:26 -03002686DEFINE_RESORT_RB(syscall_stats, a->msecs > b->msecs,
2687 struct stats *stats;
2688 double msecs;
2689 int syscall;
2690)
2691{
2692 struct int_node *source = rb_entry(nd, struct int_node, rb_node);
2693 struct stats *stats = source->priv;
2694
2695 entry->syscall = source->i;
2696 entry->stats = stats;
2697 entry->msecs = stats ? (u64)stats->n * (avg_stats(stats) / NSEC_PER_MSEC) : 0;
2698}
2699
David Ahernbf2575c2013-10-08 21:26:53 -06002700static size_t thread__dump_stats(struct thread_trace *ttrace,
2701 struct trace *trace, FILE *fp)
2702{
David Ahernbf2575c2013-10-08 21:26:53 -06002703 size_t printed = 0;
2704 struct syscall *sc;
Arnaldo Carvalho de Melob535d522016-05-04 16:06:26 -03002705 struct rb_node *nd;
2706 DECLARE_RESORT_RB_INTLIST(syscall_stats, ttrace->syscall_stats);
David Ahernbf2575c2013-10-08 21:26:53 -06002707
Arnaldo Carvalho de Melob535d522016-05-04 16:06:26 -03002708 if (syscall_stats == NULL)
David Ahernbf2575c2013-10-08 21:26:53 -06002709 return 0;
2710
2711 printed += fprintf(fp, "\n");
2712
Milian Wolff834fd462015-08-06 11:24:29 +02002713 printed += fprintf(fp, " syscall calls total min avg max stddev\n");
2714 printed += fprintf(fp, " (msec) (msec) (msec) (msec) (%%)\n");
2715 printed += fprintf(fp, " --------------- -------- --------- --------- --------- --------- ------\n");
Pekka Enberg99ff7152013-11-12 16:42:14 +02002716
Arnaldo Carvalho de Melob535d522016-05-04 16:06:26 -03002717 resort_rb__for_each(nd, syscall_stats) {
2718 struct stats *stats = syscall_stats_entry->stats;
David Ahernbf2575c2013-10-08 21:26:53 -06002719 if (stats) {
2720 double min = (double)(stats->min) / NSEC_PER_MSEC;
2721 double max = (double)(stats->max) / NSEC_PER_MSEC;
2722 double avg = avg_stats(stats);
2723 double pct;
2724 u64 n = (u64) stats->n;
2725
2726 pct = avg ? 100.0 * stddev_stats(stats)/avg : 0.0;
2727 avg /= NSEC_PER_MSEC;
2728
Arnaldo Carvalho de Melob535d522016-05-04 16:06:26 -03002729 sc = &trace->syscalls.table[syscall_stats_entry->syscall];
Pekka Enberg99ff7152013-11-12 16:42:14 +02002730 printed += fprintf(fp, " %-15s", sc->name);
Milian Wolff834fd462015-08-06 11:24:29 +02002731 printed += fprintf(fp, " %8" PRIu64 " %9.3f %9.3f %9.3f",
Arnaldo Carvalho de Melob535d522016-05-04 16:06:26 -03002732 n, syscall_stats_entry->msecs, min, avg);
Pekka Enberg27a778b2013-11-13 14:21:48 +02002733 printed += fprintf(fp, " %9.3f %9.2f%%\n", max, pct);
David Ahernbf2575c2013-10-08 21:26:53 -06002734 }
David Ahernbf2575c2013-10-08 21:26:53 -06002735 }
2736
Arnaldo Carvalho de Melob535d522016-05-04 16:06:26 -03002737 resort_rb__delete(syscall_stats);
David Ahernbf2575c2013-10-08 21:26:53 -06002738 printed += fprintf(fp, "\n\n");
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002739
2740 return printed;
2741}
2742
Arnaldo Carvalho de Melo96c14452016-05-04 12:47:16 -03002743static size_t trace__fprintf_thread(FILE *fp, struct thread *thread, struct trace *trace)
David Ahern896cbb52013-09-28 13:12:59 -06002744{
Arnaldo Carvalho de Melo96c14452016-05-04 12:47:16 -03002745 size_t printed = 0;
Namhyung Kim89dceb22014-10-06 09:46:03 +09002746 struct thread_trace *ttrace = thread__priv(thread);
David Ahern896cbb52013-09-28 13:12:59 -06002747 double ratio;
2748
2749 if (ttrace == NULL)
2750 return 0;
2751
2752 ratio = (double)ttrace->nr_events / trace->nr_events * 100.0;
2753
Pekka Enberg15e65c62013-11-14 18:43:30 +02002754 printed += fprintf(fp, " %s (%d), ", thread__comm_str(thread), thread->tid);
Pekka Enberg99ff7152013-11-12 16:42:14 +02002755 printed += fprintf(fp, "%lu events, ", ttrace->nr_events);
Pekka Enberg15e65c62013-11-14 18:43:30 +02002756 printed += fprintf(fp, "%.1f%%", ratio);
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04002757 if (ttrace->pfmaj)
2758 printed += fprintf(fp, ", %lu majfaults", ttrace->pfmaj);
2759 if (ttrace->pfmin)
2760 printed += fprintf(fp, ", %lu minfaults", ttrace->pfmin);
Arnaldo Carvalho de Melo03548eb2016-05-05 15:46:50 -03002761 if (trace->sched)
2762 printed += fprintf(fp, ", %.3f msec\n", ttrace->runtime_ms);
2763 else if (fputc('\n', fp) != EOF)
2764 ++printed;
2765
David Ahernbf2575c2013-10-08 21:26:53 -06002766 printed += thread__dump_stats(ttrace, trace, fp);
David Ahern896cbb52013-09-28 13:12:59 -06002767
Arnaldo Carvalho de Melo96c14452016-05-04 12:47:16 -03002768 return printed;
2769}
David Ahern896cbb52013-09-28 13:12:59 -06002770
Arnaldo Carvalho de Melo96c14452016-05-04 12:47:16 -03002771static unsigned long thread__nr_events(struct thread_trace *ttrace)
2772{
2773 return ttrace ? ttrace->nr_events : 0;
2774}
2775
2776DEFINE_RESORT_RB(threads, (thread__nr_events(a->thread->priv) < thread__nr_events(b->thread->priv)),
2777 struct thread *thread;
2778)
2779{
2780 entry->thread = rb_entry(nd, struct thread, rb_node);
David Ahern896cbb52013-09-28 13:12:59 -06002781}
2782
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002783static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp)
2784{
Arnaldo Carvalho de Melo96c14452016-05-04 12:47:16 -03002785 DECLARE_RESORT_RB_MACHINE_THREADS(threads, trace->host);
2786 size_t printed = trace__fprintf_threads_header(fp);
2787 struct rb_node *nd;
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002788
Arnaldo Carvalho de Melo96c14452016-05-04 12:47:16 -03002789 if (threads == NULL) {
2790 fprintf(fp, "%s", "Error sorting output by nr_events!\n");
2791 return 0;
2792 }
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002793
Arnaldo Carvalho de Melo96c14452016-05-04 12:47:16 -03002794 resort_rb__for_each(nd, threads)
2795 printed += trace__fprintf_thread(fp, threads_entry->thread, trace);
2796
2797 resort_rb__delete(threads);
2798
2799 return printed;
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002800}
2801
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03002802static int trace__set_duration(const struct option *opt, const char *str,
2803 int unset __maybe_unused)
2804{
2805 struct trace *trace = opt->value;
2806
2807 trace->duration_filter = atof(str);
2808 return 0;
2809}
2810
Arnaldo Carvalho de Melof078c382015-02-21 11:36:52 -08002811static int trace__set_filter_pids(const struct option *opt, const char *str,
2812 int unset __maybe_unused)
2813{
2814 int ret = -1;
2815 size_t i;
2816 struct trace *trace = opt->value;
2817 /*
2818 * FIXME: introduce a intarray class, plain parse csv and create a
2819 * { int nr, int entries[] } struct...
2820 */
2821 struct intlist *list = intlist__new(str);
2822
2823 if (list == NULL)
2824 return -1;
2825
2826 i = trace->filter_pids.nr = intlist__nr_entries(list) + 1;
2827 trace->filter_pids.entries = calloc(i, sizeof(pid_t));
2828
2829 if (trace->filter_pids.entries == NULL)
2830 goto out;
2831
2832 trace->filter_pids.entries[0] = getpid();
2833
2834 for (i = 1; i < trace->filter_pids.nr; ++i)
2835 trace->filter_pids.entries[i] = intlist__entry(list, i - 1)->i;
2836
2837 intlist__delete(list);
2838 ret = 0;
2839out:
2840 return ret;
2841}
2842
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002843static int trace__open_output(struct trace *trace, const char *filename)
2844{
2845 struct stat st;
2846
2847 if (!stat(filename, &st) && st.st_size) {
2848 char oldname[PATH_MAX];
2849
2850 scnprintf(oldname, sizeof(oldname), "%s.old", filename);
2851 unlink(oldname);
2852 rename(filename, oldname);
2853 }
2854
2855 trace->output = fopen(filename, "w");
2856
2857 return trace->output == NULL ? -errno : 0;
2858}
2859
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002860static int parse_pagefaults(const struct option *opt, const char *str,
2861 int unset __maybe_unused)
2862{
2863 int *trace_pgfaults = opt->value;
2864
2865 if (strcmp(str, "all") == 0)
2866 *trace_pgfaults |= TRACE_PFMAJ | TRACE_PFMIN;
2867 else if (strcmp(str, "maj") == 0)
2868 *trace_pgfaults |= TRACE_PFMAJ;
2869 else if (strcmp(str, "min") == 0)
2870 *trace_pgfaults |= TRACE_PFMIN;
2871 else
2872 return -1;
2873
2874 return 0;
2875}
2876
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002877static void evlist__set_evsel_handler(struct perf_evlist *evlist, void *handler)
2878{
2879 struct perf_evsel *evsel;
2880
2881 evlist__for_each(evlist, evsel)
2882 evsel->handler = handler;
2883}
2884
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002885int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
2886{
Yunlong Song6fdd9cb2015-03-18 21:35:57 +08002887 const char *trace_usage[] = {
Namhyung Kimf15eb532012-10-05 14:02:16 +09002888 "perf trace [<options>] [<command>]",
2889 "perf trace [<options>] -- <command> [<options>]",
David Ahern5e2485b2013-09-28 13:13:01 -06002890 "perf trace record [<options>] [<command>]",
2891 "perf trace record [<options>] -- <command> [<options>]",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002892 NULL
2893 };
2894 struct trace trace = {
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002895 .syscalls = {
2896 . max = -1,
2897 },
2898 .opts = {
2899 .target = {
2900 .uid = UINT_MAX,
2901 .uses_mmap = true,
2902 },
2903 .user_freq = UINT_MAX,
2904 .user_interval = ULLONG_MAX,
Arnaldo Carvalho de Melo509051e2014-01-14 17:52:14 -03002905 .no_buffering = true,
Arnaldo Carvalho de Melo38d54472014-12-12 17:28:32 -03002906 .mmap_pages = UINT_MAX,
Kan Liang9d9cad72015-06-17 09:51:11 -04002907 .proc_map_timeout = 500,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002908 },
Milian Wolff007d66a2015-08-05 16:52:23 -03002909 .output = stderr,
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -03002910 .show_comm = true,
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002911 .trace_syscalls = true,
Arnaldo Carvalho de Melo44621812016-04-11 15:49:11 -03002912 .kernel_syscallchains = false,
Arnaldo Carvalho de Melo05614992016-04-15 16:41:19 -03002913 .max_stack = UINT_MAX,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002914 };
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002915 const char *output_name = NULL;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03002916 const char *ev_qualifier_str = NULL;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002917 const struct option trace_options[] = {
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002918 OPT_CALLBACK(0, "event", &trace.evlist, "event",
2919 "event selector. use 'perf list' to list available events",
2920 parse_events_option),
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -03002921 OPT_BOOLEAN(0, "comm", &trace.show_comm,
2922 "show the thread COMM next to its id"),
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002923 OPT_BOOLEAN(0, "tool_stats", &trace.show_tool_stats, "show tool stats"),
Arnaldo Carvalho de Melod303e852015-04-23 12:02:07 -03002924 OPT_STRING('e', "expr", &ev_qualifier_str, "expr", "list of syscalls to trace"),
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002925 OPT_STRING('o', "output", &output_name, "file", "output file name"),
David Ahern6810fc92013-08-28 22:29:52 -06002926 OPT_STRING('i', "input", &input_name, "file", "Analyze events in file"),
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002927 OPT_STRING('p', "pid", &trace.opts.target.pid, "pid",
2928 "trace events on existing process id"),
David Ahernac9be8e2013-08-20 11:15:45 -06002929 OPT_STRING('t', "tid", &trace.opts.target.tid, "tid",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002930 "trace events on existing thread id"),
Arnaldo Carvalho de Melofa0e4ff2015-04-23 11:59:20 -03002931 OPT_CALLBACK(0, "filter-pids", &trace, "CSV list of pids",
2932 "pids to filter (by the kernel)", trace__set_filter_pids),
David Ahernac9be8e2013-08-20 11:15:45 -06002933 OPT_BOOLEAN('a', "all-cpus", &trace.opts.target.system_wide,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002934 "system-wide collection from all CPUs"),
David Ahernac9be8e2013-08-20 11:15:45 -06002935 OPT_STRING('C', "cpu", &trace.opts.target.cpu_list, "cpu",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002936 "list of cpus to monitor"),
David Ahern6810fc92013-08-28 22:29:52 -06002937 OPT_BOOLEAN(0, "no-inherit", &trace.opts.no_inherit,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002938 "child tasks do not inherit counters"),
Jiri Olsa994a1f72013-09-01 12:36:12 +02002939 OPT_CALLBACK('m', "mmap-pages", &trace.opts.mmap_pages, "pages",
2940 "number of mmap data pages",
2941 perf_evlist__parse_mmap_pages),
David Ahernac9be8e2013-08-20 11:15:45 -06002942 OPT_STRING('u', "uid", &trace.opts.target.uid_str, "user",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002943 "user to profile"),
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03002944 OPT_CALLBACK(0, "duration", &trace, "float",
2945 "show only events with duration > N.M ms",
2946 trace__set_duration),
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002947 OPT_BOOLEAN(0, "sched", &trace.sched, "show blocking scheduler events"),
Arnaldo Carvalho de Melo7c304ee02013-08-22 16:49:54 -03002948 OPT_INCR('v', "verbose", &verbose, "be more verbose"),
David Ahern4bb09192013-09-04 12:37:43 -06002949 OPT_BOOLEAN('T', "time", &trace.full_time,
2950 "Show full timestamp, not time relative to first start"),
David Ahernfd2eaba2013-11-12 09:31:15 -07002951 OPT_BOOLEAN('s', "summary", &trace.summary_only,
2952 "Show only syscall summary with statistics"),
2953 OPT_BOOLEAN('S', "with-summary", &trace.summary,
2954 "Show all syscalls and summary with statistics"),
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002955 OPT_CALLBACK_DEFAULT('F', "pf", &trace.trace_pgfaults, "all|maj|min",
2956 "Trace pagefaults", parse_pagefaults, "maj"),
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002957 OPT_BOOLEAN(0, "syscalls", &trace.trace_syscalls, "Trace syscalls"),
Yunlong Songe366a6d2015-04-02 21:47:18 +08002958 OPT_BOOLEAN('f', "force", &trace.force, "don't complain, do it"),
Milian Wolff566a0882016-04-08 13:34:15 +02002959 OPT_CALLBACK(0, "call-graph", &trace.opts,
2960 "record_mode[,record_size]", record_callchain_help,
2961 &record_parse_callchain_opt),
Arnaldo Carvalho de Melo44621812016-04-11 15:49:11 -03002962 OPT_BOOLEAN(0, "kernel-syscall-graph", &trace.kernel_syscallchains,
2963 "Show the kernel callchains on the syscall exit path"),
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -03002964 OPT_UINTEGER(0, "min-stack", &trace.min_stack,
2965 "Set the minimum stack depth when parsing the callchain, "
2966 "anything below the specified depth will be ignored."),
Arnaldo Carvalho de Meloc6d4a492016-04-14 18:29:08 -03002967 OPT_UINTEGER(0, "max-stack", &trace.max_stack,
2968 "Set the maximum stack depth when parsing the callchain, "
2969 "anything beyond the specified depth will be ignored. "
Arnaldo Carvalho de Melo4cb93442016-04-27 10:16:24 -03002970 "Default: kernel.perf_event_max_stack or " __stringify(PERF_MAX_STACK_DEPTH)),
Kan Liang9d9cad72015-06-17 09:51:11 -04002971 OPT_UINTEGER(0, "proc-map-timeout", &trace.opts.proc_map_timeout,
2972 "per thread proc mmap processing timeout in ms"),
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002973 OPT_END()
2974 };
Arnaldo Carvalho de Meloccd62a82016-04-16 09:36:32 -03002975 bool __maybe_unused max_stack_user_set = true;
Arnaldo Carvalho de Melof3e459d2016-04-15 17:52:34 -03002976 bool mmap_pages_user_set = true;
Yunlong Song6fdd9cb2015-03-18 21:35:57 +08002977 const char * const trace_subcommands[] = { "record", NULL };
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002978 int err;
Namhyung Kim32caf0d2012-10-05 14:02:13 +09002979 char bf[BUFSIZ];
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002980
Arnaldo Carvalho de Melo4d08cb82015-02-24 15:35:55 -03002981 signal(SIGSEGV, sighandler_dump_stack);
2982 signal(SIGFPE, sighandler_dump_stack);
2983
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002984 trace.evlist = perf_evlist__new();
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03002985 trace.sctbl = syscalltbl__new();
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002986
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03002987 if (trace.evlist == NULL || trace.sctbl == NULL) {
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002988 pr_err("Not enough memory to run!\n");
He Kuangff8f6952015-05-11 12:28:36 +00002989 err = -ENOMEM;
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002990 goto out;
2991 }
2992
Yunlong Song6fdd9cb2015-03-18 21:35:57 +08002993 argc = parse_options_subcommand(argc, argv, trace_options, trace_subcommands,
2994 trace_usage, PARSE_OPT_STOP_AT_NON_OPTION);
David Ahernfd2eaba2013-11-12 09:31:15 -07002995
Wang Nand7888572016-04-08 15:07:24 +00002996 err = bpf__setup_stdout(trace.evlist);
2997 if (err) {
2998 bpf__strerror_setup_stdout(trace.evlist, err, bf, sizeof(bf));
2999 pr_err("ERROR: Setup BPF stdout failed: %s\n", bf);
3000 goto out;
3001 }
3002
Arnaldo Carvalho de Melo59247e32016-04-12 16:05:02 -03003003 err = -1;
3004
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04003005 if (trace.trace_pgfaults) {
3006 trace.opts.sample_address = true;
3007 trace.opts.sample_time = true;
3008 }
3009
Arnaldo Carvalho de Melof3e459d2016-04-15 17:52:34 -03003010 if (trace.opts.mmap_pages == UINT_MAX)
3011 mmap_pages_user_set = false;
3012
Arnaldo Carvalho de Melo05614992016-04-15 16:41:19 -03003013 if (trace.max_stack == UINT_MAX) {
Arnaldo Carvalho de Melo4cb93442016-04-27 10:16:24 -03003014 trace.max_stack = sysctl_perf_event_max_stack;
Arnaldo Carvalho de Melo05614992016-04-15 16:41:19 -03003015 max_stack_user_set = false;
3016 }
3017
3018#ifdef HAVE_DWARF_UNWIND_SUPPORT
Arnaldo Carvalho de Melo2ddd5c02016-04-18 12:09:08 -03003019 if ((trace.min_stack || max_stack_user_set) && !callchain_param.enabled)
Arnaldo Carvalho de Melo05614992016-04-15 16:41:19 -03003020 record_opts__parse_callchain(&trace.opts, &callchain_param, "dwarf", false);
3021#endif
3022
Arnaldo Carvalho de Melo2ddd5c02016-04-18 12:09:08 -03003023 if (callchain_param.enabled) {
Arnaldo Carvalho de Melof3e459d2016-04-15 17:52:34 -03003024 if (!mmap_pages_user_set && geteuid() == 0)
3025 trace.opts.mmap_pages = perf_event_mlock_kb_in_pages() * 4;
3026
Milian Wolff566a0882016-04-08 13:34:15 +02003027 symbol_conf.use_callchain = true;
Arnaldo Carvalho de Melof3e459d2016-04-15 17:52:34 -03003028 }
Milian Wolff566a0882016-04-08 13:34:15 +02003029
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003030 if (trace.evlist->nr_entries > 0)
3031 evlist__set_evsel_handler(trace.evlist, trace__event_handler);
3032
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04003033 if ((argc >= 1) && (strcmp(argv[0], "record") == 0))
3034 return trace__record(&trace, argc-1, &argv[1]);
3035
3036 /* summary_only implies summary option, but don't overwrite summary if set */
3037 if (trace.summary_only)
3038 trace.summary = trace.summary_only;
3039
Arnaldo Carvalho de Melo726f3232015-02-06 10:16:45 +01003040 if (!trace.trace_syscalls && !trace.trace_pgfaults &&
3041 trace.evlist->nr_entries == 0 /* Was --events used? */) {
Stanislav Fomicheve281a962014-06-26 20:14:28 +04003042 pr_err("Please specify something to trace.\n");
3043 return -1;
3044 }
3045
Arnaldo Carvalho de Melo59247e32016-04-12 16:05:02 -03003046 if (!trace.trace_syscalls && ev_qualifier_str) {
3047 pr_err("The -e option can't be used with --no-syscalls.\n");
3048 goto out;
3049 }
3050
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003051 if (output_name != NULL) {
3052 err = trace__open_output(&trace, output_name);
3053 if (err < 0) {
3054 perror("failed to create output file");
3055 goto out;
3056 }
3057 }
3058
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03003059 trace.open_id = syscalltbl__id(trace.sctbl, "open");
3060
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03003061 if (ev_qualifier_str != NULL) {
Arnaldo Carvalho de Melob059efd2013-08-21 12:56:21 -03003062 const char *s = ev_qualifier_str;
Arnaldo Carvalho de Melo005438a82015-07-20 12:02:09 -03003063 struct strlist_config slist_config = {
3064 .dirname = system_path(STRACE_GROUPS_DIR),
3065 };
Arnaldo Carvalho de Melob059efd2013-08-21 12:56:21 -03003066
3067 trace.not_ev_qualifier = *s == '!';
3068 if (trace.not_ev_qualifier)
3069 ++s;
Arnaldo Carvalho de Melo005438a82015-07-20 12:02:09 -03003070 trace.ev_qualifier = strlist__new(s, &slist_config);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03003071 if (trace.ev_qualifier == NULL) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003072 fputs("Not enough memory to parse event qualifier",
3073 trace.output);
3074 err = -ENOMEM;
3075 goto out_close;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03003076 }
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03003077
3078 err = trace__validate_ev_qualifier(&trace);
3079 if (err)
3080 goto out_close;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03003081 }
3082
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003083 err = target__validate(&trace.opts.target);
Namhyung Kim32caf0d2012-10-05 14:02:13 +09003084 if (err) {
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003085 target__strerror(&trace.opts.target, err, bf, sizeof(bf));
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003086 fprintf(trace.output, "%s", bf);
3087 goto out_close;
Namhyung Kim32caf0d2012-10-05 14:02:13 +09003088 }
3089
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003090 err = target__parse_uid(&trace.opts.target);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003091 if (err) {
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003092 target__strerror(&trace.opts.target, err, bf, sizeof(bf));
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003093 fprintf(trace.output, "%s", bf);
3094 goto out_close;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003095 }
3096
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003097 if (!argc && target__none(&trace.opts.target))
Namhyung Kimee761202012-10-05 14:02:14 +09003098 trace.opts.target.system_wide = true;
3099
David Ahern6810fc92013-08-28 22:29:52 -06003100 if (input_name)
3101 err = trace__replay(&trace);
3102 else
3103 err = trace__run(&trace, argc, argv);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03003104
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003105out_close:
3106 if (output_name != NULL)
3107 fclose(trace.output);
3108out:
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03003109 return err;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003110}