blob: 0e2a82bda22f82abe515de48f050cbab0d63eadd [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 Melo514f1c62012-09-26 20:05:56 -030039
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -030040#include <libaudit.h> /* FIXME: Still needed for audit_errno_to_name */
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -030041#include <stdlib.h>
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -030042#include <linux/futex.h>
Jiri Olsa8dd2a132015-09-07 10:38:06 +020043#include <linux/err.h>
Arnaldo Carvalho de Melo997bba82016-03-30 19:43:32 -030044#include <linux/seccomp.h>
45#include <linux/filter.h>
46#include <linux/audit.h>
47#include <sys/ptrace.h>
Arnaldo Carvalho de Melo39878d42016-03-30 20:02:15 -030048#include <linux/random.h>
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -030049
Arnaldo Carvalho de Meloc188e7a2015-05-14 17:39:03 -030050#ifndef O_CLOEXEC
51# define O_CLOEXEC 02000000
52#endif
53
Arnaldo Carvalho de Meloc188e7a2015-05-14 17:39:03 -030054#ifndef MSG_CMSG_CLOEXEC
55# define MSG_CMSG_CLOEXEC 0x40000000
56#endif
57
Arnaldo Carvalho de Meloa1c25522015-06-11 22:47:54 -030058#ifndef PERF_FLAG_FD_NO_GROUP
59# define PERF_FLAG_FD_NO_GROUP (1UL << 0)
60#endif
61
62#ifndef PERF_FLAG_FD_OUTPUT
63# define PERF_FLAG_FD_OUTPUT (1UL << 1)
64#endif
65
66#ifndef PERF_FLAG_PID_CGROUP
67# define PERF_FLAG_PID_CGROUP (1UL << 2) /* pid=cgroup id, per-cpu mode only */
68#endif
69
70#ifndef PERF_FLAG_FD_CLOEXEC
71# define PERF_FLAG_FD_CLOEXEC (1UL << 3) /* O_CLOEXEC */
72#endif
73
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -030074struct trace {
75 struct perf_tool tool;
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -030076 struct syscalltbl *sctbl;
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -030077 struct {
78 int max;
79 struct syscall *table;
80 struct {
81 struct perf_evsel *sys_enter,
82 *sys_exit;
83 } events;
84 } syscalls;
85 struct record_opts opts;
86 struct perf_evlist *evlist;
87 struct machine *host;
88 struct thread *current;
89 u64 base_time;
90 FILE *output;
91 unsigned long nr_events;
92 struct strlist *ev_qualifier;
93 struct {
94 size_t nr;
95 int *entries;
96 } ev_qualifier_ids;
97 struct intlist *tid_list;
98 struct intlist *pid_list;
99 struct {
100 size_t nr;
101 pid_t *entries;
102 } filter_pids;
103 double duration_filter;
104 double runtime_ms;
105 struct {
106 u64 vfs_getname,
107 proc_getname;
108 } stats;
109 bool not_ev_qualifier;
110 bool live;
111 bool full_time;
112 bool sched;
113 bool multiple_threads;
114 bool summary;
115 bool summary_only;
116 bool show_comm;
117 bool show_tool_stats;
118 bool trace_syscalls;
Arnaldo Carvalho de Melo44621812016-04-11 15:49:11 -0300119 bool kernel_syscallchains;
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -0300120 bool force;
121 bool vfs_getname;
122 int trace_pgfaults;
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -0300123 int open_id;
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -0300124};
Arnaldo Carvalho de Meloa1c25522015-06-11 22:47:54 -0300125
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300126struct tp_field {
127 int offset;
128 union {
129 u64 (*integer)(struct tp_field *field, struct perf_sample *sample);
130 void *(*pointer)(struct tp_field *field, struct perf_sample *sample);
131 };
132};
133
134#define TP_UINT_FIELD(bits) \
135static u64 tp_field__u##bits(struct tp_field *field, struct perf_sample *sample) \
136{ \
David Ahern55d43bca2015-02-19 15:00:22 -0500137 u##bits value; \
138 memcpy(&value, sample->raw_data + field->offset, sizeof(value)); \
139 return value; \
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300140}
141
142TP_UINT_FIELD(8);
143TP_UINT_FIELD(16);
144TP_UINT_FIELD(32);
145TP_UINT_FIELD(64);
146
147#define TP_UINT_FIELD__SWAPPED(bits) \
148static u64 tp_field__swapped_u##bits(struct tp_field *field, struct perf_sample *sample) \
149{ \
David Ahern55d43bca2015-02-19 15:00:22 -0500150 u##bits value; \
151 memcpy(&value, sample->raw_data + field->offset, sizeof(value)); \
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300152 return bswap_##bits(value);\
153}
154
155TP_UINT_FIELD__SWAPPED(16);
156TP_UINT_FIELD__SWAPPED(32);
157TP_UINT_FIELD__SWAPPED(64);
158
159static int tp_field__init_uint(struct tp_field *field,
160 struct format_field *format_field,
161 bool needs_swap)
162{
163 field->offset = format_field->offset;
164
165 switch (format_field->size) {
166 case 1:
167 field->integer = tp_field__u8;
168 break;
169 case 2:
170 field->integer = needs_swap ? tp_field__swapped_u16 : tp_field__u16;
171 break;
172 case 4:
173 field->integer = needs_swap ? tp_field__swapped_u32 : tp_field__u32;
174 break;
175 case 8:
176 field->integer = needs_swap ? tp_field__swapped_u64 : tp_field__u64;
177 break;
178 default:
179 return -1;
180 }
181
182 return 0;
183}
184
185static void *tp_field__ptr(struct tp_field *field, struct perf_sample *sample)
186{
187 return sample->raw_data + field->offset;
188}
189
190static int tp_field__init_ptr(struct tp_field *field, struct format_field *format_field)
191{
192 field->offset = format_field->offset;
193 field->pointer = tp_field__ptr;
194 return 0;
195}
196
197struct syscall_tp {
198 struct tp_field id;
199 union {
200 struct tp_field args, ret;
201 };
202};
203
204static int perf_evsel__init_tp_uint_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_uint(field, format_field, evsel->needs_swap);
214}
215
216#define perf_evsel__init_sc_tp_uint_field(evsel, name) \
217 ({ struct syscall_tp *sc = evsel->priv;\
218 perf_evsel__init_tp_uint_field(evsel, &sc->name, #name); })
219
220static int perf_evsel__init_tp_ptr_field(struct perf_evsel *evsel,
221 struct tp_field *field,
222 const char *name)
223{
224 struct format_field *format_field = perf_evsel__field(evsel, name);
225
226 if (format_field == NULL)
227 return -1;
228
229 return tp_field__init_ptr(field, format_field);
230}
231
232#define perf_evsel__init_sc_tp_ptr_field(evsel, name) \
233 ({ struct syscall_tp *sc = evsel->priv;\
234 perf_evsel__init_tp_ptr_field(evsel, &sc->name, #name); })
235
236static void perf_evsel__delete_priv(struct perf_evsel *evsel)
237{
Arnaldo Carvalho de Melo04662522013-12-26 17:41:15 -0300238 zfree(&evsel->priv);
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300239 perf_evsel__delete(evsel);
240}
241
Namhyung Kim96695d42013-11-12 08:51:45 -0300242static int perf_evsel__init_syscall_tp(struct perf_evsel *evsel, void *handler)
243{
244 evsel->priv = malloc(sizeof(struct syscall_tp));
245 if (evsel->priv != NULL) {
246 if (perf_evsel__init_sc_tp_uint_field(evsel, id))
247 goto out_delete;
248
249 evsel->handler = handler;
250 return 0;
251 }
252
253 return -ENOMEM;
254
255out_delete:
Arnaldo Carvalho de Melo04662522013-12-26 17:41:15 -0300256 zfree(&evsel->priv);
Namhyung Kim96695d42013-11-12 08:51:45 -0300257 return -ENOENT;
258}
259
Arnaldo Carvalho de Meloef503832013-11-07 16:41:19 -0300260static struct perf_evsel *perf_evsel__syscall_newtp(const char *direction, void *handler)
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300261{
Arnaldo Carvalho de Meloef503832013-11-07 16:41:19 -0300262 struct perf_evsel *evsel = perf_evsel__newtp("raw_syscalls", direction);
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300263
David Ahern9aca7f12013-12-04 19:41:39 -0700264 /* older kernel (e.g., RHEL6) use syscalls:{enter,exit} */
Jiri Olsa8dd2a132015-09-07 10:38:06 +0200265 if (IS_ERR(evsel))
David Ahern9aca7f12013-12-04 19:41:39 -0700266 evsel = perf_evsel__newtp("syscalls", direction);
267
Jiri Olsa8dd2a132015-09-07 10:38:06 +0200268 if (IS_ERR(evsel))
269 return NULL;
270
271 if (perf_evsel__init_syscall_tp(evsel, handler))
272 goto out_delete;
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300273
274 return evsel;
275
276out_delete:
277 perf_evsel__delete_priv(evsel);
278 return NULL;
279}
280
281#define perf_evsel__sc_tp_uint(evsel, name, sample) \
282 ({ struct syscall_tp *fields = evsel->priv; \
283 fields->name.integer(&fields->name, sample); })
284
285#define perf_evsel__sc_tp_ptr(evsel, name, sample) \
286 ({ struct syscall_tp *fields = evsel->priv; \
287 fields->name.pointer(&fields->name, sample); })
288
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300289struct syscall_arg {
290 unsigned long val;
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300291 struct thread *thread;
292 struct trace *trace;
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300293 void *parm;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300294 u8 idx;
295 u8 mask;
296};
297
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300298struct strarray {
Arnaldo Carvalho de Melo03e3adc2013-10-08 16:00:21 -0300299 int offset;
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300300 int nr_entries;
301 const char **entries;
302};
303
304#define DEFINE_STRARRAY(array) struct strarray strarray__##array = { \
305 .nr_entries = ARRAY_SIZE(array), \
306 .entries = array, \
307}
308
Arnaldo Carvalho de Melo03e3adc2013-10-08 16:00:21 -0300309#define DEFINE_STRARRAY_OFFSET(array, off) struct strarray strarray__##array = { \
310 .offset = off, \
311 .nr_entries = ARRAY_SIZE(array), \
312 .entries = array, \
313}
314
Arnaldo Carvalho de Melo975b7c22013-10-08 17:17:43 -0300315static size_t __syscall_arg__scnprintf_strarray(char *bf, size_t size,
316 const char *intfmt,
317 struct syscall_arg *arg)
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300318{
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300319 struct strarray *sa = arg->parm;
Arnaldo Carvalho de Melo03e3adc2013-10-08 16:00:21 -0300320 int idx = arg->val - sa->offset;
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300321
322 if (idx < 0 || idx >= sa->nr_entries)
Arnaldo Carvalho de Melo975b7c22013-10-08 17:17:43 -0300323 return scnprintf(bf, size, intfmt, arg->val);
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300324
325 return scnprintf(bf, size, "%s", sa->entries[idx]);
326}
327
Arnaldo Carvalho de Melo975b7c22013-10-08 17:17:43 -0300328static size_t syscall_arg__scnprintf_strarray(char *bf, size_t size,
329 struct syscall_arg *arg)
330{
331 return __syscall_arg__scnprintf_strarray(bf, size, "%d", arg);
332}
333
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300334#define SCA_STRARRAY syscall_arg__scnprintf_strarray
335
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -0300336#if defined(__i386__) || defined(__x86_64__)
337/*
338 * FIXME: Make this available to all arches as soon as the ioctl beautifier
339 * gets rewritten to support all arches.
340 */
Arnaldo Carvalho de Melo78645cf2013-10-08 17:43:20 -0300341static size_t syscall_arg__scnprintf_strhexarray(char *bf, size_t size,
342 struct syscall_arg *arg)
343{
344 return __syscall_arg__scnprintf_strarray(bf, size, "%#x", arg);
345}
346
347#define SCA_STRHEXARRAY syscall_arg__scnprintf_strhexarray
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -0300348#endif /* defined(__i386__) || defined(__x86_64__) */
Arnaldo Carvalho de Melo78645cf2013-10-08 17:43:20 -0300349
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300350static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
351 struct syscall_arg *arg);
352
353#define SCA_FD syscall_arg__scnprintf_fd
354
355static size_t syscall_arg__scnprintf_fd_at(char *bf, size_t size,
356 struct syscall_arg *arg)
357{
358 int fd = arg->val;
359
360 if (fd == AT_FDCWD)
361 return scnprintf(bf, size, "CWD");
362
363 return syscall_arg__scnprintf_fd(bf, size, arg);
364}
365
366#define SCA_FDAT syscall_arg__scnprintf_fd_at
367
368static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
369 struct syscall_arg *arg);
370
371#define SCA_CLOSE_FD syscall_arg__scnprintf_close_fd
372
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -0300373static size_t syscall_arg__scnprintf_hex(char *bf, size_t size,
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300374 struct syscall_arg *arg)
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -0300375{
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300376 return scnprintf(bf, size, "%#lx", arg->val);
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -0300377}
378
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -0300379#define SCA_HEX syscall_arg__scnprintf_hex
380
Arnaldo Carvalho de Meloa1c25522015-06-11 22:47:54 -0300381static size_t syscall_arg__scnprintf_int(char *bf, size_t size,
382 struct syscall_arg *arg)
383{
384 return scnprintf(bf, size, "%d", arg->val);
385}
386
387#define SCA_INT syscall_arg__scnprintf_int
388
Arnaldo Carvalho de Melo5cea6ff2013-09-20 11:49:50 -0300389static size_t syscall_arg__scnprintf_flock(char *bf, size_t size,
390 struct syscall_arg *arg)
391{
392 int printed = 0, op = arg->val;
393
394 if (op == 0)
395 return scnprintf(bf, size, "NONE");
396#define P_CMD(cmd) \
397 if ((op & LOCK_##cmd) == LOCK_##cmd) { \
398 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #cmd); \
399 op &= ~LOCK_##cmd; \
400 }
401
402 P_CMD(SH);
403 P_CMD(EX);
404 P_CMD(NB);
405 P_CMD(UN);
406 P_CMD(MAND);
407 P_CMD(RW);
408 P_CMD(READ);
409 P_CMD(WRITE);
410#undef P_OP
411
412 if (op)
413 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", op);
414
415 return printed;
416}
417
418#define SCA_FLOCK syscall_arg__scnprintf_flock
419
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300420static 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 -0300421{
422 enum syscall_futex_args {
423 SCF_UADDR = (1 << 0),
424 SCF_OP = (1 << 1),
425 SCF_VAL = (1 << 2),
426 SCF_TIMEOUT = (1 << 3),
427 SCF_UADDR2 = (1 << 4),
428 SCF_VAL3 = (1 << 5),
429 };
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300430 int op = arg->val;
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -0300431 int cmd = op & FUTEX_CMD_MASK;
432 size_t printed = 0;
433
434 switch (cmd) {
435#define P_FUTEX_OP(n) case FUTEX_##n: printed = scnprintf(bf, size, #n);
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300436 P_FUTEX_OP(WAIT); arg->mask |= SCF_VAL3|SCF_UADDR2; break;
437 P_FUTEX_OP(WAKE); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
438 P_FUTEX_OP(FD); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
439 P_FUTEX_OP(REQUEUE); arg->mask |= SCF_VAL3|SCF_TIMEOUT; break;
440 P_FUTEX_OP(CMP_REQUEUE); arg->mask |= SCF_TIMEOUT; break;
441 P_FUTEX_OP(CMP_REQUEUE_PI); arg->mask |= SCF_TIMEOUT; break;
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -0300442 P_FUTEX_OP(WAKE_OP); break;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300443 P_FUTEX_OP(LOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
444 P_FUTEX_OP(UNLOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
445 P_FUTEX_OP(TRYLOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2; break;
446 P_FUTEX_OP(WAIT_BITSET); arg->mask |= SCF_UADDR2; break;
447 P_FUTEX_OP(WAKE_BITSET); arg->mask |= SCF_UADDR2; break;
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -0300448 P_FUTEX_OP(WAIT_REQUEUE_PI); break;
449 default: printed = scnprintf(bf, size, "%#x", cmd); break;
450 }
451
452 if (op & FUTEX_PRIVATE_FLAG)
453 printed += scnprintf(bf + printed, size - printed, "|PRIV");
454
455 if (op & FUTEX_CLOCK_REALTIME)
456 printed += scnprintf(bf + printed, size - printed, "|CLKRT");
457
458 return printed;
459}
460
Arnaldo Carvalho de Meloefe6b882013-09-03 16:15:12 -0300461#define SCA_FUTEX_OP syscall_arg__scnprintf_futex_op
462
Arnaldo Carvalho de Melo729a7842015-10-29 11:48:18 -0300463static const char *bpf_cmd[] = {
464 "MAP_CREATE", "MAP_LOOKUP_ELEM", "MAP_UPDATE_ELEM", "MAP_DELETE_ELEM",
465 "MAP_GET_NEXT_KEY", "PROG_LOAD",
466};
467static DEFINE_STRARRAY(bpf_cmd);
468
Arnaldo Carvalho de Melo03e3adc2013-10-08 16:00:21 -0300469static const char *epoll_ctl_ops[] = { "ADD", "DEL", "MOD", };
470static DEFINE_STRARRAY_OFFSET(epoll_ctl_ops, 1);
Arnaldo Carvalho de Meloeac032c2013-09-20 11:27:32 -0300471
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300472static const char *itimers[] = { "REAL", "VIRTUAL", "PROF", };
473static DEFINE_STRARRAY(itimers);
474
Arnaldo Carvalho de Melob62bee12015-08-11 11:05:36 -0300475static const char *keyctl_options[] = {
476 "GET_KEYRING_ID", "JOIN_SESSION_KEYRING", "UPDATE", "REVOKE", "CHOWN",
477 "SETPERM", "DESCRIBE", "CLEAR", "LINK", "UNLINK", "SEARCH", "READ",
478 "INSTANTIATE", "NEGATE", "SET_REQKEY_KEYRING", "SET_TIMEOUT",
479 "ASSUME_AUTHORITY", "GET_SECURITY", "SESSION_TO_PARENT", "REJECT",
480 "INSTANTIATE_IOV", "INVALIDATE", "GET_PERSISTENT",
481};
482static DEFINE_STRARRAY(keyctl_options);
483
Arnaldo Carvalho de Meloefe6b882013-09-03 16:15:12 -0300484static const char *whences[] = { "SET", "CUR", "END",
485#ifdef SEEK_DATA
486"DATA",
487#endif
488#ifdef SEEK_HOLE
489"HOLE",
490#endif
491};
492static DEFINE_STRARRAY(whences);
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -0300493
Arnaldo Carvalho de Melo80f587d2013-09-03 16:28:58 -0300494static const char *fcntl_cmds[] = {
495 "DUPFD", "GETFD", "SETFD", "GETFL", "SETFL", "GETLK", "SETLK",
496 "SETLKW", "SETOWN", "GETOWN", "SETSIG", "GETSIG", "F_GETLK64",
497 "F_SETLK64", "F_SETLKW64", "F_SETOWN_EX", "F_GETOWN_EX",
498 "F_GETOWNER_UIDS",
499};
500static DEFINE_STRARRAY(fcntl_cmds);
501
Arnaldo Carvalho de Meloc045bf02013-09-04 11:52:33 -0300502static const char *rlimit_resources[] = {
503 "CPU", "FSIZE", "DATA", "STACK", "CORE", "RSS", "NPROC", "NOFILE",
504 "MEMLOCK", "AS", "LOCKS", "SIGPENDING", "MSGQUEUE", "NICE", "RTPRIO",
505 "RTTIME",
506};
507static DEFINE_STRARRAY(rlimit_resources);
508
Arnaldo Carvalho de Meloeb5b1b12013-09-03 16:37:46 -0300509static const char *sighow[] = { "BLOCK", "UNBLOCK", "SETMASK", };
510static DEFINE_STRARRAY(sighow);
511
David Ahern4f8c1b72013-09-22 19:45:00 -0600512static const char *clockid[] = {
513 "REALTIME", "MONOTONIC", "PROCESS_CPUTIME_ID", "THREAD_CPUTIME_ID",
Arnaldo Carvalho de Melo28ebb872015-08-11 10:38:38 -0300514 "MONOTONIC_RAW", "REALTIME_COARSE", "MONOTONIC_COARSE", "BOOTTIME",
515 "REALTIME_ALARM", "BOOTTIME_ALARM", "SGI_CYCLE", "TAI"
David Ahern4f8c1b72013-09-22 19:45:00 -0600516};
517static DEFINE_STRARRAY(clockid);
518
Arnaldo Carvalho de Meloe10bce82013-09-04 10:27:41 -0300519static const char *socket_families[] = {
520 "UNSPEC", "LOCAL", "INET", "AX25", "IPX", "APPLETALK", "NETROM",
521 "BRIDGE", "ATMPVC", "X25", "INET6", "ROSE", "DECnet", "NETBEUI",
522 "SECURITY", "KEY", "NETLINK", "PACKET", "ASH", "ECONET", "ATMSVC",
523 "RDS", "SNA", "IRDA", "PPPOX", "WANPIPE", "LLC", "IB", "CAN", "TIPC",
524 "BLUETOOTH", "IUCV", "RXRPC", "ISDN", "PHONET", "IEEE802154", "CAIF",
525 "ALG", "NFC", "VSOCK",
526};
527static DEFINE_STRARRAY(socket_families);
528
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -0300529#ifndef MSG_PROBE
530#define MSG_PROBE 0x10
531#endif
David Ahernb6e8f8f2013-09-22 19:44:56 -0600532#ifndef MSG_WAITFORONE
533#define MSG_WAITFORONE 0x10000
534#endif
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -0300535#ifndef MSG_SENDPAGE_NOTLAST
536#define MSG_SENDPAGE_NOTLAST 0x20000
537#endif
538#ifndef MSG_FASTOPEN
539#define MSG_FASTOPEN 0x20000000
540#endif
541
542static size_t syscall_arg__scnprintf_msg_flags(char *bf, size_t size,
543 struct syscall_arg *arg)
544{
545 int printed = 0, flags = arg->val;
546
547 if (flags == 0)
548 return scnprintf(bf, size, "NONE");
549#define P_MSG_FLAG(n) \
550 if (flags & MSG_##n) { \
551 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
552 flags &= ~MSG_##n; \
553 }
554
555 P_MSG_FLAG(OOB);
556 P_MSG_FLAG(PEEK);
557 P_MSG_FLAG(DONTROUTE);
558 P_MSG_FLAG(TRYHARD);
559 P_MSG_FLAG(CTRUNC);
560 P_MSG_FLAG(PROBE);
561 P_MSG_FLAG(TRUNC);
562 P_MSG_FLAG(DONTWAIT);
563 P_MSG_FLAG(EOR);
564 P_MSG_FLAG(WAITALL);
565 P_MSG_FLAG(FIN);
566 P_MSG_FLAG(SYN);
567 P_MSG_FLAG(CONFIRM);
568 P_MSG_FLAG(RST);
569 P_MSG_FLAG(ERRQUEUE);
570 P_MSG_FLAG(NOSIGNAL);
571 P_MSG_FLAG(MORE);
572 P_MSG_FLAG(WAITFORONE);
573 P_MSG_FLAG(SENDPAGE_NOTLAST);
574 P_MSG_FLAG(FASTOPEN);
575 P_MSG_FLAG(CMSG_CLOEXEC);
576#undef P_MSG_FLAG
577
578 if (flags)
579 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
580
581 return printed;
582}
583
584#define SCA_MSG_FLAGS syscall_arg__scnprintf_msg_flags
585
Arnaldo Carvalho de Melo51108992013-09-04 11:42:27 -0300586static size_t syscall_arg__scnprintf_access_mode(char *bf, size_t size,
587 struct syscall_arg *arg)
588{
589 size_t printed = 0;
590 int mode = arg->val;
591
592 if (mode == F_OK) /* 0 */
593 return scnprintf(bf, size, "F");
594#define P_MODE(n) \
595 if (mode & n##_OK) { \
596 printed += scnprintf(bf + printed, size - printed, "%s", #n); \
597 mode &= ~n##_OK; \
598 }
599
600 P_MODE(R);
601 P_MODE(W);
602 P_MODE(X);
603#undef P_MODE
604
605 if (mode)
606 printed += scnprintf(bf + printed, size - printed, "|%#x", mode);
607
608 return printed;
609}
610
611#define SCA_ACCMODE syscall_arg__scnprintf_access_mode
612
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -0300613static size_t syscall_arg__scnprintf_filename(char *bf, size_t size,
614 struct syscall_arg *arg);
615
616#define SCA_FILENAME syscall_arg__scnprintf_filename
617
Arnaldo Carvalho de Melobe65a892013-09-02 16:22:31 -0300618static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300619 struct syscall_arg *arg)
Arnaldo Carvalho de Melobe65a892013-09-02 16:22:31 -0300620{
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300621 int printed = 0, flags = arg->val;
Arnaldo Carvalho de Melobe65a892013-09-02 16:22:31 -0300622
623 if (!(flags & O_CREAT))
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300624 arg->mask |= 1 << (arg->idx + 1); /* Mask the mode parm */
Arnaldo Carvalho de Melobe65a892013-09-02 16:22:31 -0300625
626 if (flags == 0)
627 return scnprintf(bf, size, "RDONLY");
628#define P_FLAG(n) \
629 if (flags & O_##n) { \
630 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
631 flags &= ~O_##n; \
632 }
633
634 P_FLAG(APPEND);
635 P_FLAG(ASYNC);
636 P_FLAG(CLOEXEC);
637 P_FLAG(CREAT);
638 P_FLAG(DIRECT);
639 P_FLAG(DIRECTORY);
640 P_FLAG(EXCL);
641 P_FLAG(LARGEFILE);
642 P_FLAG(NOATIME);
643 P_FLAG(NOCTTY);
644#ifdef O_NONBLOCK
645 P_FLAG(NONBLOCK);
646#elif O_NDELAY
647 P_FLAG(NDELAY);
648#endif
649#ifdef O_PATH
650 P_FLAG(PATH);
651#endif
652 P_FLAG(RDWR);
653#ifdef O_DSYNC
654 if ((flags & O_SYNC) == O_SYNC)
655 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", "SYNC");
656 else {
657 P_FLAG(DSYNC);
658 }
659#else
660 P_FLAG(SYNC);
661#endif
662 P_FLAG(TRUNC);
663 P_FLAG(WRONLY);
664#undef P_FLAG
665
666 if (flags)
667 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
668
669 return printed;
670}
671
672#define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags
673
Arnaldo Carvalho de Meloa1c25522015-06-11 22:47:54 -0300674static size_t syscall_arg__scnprintf_perf_flags(char *bf, size_t size,
675 struct syscall_arg *arg)
676{
677 int printed = 0, flags = arg->val;
678
679 if (flags == 0)
680 return 0;
681
682#define P_FLAG(n) \
683 if (flags & PERF_FLAG_##n) { \
684 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
685 flags &= ~PERF_FLAG_##n; \
686 }
687
688 P_FLAG(FD_NO_GROUP);
689 P_FLAG(FD_OUTPUT);
690 P_FLAG(PID_CGROUP);
691 P_FLAG(FD_CLOEXEC);
692#undef P_FLAG
693
694 if (flags)
695 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
696
697 return printed;
698}
699
700#define SCA_PERF_FLAGS syscall_arg__scnprintf_perf_flags
701
Arnaldo Carvalho de Melo46cce192013-09-23 12:52:04 -0300702static size_t syscall_arg__scnprintf_pipe_flags(char *bf, size_t size,
703 struct syscall_arg *arg)
704{
705 int printed = 0, flags = arg->val;
706
707#define P_FLAG(n) \
708 if (flags & O_##n) { \
709 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
710 flags &= ~O_##n; \
711 }
712
713 P_FLAG(CLOEXEC);
714 P_FLAG(NONBLOCK);
715#undef P_FLAG
716
717 if (flags)
718 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
719
720 return printed;
721}
722
723#define SCA_PIPE_FLAGS syscall_arg__scnprintf_pipe_flags
724
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -0300725static size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscall_arg *arg)
726{
727 int sig = arg->val;
728
729 switch (sig) {
730#define P_SIGNUM(n) case SIG##n: return scnprintf(bf, size, #n)
731 P_SIGNUM(HUP);
732 P_SIGNUM(INT);
733 P_SIGNUM(QUIT);
734 P_SIGNUM(ILL);
735 P_SIGNUM(TRAP);
736 P_SIGNUM(ABRT);
737 P_SIGNUM(BUS);
738 P_SIGNUM(FPE);
739 P_SIGNUM(KILL);
740 P_SIGNUM(USR1);
741 P_SIGNUM(SEGV);
742 P_SIGNUM(USR2);
743 P_SIGNUM(PIPE);
744 P_SIGNUM(ALRM);
745 P_SIGNUM(TERM);
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -0300746 P_SIGNUM(CHLD);
747 P_SIGNUM(CONT);
748 P_SIGNUM(STOP);
749 P_SIGNUM(TSTP);
750 P_SIGNUM(TTIN);
751 P_SIGNUM(TTOU);
752 P_SIGNUM(URG);
753 P_SIGNUM(XCPU);
754 P_SIGNUM(XFSZ);
755 P_SIGNUM(VTALRM);
756 P_SIGNUM(PROF);
757 P_SIGNUM(WINCH);
758 P_SIGNUM(IO);
759 P_SIGNUM(PWR);
760 P_SIGNUM(SYS);
Ben Hutchings02c5bb42014-02-06 01:00:41 +0000761#ifdef SIGEMT
762 P_SIGNUM(EMT);
763#endif
764#ifdef SIGSTKFLT
765 P_SIGNUM(STKFLT);
766#endif
767#ifdef SIGSWI
768 P_SIGNUM(SWI);
769#endif
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -0300770 default: break;
771 }
772
773 return scnprintf(bf, size, "%#x", sig);
774}
775
776#define SCA_SIGNUM syscall_arg__scnprintf_signum
777
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -0300778#if defined(__i386__) || defined(__x86_64__)
779/*
780 * FIXME: Make this available to all arches.
781 */
Arnaldo Carvalho de Melo78645cf2013-10-08 17:43:20 -0300782#define TCGETS 0x5401
783
784static const char *tioctls[] = {
785 "TCGETS", "TCSETS", "TCSETSW", "TCSETSF", "TCGETA", "TCSETA", "TCSETAW",
786 "TCSETAF", "TCSBRK", "TCXONC", "TCFLSH", "TIOCEXCL", "TIOCNXCL",
787 "TIOCSCTTY", "TIOCGPGRP", "TIOCSPGRP", "TIOCOUTQ", "TIOCSTI",
788 "TIOCGWINSZ", "TIOCSWINSZ", "TIOCMGET", "TIOCMBIS", "TIOCMBIC",
789 "TIOCMSET", "TIOCGSOFTCAR", "TIOCSSOFTCAR", "FIONREAD", "TIOCLINUX",
790 "TIOCCONS", "TIOCGSERIAL", "TIOCSSERIAL", "TIOCPKT", "FIONBIO",
791 "TIOCNOTTY", "TIOCSETD", "TIOCGETD", "TCSBRKP", [0x27] = "TIOCSBRK",
792 "TIOCCBRK", "TIOCGSID", "TCGETS2", "TCSETS2", "TCSETSW2", "TCSETSF2",
793 "TIOCGRS485", "TIOCSRS485", "TIOCGPTN", "TIOCSPTLCK",
794 "TIOCGDEV||TCGETX", "TCSETX", "TCSETXF", "TCSETXW", "TIOCSIG",
795 "TIOCVHANGUP", "TIOCGPKT", "TIOCGPTLCK", "TIOCGEXCL",
796 [0x50] = "FIONCLEX", "FIOCLEX", "FIOASYNC", "TIOCSERCONFIG",
797 "TIOCSERGWILD", "TIOCSERSWILD", "TIOCGLCKTRMIOS", "TIOCSLCKTRMIOS",
798 "TIOCSERGSTRUCT", "TIOCSERGETLSR", "TIOCSERGETMULTI", "TIOCSERSETMULTI",
799 "TIOCMIWAIT", "TIOCGICOUNT", [0x60] = "FIOQSIZE",
800};
801
802static DEFINE_STRARRAY_OFFSET(tioctls, 0x5401);
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -0300803#endif /* defined(__i386__) || defined(__x86_64__) */
Arnaldo Carvalho de Melo78645cf2013-10-08 17:43:20 -0300804
Arnaldo Carvalho de Melo6fb35b92016-04-13 11:50:23 -0300805#ifndef SECCOMP_SET_MODE_STRICT
806#define SECCOMP_SET_MODE_STRICT 0
807#endif
808#ifndef SECCOMP_SET_MODE_FILTER
809#define SECCOMP_SET_MODE_FILTER 1
810#endif
811
Arnaldo Carvalho de Melo997bba82016-03-30 19:43:32 -0300812static size_t syscall_arg__scnprintf_seccomp_op(char *bf, size_t size, struct syscall_arg *arg)
813{
814 int op = arg->val;
815 size_t printed = 0;
816
817 switch (op) {
818#define P_SECCOMP_SET_MODE_OP(n) case SECCOMP_SET_MODE_##n: printed = scnprintf(bf, size, #n); break
819 P_SECCOMP_SET_MODE_OP(STRICT);
820 P_SECCOMP_SET_MODE_OP(FILTER);
821#undef P_SECCOMP_SET_MODE_OP
822 default: printed = scnprintf(bf, size, "%#x", op); break;
823 }
824
825 return printed;
826}
827
828#define SCA_SECCOMP_OP syscall_arg__scnprintf_seccomp_op
829
Arnaldo Carvalho de Melo6fb35b92016-04-13 11:50:23 -0300830#ifndef SECCOMP_FILTER_FLAG_TSYNC
831#define SECCOMP_FILTER_FLAG_TSYNC 1
832#endif
833
Arnaldo Carvalho de Melo997bba82016-03-30 19:43:32 -0300834static size_t syscall_arg__scnprintf_seccomp_flags(char *bf, size_t size,
835 struct syscall_arg *arg)
836{
837 int printed = 0, flags = arg->val;
838
839#define P_FLAG(n) \
840 if (flags & SECCOMP_FILTER_FLAG_##n) { \
841 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
842 flags &= ~SECCOMP_FILTER_FLAG_##n; \
843 }
844
845 P_FLAG(TSYNC);
846#undef P_FLAG
847
848 if (flags)
849 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
850
851 return printed;
852}
853
854#define SCA_SECCOMP_FLAGS syscall_arg__scnprintf_seccomp_flags
855
Arnaldo Carvalho de Meloa355a612016-04-13 11:55:18 -0300856#ifndef GRND_NONBLOCK
857#define GRND_NONBLOCK 0x0001
858#endif
859#ifndef GRND_RANDOM
860#define GRND_RANDOM 0x0002
861#endif
862
Arnaldo Carvalho de Melo39878d42016-03-30 20:02:15 -0300863static size_t syscall_arg__scnprintf_getrandom_flags(char *bf, size_t size,
864 struct syscall_arg *arg)
865{
866 int printed = 0, flags = arg->val;
867
868#define P_FLAG(n) \
869 if (flags & GRND_##n) { \
870 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
871 flags &= ~GRND_##n; \
872 }
873
874 P_FLAG(RANDOM);
875 P_FLAG(NONBLOCK);
876#undef P_FLAG
877
878 if (flags)
879 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
880
881 return printed;
882}
883
884#define SCA_GETRANDOM_FLAGS syscall_arg__scnprintf_getrandom_flags
885
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300886#define STRARRAY(arg, name, array) \
887 .arg_scnprintf = { [arg] = SCA_STRARRAY, }, \
888 .arg_parm = { [arg] = &strarray__##array, }
889
Arnaldo Carvalho de Meloea8dc3c2016-04-13 12:10:19 -0300890#include "trace/beauty/eventfd.c"
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -0300891#include "trace/beauty/pid.c"
Arnaldo Carvalho de Melodf4cb162016-04-13 12:05:44 -0300892#include "trace/beauty/mmap.c"
Arnaldo Carvalho de Meloba2f22c2016-04-07 12:05:51 -0300893#include "trace/beauty/mode_t.c"
Arnaldo Carvalho de Meloa3bca912016-04-06 12:51:33 -0300894#include "trace/beauty/sched_policy.c"
Arnaldo Carvalho de Melobbf86c42016-04-14 13:53:10 -0300895#include "trace/beauty/socket_type.c"
Arnaldo Carvalho de Melo7206b902016-04-06 14:11:36 -0300896#include "trace/beauty/waitid_options.c"
Arnaldo Carvalho de Meloa3bca912016-04-06 12:51:33 -0300897
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300898static struct syscall_fmt {
899 const char *name;
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -0300900 const char *alias;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300901 size_t (*arg_scnprintf[6])(char *bf, size_t size, struct syscall_arg *arg);
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300902 void *arg_parm[6];
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300903 bool errmsg;
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -0300904 bool errpid;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300905 bool timeout;
Arnaldo Carvalho de Melo04b34722013-08-26 11:36:30 -0300906 bool hexret;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300907} syscall_fmts[] = {
Arnaldo Carvalho de Melo51108992013-09-04 11:42:27 -0300908 { .name = "access", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300909 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */
910 [1] = SCA_ACCMODE, /* mode */ }, },
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -0300911 { .name = "arch_prctl", .errmsg = true, .alias = "prctl", },
Arnaldo Carvalho de Melo729a7842015-10-29 11:48:18 -0300912 { .name = "bpf", .errmsg = true, STRARRAY(0, cmd, bpf_cmd), },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -0300913 { .name = "brk", .hexret = true,
914 .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300915 { .name = "chdir", .errmsg = true,
916 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
917 { .name = "chmod", .errmsg = true,
918 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
919 { .name = "chroot", .errmsg = true,
920 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
David Ahern4f8c1b72013-09-22 19:45:00 -0600921 { .name = "clock_gettime", .errmsg = true, STRARRAY(0, clk_id, clockid), },
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -0300922 { .name = "clone", .errpid = true, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300923 { .name = "close", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300924 .arg_scnprintf = { [0] = SCA_CLOSE_FD, /* fd */ }, },
Arnaldo Carvalho de Meloa14bb862013-07-30 16:38:23 -0300925 { .name = "connect", .errmsg = true, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300926 { .name = "creat", .errmsg = true,
927 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300928 { .name = "dup", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300929 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300930 { .name = "dup2", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300931 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300932 { .name = "dup3", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300933 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300934 { .name = "epoll_ctl", .errmsg = true, STRARRAY(1, op, epoll_ctl_ops), },
Arnaldo Carvalho de Melo49af9e92013-09-12 12:18:56 -0300935 { .name = "eventfd2", .errmsg = true,
936 .arg_scnprintf = { [1] = SCA_EFD_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300937 { .name = "faccessat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300938 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
939 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300940 { .name = "fadvise64", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300941 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300942 { .name = "fallocate", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300943 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300944 { .name = "fchdir", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300945 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300946 { .name = "fchmod", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300947 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300948 { .name = "fchmodat", .errmsg = true,
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -0300949 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */
950 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300951 { .name = "fchown", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300952 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300953 { .name = "fchownat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300954 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */
955 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300956 { .name = "fcntl", .errmsg = true,
957 .arg_scnprintf = { [0] = SCA_FD, /* fd */
958 [1] = SCA_STRARRAY, /* cmd */ },
959 .arg_parm = { [1] = &strarray__fcntl_cmds, /* cmd */ }, },
960 { .name = "fdatasync", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300961 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo5cea6ff2013-09-20 11:49:50 -0300962 { .name = "flock", .errmsg = true,
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300963 .arg_scnprintf = { [0] = SCA_FD, /* fd */
964 [1] = SCA_FLOCK, /* cmd */ }, },
965 { .name = "fsetxattr", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300966 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300967 { .name = "fstat", .errmsg = true, .alias = "newfstat",
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300968 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300969 { .name = "fstatat", .errmsg = true, .alias = "newfstatat",
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300970 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
971 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300972 { .name = "fstatfs", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300973 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300974 { .name = "fsync", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300975 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300976 { .name = "ftruncate", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300977 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -0300978 { .name = "futex", .errmsg = true,
979 .arg_scnprintf = { [1] = SCA_FUTEX_OP, /* op */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300980 { .name = "futimesat", .errmsg = true,
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -0300981 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */
982 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300983 { .name = "getdents", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300984 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300985 { .name = "getdents64", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300986 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300987 { .name = "getitimer", .errmsg = true, STRARRAY(0, which, itimers), },
Arnaldo Carvalho de Meloc65f1072016-04-06 14:55:18 -0300988 { .name = "getpid", .errpid = true, },
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -0300989 { .name = "getpgid", .errpid = true, },
Arnaldo Carvalho de Meloc65f1072016-04-06 14:55:18 -0300990 { .name = "getppid", .errpid = true, },
Arnaldo Carvalho de Melo39878d42016-03-30 20:02:15 -0300991 { .name = "getrandom", .errmsg = true,
992 .arg_scnprintf = { [2] = SCA_GETRANDOM_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300993 { .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300994 { .name = "getxattr", .errmsg = true,
995 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
996 { .name = "inotify_add_watch", .errmsg = true,
997 .arg_scnprintf = { [1] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -0300998 { .name = "ioctl", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300999 .arg_scnprintf = { [0] = SCA_FD, /* fd */
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -03001000#if defined(__i386__) || defined(__x86_64__)
1001/*
1002 * FIXME: Make this available to all arches.
1003 */
Arnaldo Carvalho de Melo78645cf2013-10-08 17:43:20 -03001004 [1] = SCA_STRHEXARRAY, /* cmd */
1005 [2] = SCA_HEX, /* arg */ },
1006 .arg_parm = { [1] = &strarray__tioctls, /* cmd */ }, },
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -03001007#else
1008 [2] = SCA_HEX, /* arg */ }, },
1009#endif
Arnaldo Carvalho de Melob62bee12015-08-11 11:05:36 -03001010 { .name = "keyctl", .errmsg = true, STRARRAY(0, option, keyctl_options), },
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -03001011 { .name = "kill", .errmsg = true,
1012 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001013 { .name = "lchown", .errmsg = true,
1014 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
1015 { .name = "lgetxattr", .errmsg = true,
1016 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001017 { .name = "linkat", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001018 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001019 { .name = "listxattr", .errmsg = true,
1020 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -03001021 { .name = "llistxattr", .errmsg = true,
1022 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
1023 { .name = "lremovexattr", .errmsg = true,
1024 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001025 { .name = "lseek", .errmsg = true,
1026 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1027 [2] = SCA_STRARRAY, /* whence */ },
1028 .arg_parm = { [2] = &strarray__whences, /* whence */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001029 { .name = "lsetxattr", .errmsg = true,
1030 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -03001031 { .name = "lstat", .errmsg = true, .alias = "newlstat",
1032 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001033 { .name = "lsxattr", .errmsg = true,
1034 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo9e9716d2013-08-23 10:06:41 -03001035 { .name = "madvise", .errmsg = true,
1036 .arg_scnprintf = { [0] = SCA_HEX, /* start */
1037 [2] = SCA_MADV_BHV, /* behavior */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001038 { .name = "mkdir", .errmsg = true,
1039 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001040 { .name = "mkdirat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001041 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */
1042 [1] = SCA_FILENAME, /* pathname */ }, },
1043 { .name = "mknod", .errmsg = true,
1044 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001045 { .name = "mknodat", .errmsg = true,
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -03001046 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */
1047 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo3d903aa2013-09-24 00:09:38 -03001048 { .name = "mlock", .errmsg = true,
1049 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
1050 { .name = "mlockall", .errmsg = true,
1051 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -03001052 { .name = "mmap", .hexret = true,
Arnaldo Carvalho de Meloae685382013-08-20 17:44:42 -03001053 .arg_scnprintf = { [0] = SCA_HEX, /* addr */
Arnaldo Carvalho de Melo941557e2013-08-23 10:48:33 -03001054 [2] = SCA_MMAP_PROT, /* prot */
Namhyung Kim73faab32013-11-12 15:24:59 +09001055 [3] = SCA_MMAP_FLAGS, /* flags */
1056 [4] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -03001057 { .name = "mprotect", .errmsg = true,
Arnaldo Carvalho de Meloae685382013-08-20 17:44:42 -03001058 .arg_scnprintf = { [0] = SCA_HEX, /* start */
1059 [2] = SCA_MMAP_PROT, /* prot */ }, },
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -03001060 { .name = "mq_unlink", .errmsg = true,
1061 .arg_scnprintf = { [0] = SCA_FILENAME, /* u_name */ }, },
Arnaldo Carvalho de Meloae685382013-08-20 17:44:42 -03001062 { .name = "mremap", .hexret = true,
1063 .arg_scnprintf = { [0] = SCA_HEX, /* addr */
Alex Snast86998dd2014-08-13 18:42:40 +03001064 [3] = SCA_MREMAP_FLAGS, /* flags */
Arnaldo Carvalho de Meloae685382013-08-20 17:44:42 -03001065 [4] = SCA_HEX, /* new_addr */ }, },
Arnaldo Carvalho de Melo3d903aa2013-09-24 00:09:38 -03001066 { .name = "munlock", .errmsg = true,
1067 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -03001068 { .name = "munmap", .errmsg = true,
1069 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001070 { .name = "name_to_handle_at", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001071 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001072 { .name = "newfstatat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001073 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
1074 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melobe65a892013-09-02 16:22:31 -03001075 { .name = "open", .errmsg = true,
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001076 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */
1077 [1] = SCA_OPEN_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo31cd3852013-09-02 16:40:40 -03001078 { .name = "open_by_handle_at", .errmsg = true,
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001079 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
1080 [2] = SCA_OPEN_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo31cd3852013-09-02 16:40:40 -03001081 { .name = "openat", .errmsg = true,
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001082 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001083 [1] = SCA_FILENAME, /* filename */
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001084 [2] = SCA_OPEN_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Meloa1c25522015-06-11 22:47:54 -03001085 { .name = "perf_event_open", .errmsg = true,
1086 .arg_scnprintf = { [1] = SCA_INT, /* pid */
1087 [2] = SCA_INT, /* cpu */
1088 [3] = SCA_FD, /* group_fd */
1089 [4] = SCA_PERF_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo46cce192013-09-23 12:52:04 -03001090 { .name = "pipe2", .errmsg = true,
1091 .arg_scnprintf = { [1] = SCA_PIPE_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -03001092 { .name = "poll", .errmsg = true, .timeout = true, },
1093 { .name = "ppoll", .errmsg = true, .timeout = true, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001094 { .name = "pread", .errmsg = true, .alias = "pread64",
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001095 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001096 { .name = "preadv", .errmsg = true, .alias = "pread",
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001097 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -03001098 { .name = "prlimit64", .errmsg = true, STRARRAY(1, resource, rlimit_resources), },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001099 { .name = "pwrite", .errmsg = true, .alias = "pwrite64",
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001100 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001101 { .name = "pwritev", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001102 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001103 { .name = "read", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001104 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001105 { .name = "readlink", .errmsg = true,
1106 .arg_scnprintf = { [0] = SCA_FILENAME, /* path */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001107 { .name = "readlinkat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001108 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
1109 [1] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001110 { .name = "readv", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001111 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -03001112 { .name = "recvfrom", .errmsg = true,
Arnaldo Carvalho de Melo8d8c66a2015-08-11 10:57:02 -03001113 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1114 [3] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -03001115 { .name = "recvmmsg", .errmsg = true,
Arnaldo Carvalho de Melo8d8c66a2015-08-11 10:57:02 -03001116 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1117 [3] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -03001118 { .name = "recvmsg", .errmsg = true,
Arnaldo Carvalho de Melo8d8c66a2015-08-11 10:57:02 -03001119 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1120 [2] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001121 { .name = "removexattr", .errmsg = true,
1122 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001123 { .name = "renameat", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001124 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001125 { .name = "rmdir", .errmsg = true,
1126 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -03001127 { .name = "rt_sigaction", .errmsg = true,
1128 .arg_scnprintf = { [0] = SCA_SIGNUM, /* sig */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -03001129 { .name = "rt_sigprocmask", .errmsg = true, STRARRAY(0, how, sighow), },
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -03001130 { .name = "rt_sigqueueinfo", .errmsg = true,
1131 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
1132 { .name = "rt_tgsigqueueinfo", .errmsg = true,
1133 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
Arnaldo Carvalho de Meloa3bca912016-04-06 12:51:33 -03001134 { .name = "sched_setscheduler", .errmsg = true,
1135 .arg_scnprintf = { [1] = SCA_SCHED_POLICY, /* policy */ }, },
Arnaldo Carvalho de Melo997bba82016-03-30 19:43:32 -03001136 { .name = "seccomp", .errmsg = true,
1137 .arg_scnprintf = { [0] = SCA_SECCOMP_OP, /* op */
1138 [1] = SCA_SECCOMP_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -03001139 { .name = "select", .errmsg = true, .timeout = true, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -03001140 { .name = "sendmmsg", .errmsg = true,
Arnaldo Carvalho de Melo8d8c66a2015-08-11 10:57:02 -03001141 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1142 [3] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -03001143 { .name = "sendmsg", .errmsg = true,
Arnaldo Carvalho de Melo8d8c66a2015-08-11 10:57:02 -03001144 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1145 [2] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -03001146 { .name = "sendto", .errmsg = true,
Arnaldo Carvalho de Melo8d8c66a2015-08-11 10:57:02 -03001147 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1148 [3] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Meloc65f1072016-04-06 14:55:18 -03001149 { .name = "set_tid_address", .errpid = true, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -03001150 { .name = "setitimer", .errmsg = true, STRARRAY(0, which, itimers), },
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -03001151 { .name = "setpgid", .errmsg = true, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -03001152 { .name = "setrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001153 { .name = "setxattr", .errmsg = true,
1154 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001155 { .name = "shutdown", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001156 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Meloe10bce82013-09-04 10:27:41 -03001157 { .name = "socket", .errmsg = true,
Arnaldo Carvalho de Meloa28b24b2013-09-04 11:00:44 -03001158 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
1159 [1] = SCA_SK_TYPE, /* type */ },
Arnaldo Carvalho de Meloe10bce82013-09-04 10:27:41 -03001160 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, },
Arnaldo Carvalho de Melo07120aa2013-09-20 12:24:20 -03001161 { .name = "socketpair", .errmsg = true,
1162 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
1163 [1] = SCA_SK_TYPE, /* type */ },
1164 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, },
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -03001165 { .name = "stat", .errmsg = true, .alias = "newstat",
1166 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001167 { .name = "statfs", .errmsg = true,
1168 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
1169 { .name = "swapoff", .errmsg = true,
1170 .arg_scnprintf = { [0] = SCA_FILENAME, /* specialfile */ }, },
1171 { .name = "swapon", .errmsg = true,
1172 .arg_scnprintf = { [0] = SCA_FILENAME, /* specialfile */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001173 { .name = "symlinkat", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001174 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -03001175 { .name = "tgkill", .errmsg = true,
1176 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
1177 { .name = "tkill", .errmsg = true,
1178 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001179 { .name = "truncate", .errmsg = true,
1180 .arg_scnprintf = { [0] = SCA_FILENAME, /* path */ }, },
Arnaldo Carvalho de Meloe5959682013-08-26 12:21:41 -03001181 { .name = "uname", .errmsg = true, .alias = "newuname", },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001182 { .name = "unlinkat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001183 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
1184 [1] = SCA_FILENAME, /* pathname */ }, },
1185 { .name = "utime", .errmsg = true,
1186 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001187 { .name = "utimensat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001188 .arg_scnprintf = { [0] = SCA_FDAT, /* dirfd */
1189 [1] = SCA_FILENAME, /* filename */ }, },
1190 { .name = "utimes", .errmsg = true,
1191 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -03001192 { .name = "vmsplice", .errmsg = true,
1193 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -03001194 { .name = "wait4", .errpid = true,
Arnaldo Carvalho de Melo7206b902016-04-06 14:11:36 -03001195 .arg_scnprintf = { [2] = SCA_WAITID_OPTIONS, /* options */ }, },
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -03001196 { .name = "waitid", .errpid = true,
Arnaldo Carvalho de Melo7206b902016-04-06 14:11:36 -03001197 .arg_scnprintf = { [3] = SCA_WAITID_OPTIONS, /* options */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001198 { .name = "write", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001199 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001200 { .name = "writev", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001201 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001202};
1203
1204static int syscall_fmt__cmp(const void *name, const void *fmtp)
1205{
1206 const struct syscall_fmt *fmt = fmtp;
1207 return strcmp(name, fmt->name);
1208}
1209
1210static struct syscall_fmt *syscall_fmt__find(const char *name)
1211{
1212 const int nmemb = ARRAY_SIZE(syscall_fmts);
1213 return bsearch(name, syscall_fmts, nmemb, sizeof(struct syscall_fmt), syscall_fmt__cmp);
1214}
1215
1216struct syscall {
1217 struct event_format *tp_format;
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001218 int nr_args;
1219 struct format_field *args;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001220 const char *name;
Arnaldo Carvalho de Melo5089f202014-06-17 14:29:24 -03001221 bool is_exit;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001222 struct syscall_fmt *fmt;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001223 size_t (**arg_scnprintf)(char *bf, size_t size, struct syscall_arg *arg);
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -03001224 void **arg_parm;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001225};
1226
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001227static size_t fprintf_duration(unsigned long t, FILE *fp)
1228{
1229 double duration = (double)t / NSEC_PER_MSEC;
1230 size_t printed = fprintf(fp, "(");
1231
1232 if (duration >= 1.0)
1233 printed += color_fprintf(fp, PERF_COLOR_RED, "%6.3f ms", duration);
1234 else if (duration >= 0.01)
1235 printed += color_fprintf(fp, PERF_COLOR_YELLOW, "%6.3f ms", duration);
1236 else
1237 printed += color_fprintf(fp, PERF_COLOR_NORMAL, "%6.3f ms", duration);
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001238 return printed + fprintf(fp, "): ");
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001239}
1240
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001241/**
1242 * filename.ptr: The filename char pointer that will be vfs_getname'd
1243 * filename.entry_str_pos: Where to insert the string translated from
1244 * filename.ptr by the vfs_getname tracepoint/kprobe.
1245 */
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001246struct thread_trace {
1247 u64 entry_time;
1248 u64 exit_time;
1249 bool entry_pending;
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03001250 unsigned long nr_events;
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04001251 unsigned long pfmaj, pfmin;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001252 char *entry_str;
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001253 double runtime_ms;
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001254 struct {
1255 unsigned long ptr;
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03001256 short int entry_str_pos;
1257 bool pending_open;
1258 unsigned int namelen;
1259 char *name;
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001260 } filename;
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001261 struct {
1262 int max;
1263 char **table;
1264 } paths;
David Ahernbf2575c2013-10-08 21:26:53 -06001265
1266 struct intlist *syscall_stats;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001267};
1268
1269static struct thread_trace *thread_trace__new(void)
1270{
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001271 struct thread_trace *ttrace = zalloc(sizeof(struct thread_trace));
1272
1273 if (ttrace)
1274 ttrace->paths.max = -1;
1275
David Ahernbf2575c2013-10-08 21:26:53 -06001276 ttrace->syscall_stats = intlist__new(NULL);
1277
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001278 return ttrace;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001279}
1280
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001281static struct thread_trace *thread__trace(struct thread *thread, FILE *fp)
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001282{
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03001283 struct thread_trace *ttrace;
1284
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001285 if (thread == NULL)
1286 goto fail;
1287
Namhyung Kim89dceb22014-10-06 09:46:03 +09001288 if (thread__priv(thread) == NULL)
1289 thread__set_priv(thread, thread_trace__new());
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001290
Namhyung Kim89dceb22014-10-06 09:46:03 +09001291 if (thread__priv(thread) == NULL)
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001292 goto fail;
1293
Namhyung Kim89dceb22014-10-06 09:46:03 +09001294 ttrace = thread__priv(thread);
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03001295 ++ttrace->nr_events;
1296
1297 return ttrace;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001298fail:
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001299 color_fprintf(fp, PERF_COLOR_RED,
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001300 "WARNING: not enough memory, dropping samples!\n");
1301 return NULL;
1302}
1303
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04001304#define TRACE_PFMAJ (1 << 0)
1305#define TRACE_PFMIN (1 << 1)
1306
Arnaldo Carvalho de Meloe4d44e82015-08-04 22:17:29 -03001307static const size_t trace__entry_str_size = 2048;
1308
Arnaldo Carvalho de Melo97119f32013-09-27 17:34:10 -03001309static int trace__set_fd_pathname(struct thread *thread, int fd, const char *pathname)
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001310{
Namhyung Kim89dceb22014-10-06 09:46:03 +09001311 struct thread_trace *ttrace = thread__priv(thread);
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001312
1313 if (fd > ttrace->paths.max) {
1314 char **npath = realloc(ttrace->paths.table, (fd + 1) * sizeof(char *));
1315
1316 if (npath == NULL)
1317 return -1;
1318
1319 if (ttrace->paths.max != -1) {
1320 memset(npath + ttrace->paths.max + 1, 0,
1321 (fd - ttrace->paths.max) * sizeof(char *));
1322 } else {
1323 memset(npath, 0, (fd + 1) * sizeof(char *));
1324 }
1325
1326 ttrace->paths.table = npath;
1327 ttrace->paths.max = fd;
1328 }
1329
1330 ttrace->paths.table[fd] = strdup(pathname);
1331
1332 return ttrace->paths.table[fd] != NULL ? 0 : -1;
1333}
1334
Arnaldo Carvalho de Melo97119f32013-09-27 17:34:10 -03001335static int thread__read_fd_path(struct thread *thread, int fd)
1336{
1337 char linkname[PATH_MAX], pathname[PATH_MAX];
1338 struct stat st;
1339 int ret;
1340
1341 if (thread->pid_ == thread->tid) {
1342 scnprintf(linkname, sizeof(linkname),
1343 "/proc/%d/fd/%d", thread->pid_, fd);
1344 } else {
1345 scnprintf(linkname, sizeof(linkname),
1346 "/proc/%d/task/%d/fd/%d", thread->pid_, thread->tid, fd);
1347 }
1348
1349 if (lstat(linkname, &st) < 0 || st.st_size + 1 > (off_t)sizeof(pathname))
1350 return -1;
1351
1352 ret = readlink(linkname, pathname, sizeof(pathname));
1353
1354 if (ret < 0 || ret > st.st_size)
1355 return -1;
1356
1357 pathname[ret] = '\0';
1358 return trace__set_fd_pathname(thread, fd, pathname);
1359}
1360
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001361static const char *thread__fd_path(struct thread *thread, int fd,
1362 struct trace *trace)
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001363{
Namhyung Kim89dceb22014-10-06 09:46:03 +09001364 struct thread_trace *ttrace = thread__priv(thread);
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001365
1366 if (ttrace == NULL)
1367 return NULL;
1368
1369 if (fd < 0)
1370 return NULL;
1371
Arnaldo Carvalho de Melocdcd1e62014-06-10 16:00:18 -03001372 if ((fd > ttrace->paths.max || ttrace->paths.table[fd] == NULL)) {
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001373 if (!trace->live)
1374 return NULL;
1375 ++trace->stats.proc_getname;
Arnaldo Carvalho de Melocdcd1e62014-06-10 16:00:18 -03001376 if (thread__read_fd_path(thread, fd))
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001377 return NULL;
1378 }
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001379
1380 return ttrace->paths.table[fd];
1381}
1382
1383static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
1384 struct syscall_arg *arg)
1385{
1386 int fd = arg->val;
1387 size_t printed = scnprintf(bf, size, "%d", fd);
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001388 const char *path = thread__fd_path(arg->thread, fd, arg->trace);
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001389
1390 if (path)
1391 printed += scnprintf(bf + printed, size - printed, "<%s>", path);
1392
1393 return printed;
1394}
1395
1396static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
1397 struct syscall_arg *arg)
1398{
1399 int fd = arg->val;
1400 size_t printed = syscall_arg__scnprintf_fd(bf, size, arg);
Namhyung Kim89dceb22014-10-06 09:46:03 +09001401 struct thread_trace *ttrace = thread__priv(arg->thread);
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001402
Arnaldo Carvalho de Melo04662522013-12-26 17:41:15 -03001403 if (ttrace && fd >= 0 && fd <= ttrace->paths.max)
1404 zfree(&ttrace->paths.table[fd]);
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001405
1406 return printed;
1407}
1408
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001409static void thread__set_filename_pos(struct thread *thread, const char *bf,
1410 unsigned long ptr)
1411{
1412 struct thread_trace *ttrace = thread__priv(thread);
1413
1414 ttrace->filename.ptr = ptr;
1415 ttrace->filename.entry_str_pos = bf - ttrace->entry_str;
1416}
1417
1418static size_t syscall_arg__scnprintf_filename(char *bf, size_t size,
1419 struct syscall_arg *arg)
1420{
1421 unsigned long ptr = arg->val;
1422
1423 if (!arg->trace->vfs_getname)
1424 return scnprintf(bf, size, "%#x", ptr);
1425
1426 thread__set_filename_pos(arg->thread, bf, ptr);
1427 return 0;
1428}
1429
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001430static bool trace__filter_duration(struct trace *trace, double t)
1431{
1432 return t < (trace->duration_filter * NSEC_PER_MSEC);
1433}
1434
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001435static size_t trace__fprintf_tstamp(struct trace *trace, u64 tstamp, FILE *fp)
1436{
1437 double ts = (double)(tstamp - trace->base_time) / NSEC_PER_MSEC;
1438
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001439 return fprintf(fp, "%10.3f ", ts);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001440}
1441
Namhyung Kimf15eb532012-10-05 14:02:16 +09001442static bool done = false;
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03001443static bool interrupted = false;
Namhyung Kimf15eb532012-10-05 14:02:16 +09001444
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03001445static void sig_handler(int sig)
Namhyung Kimf15eb532012-10-05 14:02:16 +09001446{
1447 done = true;
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03001448 interrupted = sig == SIGINT;
Namhyung Kimf15eb532012-10-05 14:02:16 +09001449}
1450
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001451static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thread,
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001452 u64 duration, u64 tstamp, FILE *fp)
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001453{
1454 size_t printed = trace__fprintf_tstamp(trace, tstamp, fp);
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001455 printed += fprintf_duration(duration, fp);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001456
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -03001457 if (trace->multiple_threads) {
1458 if (trace->show_comm)
Frederic Weisbecker1902efe2013-09-11 16:56:44 +02001459 printed += fprintf(fp, "%.14s/", thread__comm_str(thread));
Adrian Hunter38051232013-07-04 16:20:31 +03001460 printed += fprintf(fp, "%d ", thread->tid);
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -03001461 }
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001462
1463 return printed;
1464}
1465
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001466static int trace__process_event(struct trace *trace, struct machine *machine,
Frederic Weisbecker162f0be2013-09-11 16:18:24 +02001467 union perf_event *event, struct perf_sample *sample)
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001468{
1469 int ret = 0;
1470
1471 switch (event->header.type) {
1472 case PERF_RECORD_LOST:
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001473 color_fprintf(trace->output, PERF_COLOR_RED,
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001474 "LOST %" PRIu64 " events!\n", event->lost.lost);
Frederic Weisbecker162f0be2013-09-11 16:18:24 +02001475 ret = machine__process_lost_event(machine, event, sample);
Arnaldo Carvalho de Melo3ed5ca22016-03-30 16:51:17 -03001476 break;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001477 default:
Frederic Weisbecker162f0be2013-09-11 16:18:24 +02001478 ret = machine__process_event(machine, event, sample);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001479 break;
1480 }
1481
1482 return ret;
1483}
1484
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001485static int trace__tool_process(struct perf_tool *tool,
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001486 union perf_event *event,
Frederic Weisbecker162f0be2013-09-11 16:18:24 +02001487 struct perf_sample *sample,
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001488 struct machine *machine)
1489{
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001490 struct trace *trace = container_of(tool, struct trace, tool);
Frederic Weisbecker162f0be2013-09-11 16:18:24 +02001491 return trace__process_event(trace, machine, event, sample);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001492}
1493
1494static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
1495{
Namhyung Kim0a7e6d12014-08-12 15:40:45 +09001496 int err = symbol__init(NULL);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001497
1498 if (err)
1499 return err;
1500
David Ahern8fb598e2013-09-28 13:13:00 -06001501 trace->host = machine__new_host();
1502 if (trace->host == NULL)
1503 return -ENOMEM;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001504
Arnaldo Carvalho de Melo959c2192015-07-24 12:13:05 -03001505 if (trace_event__register_resolver(trace->host, machine__resolve_kernel_addr) < 0)
Arnaldo Carvalho de Melo706c3da2015-07-22 16:16:16 -03001506 return -errno;
1507
Arnaldo Carvalho de Meloa33fbd52013-11-11 11:36:12 -03001508 err = __machine__synthesize_threads(trace->host, &trace->tool, &trace->opts.target,
Kan Liang9d9cad72015-06-17 09:51:11 -04001509 evlist->threads, trace__tool_process, false,
1510 trace->opts.proc_map_timeout);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001511 if (err)
1512 symbol__exit();
1513
1514 return err;
1515}
1516
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001517static int syscall__set_arg_fmts(struct syscall *sc)
1518{
1519 struct format_field *field;
1520 int idx = 0;
1521
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001522 sc->arg_scnprintf = calloc(sc->nr_args, sizeof(void *));
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001523 if (sc->arg_scnprintf == NULL)
1524 return -1;
1525
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -03001526 if (sc->fmt)
1527 sc->arg_parm = sc->fmt->arg_parm;
1528
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001529 for (field = sc->args; field; field = field->next) {
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -03001530 if (sc->fmt && sc->fmt->arg_scnprintf[idx])
1531 sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx];
1532 else if (field->flags & FIELD_IS_POINTER)
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001533 sc->arg_scnprintf[idx] = syscall_arg__scnprintf_hex;
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -03001534 else if (strcmp(field->type, "pid_t") == 0)
1535 sc->arg_scnprintf[idx] = SCA_PID;
Arnaldo Carvalho de Meloba2f22c2016-04-07 12:05:51 -03001536 else if (strcmp(field->type, "umode_t") == 0)
1537 sc->arg_scnprintf[idx] = SCA_MODE_T;
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001538 ++idx;
1539 }
1540
1541 return 0;
1542}
1543
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001544static int trace__read_syscall_info(struct trace *trace, int id)
1545{
1546 char tp_name[128];
1547 struct syscall *sc;
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03001548 const char *name = syscalltbl__name(trace->sctbl, id);
Arnaldo Carvalho de Melo3a531262012-10-20 12:39:03 -03001549
1550 if (name == NULL)
1551 return -1;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001552
1553 if (id > trace->syscalls.max) {
1554 struct syscall *nsyscalls = realloc(trace->syscalls.table, (id + 1) * sizeof(*sc));
1555
1556 if (nsyscalls == NULL)
1557 return -1;
1558
1559 if (trace->syscalls.max != -1) {
1560 memset(nsyscalls + trace->syscalls.max + 1, 0,
1561 (id - trace->syscalls.max) * sizeof(*sc));
1562 } else {
1563 memset(nsyscalls, 0, (id + 1) * sizeof(*sc));
1564 }
1565
1566 trace->syscalls.table = nsyscalls;
1567 trace->syscalls.max = id;
1568 }
1569
1570 sc = trace->syscalls.table + id;
Arnaldo Carvalho de Melo3a531262012-10-20 12:39:03 -03001571 sc->name = name;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001572
Arnaldo Carvalho de Melo3a531262012-10-20 12:39:03 -03001573 sc->fmt = syscall_fmt__find(sc->name);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001574
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -03001575 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name);
Jiri Olsa97978b32013-12-03 14:09:24 +01001576 sc->tp_format = trace_event__tp_format("syscalls", tp_name);
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -03001577
Jiri Olsa8dd2a132015-09-07 10:38:06 +02001578 if (IS_ERR(sc->tp_format) && sc->fmt && sc->fmt->alias) {
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -03001579 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->fmt->alias);
Jiri Olsa97978b32013-12-03 14:09:24 +01001580 sc->tp_format = trace_event__tp_format("syscalls", tp_name);
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -03001581 }
1582
Jiri Olsa8dd2a132015-09-07 10:38:06 +02001583 if (IS_ERR(sc->tp_format))
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001584 return -1;
1585
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001586 sc->args = sc->tp_format->format.fields;
1587 sc->nr_args = sc->tp_format->format.nr_fields;
Taeung Songc42de702016-02-26 22:14:25 +09001588 /*
1589 * We need to check and discard the first variable '__syscall_nr'
1590 * or 'nr' that mean the syscall number. It is needless here.
1591 * So drop '__syscall_nr' or 'nr' field but does not exist on older kernels.
1592 */
1593 if (sc->args && (!strcmp(sc->args->name, "__syscall_nr") || !strcmp(sc->args->name, "nr"))) {
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001594 sc->args = sc->args->next;
1595 --sc->nr_args;
1596 }
1597
Arnaldo Carvalho de Melo5089f202014-06-17 14:29:24 -03001598 sc->is_exit = !strcmp(name, "exit_group") || !strcmp(name, "exit");
1599
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001600 return syscall__set_arg_fmts(sc);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001601}
1602
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001603static int trace__validate_ev_qualifier(struct trace *trace)
1604{
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001605 int err = 0, i;
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001606 struct str_node *pos;
1607
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001608 trace->ev_qualifier_ids.nr = strlist__nr_entries(trace->ev_qualifier);
1609 trace->ev_qualifier_ids.entries = malloc(trace->ev_qualifier_ids.nr *
1610 sizeof(trace->ev_qualifier_ids.entries[0]));
1611
1612 if (trace->ev_qualifier_ids.entries == NULL) {
1613 fputs("Error:\tNot enough memory for allocating events qualifier ids\n",
1614 trace->output);
1615 err = -EINVAL;
1616 goto out;
1617 }
1618
1619 i = 0;
1620
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001621 strlist__for_each(pos, trace->ev_qualifier) {
1622 const char *sc = pos->s;
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03001623 int id = syscalltbl__id(trace->sctbl, sc);
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001624
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001625 if (id < 0) {
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001626 if (err == 0) {
1627 fputs("Error:\tInvalid syscall ", trace->output);
1628 err = -EINVAL;
1629 } else {
1630 fputs(", ", trace->output);
1631 }
1632
1633 fputs(sc, trace->output);
1634 }
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001635
1636 trace->ev_qualifier_ids.entries[i++] = id;
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001637 }
1638
1639 if (err < 0) {
1640 fputs("\nHint:\ttry 'perf list syscalls:sys_enter_*'"
1641 "\nHint:\tand: 'man syscalls'\n", trace->output);
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001642 zfree(&trace->ev_qualifier_ids.entries);
1643 trace->ev_qualifier_ids.nr = 0;
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001644 }
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001645out:
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001646 return err;
1647}
1648
David Ahern55d43bca2015-02-19 15:00:22 -05001649/*
1650 * args is to be interpreted as a series of longs but we need to handle
1651 * 8-byte unaligned accesses. args points to raw_data within the event
1652 * and raw_data is guaranteed to be 8-byte unaligned because it is
1653 * preceded by raw_size which is a u32. So we need to copy args to a temp
1654 * variable to read it. Most notably this avoids extended load instructions
1655 * on unaligned addresses
1656 */
1657
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001658static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
David Ahern55d43bca2015-02-19 15:00:22 -05001659 unsigned char *args, struct trace *trace,
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001660 struct thread *thread)
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001661{
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001662 size_t printed = 0;
David Ahern55d43bca2015-02-19 15:00:22 -05001663 unsigned char *p;
1664 unsigned long val;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001665
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001666 if (sc->args != NULL) {
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001667 struct format_field *field;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001668 u8 bit = 1;
1669 struct syscall_arg arg = {
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001670 .idx = 0,
1671 .mask = 0,
1672 .trace = trace,
1673 .thread = thread,
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001674 };
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001675
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001676 for (field = sc->args; field;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001677 field = field->next, ++arg.idx, bit <<= 1) {
1678 if (arg.mask & bit)
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -03001679 continue;
David Ahern55d43bca2015-02-19 15:00:22 -05001680
1681 /* special care for unaligned accesses */
1682 p = args + sizeof(unsigned long) * arg.idx;
1683 memcpy(&val, p, sizeof(val));
1684
Arnaldo Carvalho de Melo4aa58232013-09-20 12:19:41 -03001685 /*
1686 * Suppress this argument if its value is zero and
1687 * and we don't have a string associated in an
1688 * strarray for it.
1689 */
David Ahern55d43bca2015-02-19 15:00:22 -05001690 if (val == 0 &&
Arnaldo Carvalho de Melo4aa58232013-09-20 12:19:41 -03001691 !(sc->arg_scnprintf &&
1692 sc->arg_scnprintf[arg.idx] == SCA_STRARRAY &&
1693 sc->arg_parm[arg.idx]))
Arnaldo Carvalho de Melo22ae5cf12013-09-12 11:27:34 -03001694 continue;
1695
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001696 printed += scnprintf(bf + printed, size - printed,
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001697 "%s%s: ", printed ? ", " : "", field->name);
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001698 if (sc->arg_scnprintf && sc->arg_scnprintf[arg.idx]) {
David Ahern55d43bca2015-02-19 15:00:22 -05001699 arg.val = val;
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -03001700 if (sc->arg_parm)
1701 arg.parm = sc->arg_parm[arg.idx];
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001702 printed += sc->arg_scnprintf[arg.idx](bf + printed,
1703 size - printed, &arg);
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -03001704 } else {
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001705 printed += scnprintf(bf + printed, size - printed,
David Ahern55d43bca2015-02-19 15:00:22 -05001706 "%ld", val);
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -03001707 }
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001708 }
1709 } else {
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001710 int i = 0;
1711
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001712 while (i < 6) {
David Ahern55d43bca2015-02-19 15:00:22 -05001713 /* special care for unaligned accesses */
1714 p = args + sizeof(unsigned long) * i;
1715 memcpy(&val, p, sizeof(val));
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001716 printed += scnprintf(bf + printed, size - printed,
1717 "%sarg%d: %ld",
David Ahern55d43bca2015-02-19 15:00:22 -05001718 printed ? ", " : "", i, val);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001719 ++i;
1720 }
1721 }
1722
1723 return printed;
1724}
1725
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001726typedef int (*tracepoint_handler)(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04001727 union perf_event *event,
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001728 struct perf_sample *sample);
1729
1730static struct syscall *trace__syscall_info(struct trace *trace,
David Ahernbf2575c2013-10-08 21:26:53 -06001731 struct perf_evsel *evsel, int id)
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001732{
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001733
1734 if (id < 0) {
Arnaldo Carvalho de Meloadaa18b2013-08-22 17:55:25 -03001735
1736 /*
1737 * XXX: Noticed on x86_64, reproduced as far back as 3.0.36, haven't tried
1738 * before that, leaving at a higher verbosity level till that is
1739 * explained. Reproduced with plain ftrace with:
1740 *
1741 * echo 1 > /t/events/raw_syscalls/sys_exit/enable
1742 * grep "NR -1 " /t/trace_pipe
1743 *
1744 * After generating some load on the machine.
1745 */
1746 if (verbose > 1) {
1747 static u64 n;
1748 fprintf(trace->output, "Invalid syscall %d id, skipping (%s, %" PRIu64 ") ...\n",
1749 id, perf_evsel__name(evsel), ++n);
1750 }
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001751 return NULL;
1752 }
1753
1754 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL) &&
1755 trace__read_syscall_info(trace, id))
1756 goto out_cant_read;
1757
1758 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL))
1759 goto out_cant_read;
1760
1761 return &trace->syscalls.table[id];
1762
1763out_cant_read:
Arnaldo Carvalho de Melo7c304ee02013-08-22 16:49:54 -03001764 if (verbose) {
1765 fprintf(trace->output, "Problems reading syscall %d", id);
1766 if (id <= trace->syscalls.max && trace->syscalls.table[id].name != NULL)
1767 fprintf(trace->output, "(%s)", trace->syscalls.table[id].name);
1768 fputs(" information\n", trace->output);
1769 }
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001770 return NULL;
1771}
1772
David Ahernbf2575c2013-10-08 21:26:53 -06001773static void thread__update_stats(struct thread_trace *ttrace,
1774 int id, struct perf_sample *sample)
1775{
1776 struct int_node *inode;
1777 struct stats *stats;
1778 u64 duration = 0;
1779
1780 inode = intlist__findnew(ttrace->syscall_stats, id);
1781 if (inode == NULL)
1782 return;
1783
1784 stats = inode->priv;
1785 if (stats == NULL) {
1786 stats = malloc(sizeof(struct stats));
1787 if (stats == NULL)
1788 return;
1789 init_stats(stats);
1790 inode->priv = stats;
1791 }
1792
1793 if (ttrace->entry_time && sample->time > ttrace->entry_time)
1794 duration = sample->time - ttrace->entry_time;
1795
1796 update_stats(stats, duration);
1797}
1798
Arnaldo Carvalho de Meloe5966632015-02-13 13:22:21 -03001799static int trace__printf_interrupted_entry(struct trace *trace, struct perf_sample *sample)
1800{
1801 struct thread_trace *ttrace;
1802 u64 duration;
1803 size_t printed;
1804
1805 if (trace->current == NULL)
1806 return 0;
1807
1808 ttrace = thread__priv(trace->current);
1809
1810 if (!ttrace->entry_pending)
1811 return 0;
1812
1813 duration = sample->time - ttrace->entry_time;
1814
1815 printed = trace__fprintf_entry_head(trace, trace->current, duration, sample->time, trace->output);
1816 printed += fprintf(trace->output, "%-70s) ...\n", ttrace->entry_str);
1817 ttrace->entry_pending = false;
1818
1819 return printed;
1820}
1821
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001822static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04001823 union perf_event *event __maybe_unused,
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001824 struct perf_sample *sample)
1825{
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001826 char *msg;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001827 void *args;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001828 size_t printed = 0;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001829 struct thread *thread;
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001830 int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
David Ahernbf2575c2013-10-08 21:26:53 -06001831 struct syscall *sc = trace__syscall_info(trace, evsel, id);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001832 struct thread_trace *ttrace;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001833
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001834 if (sc == NULL)
1835 return -1;
1836
David Ahern8fb598e2013-09-28 13:13:00 -06001837 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001838 ttrace = thread__trace(thread, trace->output);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001839 if (ttrace == NULL)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001840 goto out_put;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001841
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -03001842 args = perf_evsel__sc_tp_ptr(evsel, args, sample);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001843
1844 if (ttrace->entry_str == NULL) {
Arnaldo Carvalho de Meloe4d44e82015-08-04 22:17:29 -03001845 ttrace->entry_str = malloc(trace__entry_str_size);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001846 if (!ttrace->entry_str)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001847 goto out_put;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001848 }
1849
David Ahern13f22a22015-03-19 12:23:03 -06001850 if (!trace->summary_only)
Arnaldo Carvalho de Melo6ebad5c2015-03-25 18:01:15 -03001851 trace__printf_interrupted_entry(trace, sample);
Arnaldo Carvalho de Meloe5966632015-02-13 13:22:21 -03001852
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001853 ttrace->entry_time = sample->time;
1854 msg = ttrace->entry_str;
Arnaldo Carvalho de Meloe4d44e82015-08-04 22:17:29 -03001855 printed += scnprintf(msg + printed, trace__entry_str_size - printed, "%s(", sc->name);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001856
Arnaldo Carvalho de Meloe4d44e82015-08-04 22:17:29 -03001857 printed += syscall__scnprintf_args(sc, msg + printed, trace__entry_str_size - printed,
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001858 args, trace, thread);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001859
Arnaldo Carvalho de Melo5089f202014-06-17 14:29:24 -03001860 if (sc->is_exit) {
David Ahernfd2eaba2013-11-12 09:31:15 -07001861 if (!trace->duration_filter && !trace->summary_only) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001862 trace__fprintf_entry_head(trace, thread, 1, sample->time, trace->output);
1863 fprintf(trace->output, "%-70s\n", ttrace->entry_str);
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001864 }
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03001865 } else {
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001866 ttrace->entry_pending = true;
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03001867 /* See trace__vfs_getname & trace__sys_exit */
1868 ttrace->filename.pending_open = false;
1869 }
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001870
Arnaldo Carvalho de Melof3b623b2015-03-02 22:21:35 -03001871 if (trace->current != thread) {
1872 thread__put(trace->current);
1873 trace->current = thread__get(thread);
1874 }
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001875 err = 0;
1876out_put:
1877 thread__put(thread);
1878 return err;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001879}
1880
Arnaldo Carvalho de Melo202ff962016-04-12 10:11:07 -03001881static int trace__fprintf_callchain(struct trace *trace, struct perf_evsel *evsel,
1882 struct perf_sample *sample)
1883{
1884 struct addr_location al;
1885 /* TODO: user-configurable print_opts */
Arnaldo Carvalho de Meloe20ab862016-04-12 15:16:15 -03001886 const unsigned int print_opts = EVSEL__PRINT_SYM |
1887 EVSEL__PRINT_DSO |
1888 EVSEL__PRINT_UNKNOWN_AS_ADDR;
Arnaldo Carvalho de Melo202ff962016-04-12 10:11:07 -03001889
1890 if (sample->callchain == NULL)
1891 return 0;
1892
Arnaldo Carvalho de Melo6f736732016-04-14 17:45:51 -03001893 if (machine__resolve(trace->host, &al, sample) < 0 ||
1894 thread__resolve_callchain(al.thread, &callchain_cursor, evsel,
1895 sample, NULL, NULL, scripting_max_stack)) {
Arnaldo Carvalho de Melo202ff962016-04-12 10:11:07 -03001896 pr_err("Problem processing %s callchain, skipping...\n",
1897 perf_evsel__name(evsel));
1898 return 0;
1899 }
1900
Arnaldo Carvalho de Melo6f736732016-04-14 17:45:51 -03001901 return sample__fprintf_callchain(sample, &al, 38, print_opts,
1902 &callchain_cursor, trace->output);
Arnaldo Carvalho de Melo202ff962016-04-12 10:11:07 -03001903}
1904
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001905static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04001906 union perf_event *event __maybe_unused,
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001907 struct perf_sample *sample)
1908{
Chang Hyun Park2c82c3a2014-09-26 21:54:01 +09001909 long ret;
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001910 u64 duration = 0;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001911 struct thread *thread;
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001912 int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
David Ahernbf2575c2013-10-08 21:26:53 -06001913 struct syscall *sc = trace__syscall_info(trace, evsel, id);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001914 struct thread_trace *ttrace;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001915
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001916 if (sc == NULL)
1917 return -1;
1918
David Ahern8fb598e2013-09-28 13:13:00 -06001919 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001920 ttrace = thread__trace(thread, trace->output);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001921 if (ttrace == NULL)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001922 goto out_put;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001923
David Ahernbf2575c2013-10-08 21:26:53 -06001924 if (trace->summary)
1925 thread__update_stats(ttrace, id, sample);
1926
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -03001927 ret = perf_evsel__sc_tp_uint(evsel, ret, sample);
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001928
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03001929 if (id == trace->open_id && ret >= 0 && ttrace->filename.pending_open) {
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03001930 trace__set_fd_pathname(thread, ret, ttrace->filename.name);
1931 ttrace->filename.pending_open = false;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001932 ++trace->stats.vfs_getname;
1933 }
1934
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001935 ttrace->exit_time = sample->time;
1936
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001937 if (ttrace->entry_time) {
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001938 duration = sample->time - ttrace->entry_time;
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001939 if (trace__filter_duration(trace, duration))
1940 goto out;
1941 } else if (trace->duration_filter)
1942 goto out;
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001943
David Ahernfd2eaba2013-11-12 09:31:15 -07001944 if (trace->summary_only)
1945 goto out;
1946
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001947 trace__fprintf_entry_head(trace, thread, duration, sample->time, trace->output);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001948
1949 if (ttrace->entry_pending) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001950 fprintf(trace->output, "%-70s", ttrace->entry_str);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001951 } else {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001952 fprintf(trace->output, " ... [");
1953 color_fprintf(trace->output, PERF_COLOR_YELLOW, "continued");
1954 fprintf(trace->output, "]: %s()", sc->name);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001955 }
1956
Arnaldo Carvalho de Meloda3c9a42013-08-26 11:28:34 -03001957 if (sc->fmt == NULL) {
1958signed_print:
Chang Hyun Park2c82c3a2014-09-26 21:54:01 +09001959 fprintf(trace->output, ") = %ld", ret);
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -03001960 } else if (ret < 0 && (sc->fmt->errmsg || sc->fmt->errpid)) {
Masami Hiramatsu942a91e2014-08-14 02:22:41 +00001961 char bf[STRERR_BUFSIZE];
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001962 const char *emsg = strerror_r(-ret, bf, sizeof(bf)),
1963 *e = audit_errno_to_name(-ret);
1964
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001965 fprintf(trace->output, ") = -1 %s %s", e, emsg);
Arnaldo Carvalho de Meloda3c9a42013-08-26 11:28:34 -03001966 } else if (ret == 0 && sc->fmt->timeout)
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001967 fprintf(trace->output, ") = 0 Timeout");
Arnaldo Carvalho de Melo04b34722013-08-26 11:36:30 -03001968 else if (sc->fmt->hexret)
Chang Hyun Park2c82c3a2014-09-26 21:54:01 +09001969 fprintf(trace->output, ") = %#lx", ret);
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -03001970 else if (sc->fmt->errpid) {
1971 struct thread *child = machine__find_thread(trace->host, ret, ret);
1972
1973 if (child != NULL) {
1974 fprintf(trace->output, ") = %ld", ret);
1975 if (child->comm_set)
1976 fprintf(trace->output, " (%s)", thread__comm_str(child));
1977 thread__put(child);
1978 }
1979 } else
Arnaldo Carvalho de Meloda3c9a42013-08-26 11:28:34 -03001980 goto signed_print;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001981
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001982 fputc('\n', trace->output);
Milian Wolff566a0882016-04-08 13:34:15 +02001983
Arnaldo Carvalho de Melo202ff962016-04-12 10:11:07 -03001984 trace__fprintf_callchain(trace, evsel, sample);
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001985out:
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001986 ttrace->entry_pending = false;
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001987 err = 0;
1988out_put:
1989 thread__put(thread);
1990 return err;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001991}
1992
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001993static int trace__vfs_getname(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04001994 union perf_event *event __maybe_unused,
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001995 struct perf_sample *sample)
1996{
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001997 struct thread *thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
1998 struct thread_trace *ttrace;
1999 size_t filename_len, entry_str_len, to_move;
2000 ssize_t remaining_space;
2001 char *pos;
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03002002 const char *filename = perf_evsel__rawptr(evsel, sample, "pathname");
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03002003
2004 if (!thread)
2005 goto out;
2006
2007 ttrace = thread__priv(thread);
2008 if (!ttrace)
2009 goto out;
2010
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03002011 filename_len = strlen(filename);
2012
2013 if (ttrace->filename.namelen < filename_len) {
2014 char *f = realloc(ttrace->filename.name, filename_len + 1);
2015
2016 if (f == NULL)
2017 goto out;
2018
2019 ttrace->filename.namelen = filename_len;
2020 ttrace->filename.name = f;
2021 }
2022
2023 strcpy(ttrace->filename.name, filename);
2024 ttrace->filename.pending_open = true;
2025
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03002026 if (!ttrace->filename.ptr)
2027 goto out;
2028
2029 entry_str_len = strlen(ttrace->entry_str);
2030 remaining_space = trace__entry_str_size - entry_str_len - 1; /* \0 */
2031 if (remaining_space <= 0)
2032 goto out;
2033
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03002034 if (filename_len > (size_t)remaining_space) {
2035 filename += filename_len - remaining_space;
2036 filename_len = remaining_space;
2037 }
2038
2039 to_move = entry_str_len - ttrace->filename.entry_str_pos + 1; /* \0 */
2040 pos = ttrace->entry_str + ttrace->filename.entry_str_pos;
2041 memmove(pos + filename_len, pos, to_move);
2042 memcpy(pos, filename, filename_len);
2043
2044 ttrace->filename.ptr = 0;
2045 ttrace->filename.entry_str_pos = 0;
2046out:
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002047 return 0;
2048}
2049
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002050static int trace__sched_stat_runtime(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04002051 union perf_event *event __maybe_unused,
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002052 struct perf_sample *sample)
2053{
2054 u64 runtime = perf_evsel__intval(evsel, sample, "runtime");
2055 double runtime_ms = (double)runtime / NSEC_PER_MSEC;
David Ahern8fb598e2013-09-28 13:13:00 -06002056 struct thread *thread = machine__findnew_thread(trace->host,
Adrian Hunter314add62013-08-27 11:23:03 +03002057 sample->pid,
2058 sample->tid);
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002059 struct thread_trace *ttrace = thread__trace(thread, trace->output);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002060
2061 if (ttrace == NULL)
2062 goto out_dump;
2063
2064 ttrace->runtime_ms += runtime_ms;
2065 trace->runtime_ms += runtime_ms;
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002066 thread__put(thread);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002067 return 0;
2068
2069out_dump:
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002070 fprintf(trace->output, "%s: comm=%s,pid=%u,runtime=%" PRIu64 ",vruntime=%" PRIu64 ")\n",
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002071 evsel->name,
2072 perf_evsel__strval(evsel, sample, "comm"),
2073 (pid_t)perf_evsel__intval(evsel, sample, "pid"),
2074 runtime,
2075 perf_evsel__intval(evsel, sample, "vruntime"));
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002076 thread__put(thread);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002077 return 0;
2078}
2079
Wang Nan1d6c9402016-02-26 09:31:55 +00002080static void bpf_output__printer(enum binary_printer_ops op,
2081 unsigned int val, void *extra)
2082{
2083 FILE *output = extra;
2084 unsigned char ch = (unsigned char)val;
2085
2086 switch (op) {
2087 case BINARY_PRINT_CHAR_DATA:
2088 fprintf(output, "%c", isprint(ch) ? ch : '.');
2089 break;
2090 case BINARY_PRINT_DATA_BEGIN:
2091 case BINARY_PRINT_LINE_BEGIN:
2092 case BINARY_PRINT_ADDR:
2093 case BINARY_PRINT_NUM_DATA:
2094 case BINARY_PRINT_NUM_PAD:
2095 case BINARY_PRINT_SEP:
2096 case BINARY_PRINT_CHAR_PAD:
2097 case BINARY_PRINT_LINE_END:
2098 case BINARY_PRINT_DATA_END:
2099 default:
2100 break;
2101 }
2102}
2103
2104static void bpf_output__fprintf(struct trace *trace,
2105 struct perf_sample *sample)
2106{
2107 print_binary(sample->raw_data, sample->raw_size, 8,
2108 bpf_output__printer, trace->output);
2109}
2110
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002111static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
2112 union perf_event *event __maybe_unused,
2113 struct perf_sample *sample)
2114{
2115 trace__printf_interrupted_entry(trace, sample);
2116 trace__fprintf_tstamp(trace, sample->time, trace->output);
Arnaldo Carvalho de Melo08089212015-02-19 21:51:50 -08002117
2118 if (trace->trace_syscalls)
2119 fprintf(trace->output, "( ): ");
2120
2121 fprintf(trace->output, "%s:", evsel->name);
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002122
Wang Nan1d6c9402016-02-26 09:31:55 +00002123 if (perf_evsel__is_bpf_output(evsel)) {
2124 bpf_output__fprintf(trace, sample);
2125 } else if (evsel->tp_format) {
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002126 event_format__fprintf(evsel->tp_format, sample->cpu,
2127 sample->raw_data, sample->raw_size,
2128 trace->output);
2129 }
2130
2131 fprintf(trace->output, ")\n");
Arnaldo Carvalho de Melo202ff962016-04-12 10:11:07 -03002132
2133 trace__fprintf_callchain(trace, evsel, sample);
2134
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002135 return 0;
2136}
2137
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002138static void print_location(FILE *f, struct perf_sample *sample,
2139 struct addr_location *al,
2140 bool print_dso, bool print_sym)
2141{
2142
2143 if ((verbose || print_dso) && al->map)
2144 fprintf(f, "%s@", al->map->dso->long_name);
2145
2146 if ((verbose || print_sym) && al->sym)
Arnaldo Carvalho de Melo4414a3c2014-07-08 15:39:21 -03002147 fprintf(f, "%s+0x%" PRIx64, al->sym->name,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002148 al->addr - al->sym->start);
2149 else if (al->map)
Arnaldo Carvalho de Melo4414a3c2014-07-08 15:39:21 -03002150 fprintf(f, "0x%" PRIx64, al->addr);
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002151 else
Arnaldo Carvalho de Melo4414a3c2014-07-08 15:39:21 -03002152 fprintf(f, "0x%" PRIx64, sample->addr);
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002153}
2154
2155static int trace__pgfault(struct trace *trace,
2156 struct perf_evsel *evsel,
Arnaldo Carvalho de Melo473398a2016-03-22 18:23:43 -03002157 union perf_event *event __maybe_unused,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002158 struct perf_sample *sample)
2159{
2160 struct thread *thread;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002161 struct addr_location al;
2162 char map_type = 'd';
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04002163 struct thread_trace *ttrace;
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002164 int err = -1;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002165
2166 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04002167 ttrace = thread__trace(thread, trace->output);
2168 if (ttrace == NULL)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002169 goto out_put;
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04002170
2171 if (evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ)
2172 ttrace->pfmaj++;
2173 else
2174 ttrace->pfmin++;
2175
2176 if (trace->summary_only)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002177 goto out;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002178
Arnaldo Carvalho de Melo473398a2016-03-22 18:23:43 -03002179 thread__find_addr_location(thread, sample->cpumode, MAP__FUNCTION,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002180 sample->ip, &al);
2181
2182 trace__fprintf_entry_head(trace, thread, 0, sample->time, trace->output);
2183
2184 fprintf(trace->output, "%sfault [",
2185 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ?
2186 "maj" : "min");
2187
2188 print_location(trace->output, sample, &al, false, true);
2189
2190 fprintf(trace->output, "] => ");
2191
Arnaldo Carvalho de Melo473398a2016-03-22 18:23:43 -03002192 thread__find_addr_location(thread, sample->cpumode, MAP__VARIABLE,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002193 sample->addr, &al);
2194
2195 if (!al.map) {
Arnaldo Carvalho de Melo473398a2016-03-22 18:23:43 -03002196 thread__find_addr_location(thread, sample->cpumode,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002197 MAP__FUNCTION, sample->addr, &al);
2198
2199 if (al.map)
2200 map_type = 'x';
2201 else
2202 map_type = '?';
2203 }
2204
2205 print_location(trace->output, sample, &al, true, false);
2206
2207 fprintf(trace->output, " (%c%c)\n", map_type, al.level);
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002208out:
2209 err = 0;
2210out_put:
2211 thread__put(thread);
2212 return err;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002213}
2214
David Ahernbdc89662013-08-28 22:29:53 -06002215static bool skip_sample(struct trace *trace, struct perf_sample *sample)
2216{
2217 if ((trace->pid_list && intlist__find(trace->pid_list, sample->pid)) ||
2218 (trace->tid_list && intlist__find(trace->tid_list, sample->tid)))
2219 return false;
2220
2221 if (trace->pid_list || trace->tid_list)
2222 return true;
2223
2224 return false;
2225}
2226
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03002227static void trace__set_base_time(struct trace *trace,
Arnaldo Carvalho de Melo8a07a802016-03-31 15:19:39 -03002228 struct perf_evsel *evsel,
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03002229 struct perf_sample *sample)
2230{
Arnaldo Carvalho de Melo8a07a802016-03-31 15:19:39 -03002231 /*
2232 * BPF events were not setting PERF_SAMPLE_TIME, so be more robust
2233 * and don't use sample->time unconditionally, we may end up having
2234 * some other event in the future without PERF_SAMPLE_TIME for good
2235 * reason, i.e. we may not be interested in its timestamps, just in
2236 * it taking place, picking some piece of information when it
2237 * appears in our event stream (vfs_getname comes to mind).
2238 */
2239 if (trace->base_time == 0 && !trace->full_time &&
2240 (evsel->attr.sample_type & PERF_SAMPLE_TIME))
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03002241 trace->base_time = sample->time;
2242}
2243
David Ahern6810fc92013-08-28 22:29:52 -06002244static int trace__process_sample(struct perf_tool *tool,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04002245 union perf_event *event,
David Ahern6810fc92013-08-28 22:29:52 -06002246 struct perf_sample *sample,
2247 struct perf_evsel *evsel,
2248 struct machine *machine __maybe_unused)
2249{
2250 struct trace *trace = container_of(tool, struct trace, tool);
2251 int err = 0;
2252
Arnaldo Carvalho de Melo744a9712013-11-06 10:17:38 -03002253 tracepoint_handler handler = evsel->handler;
David Ahern6810fc92013-08-28 22:29:52 -06002254
David Ahernbdc89662013-08-28 22:29:53 -06002255 if (skip_sample(trace, sample))
2256 return 0;
2257
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03002258 trace__set_base_time(trace, evsel, sample);
David Ahern6810fc92013-08-28 22:29:52 -06002259
David Ahern31605652013-12-04 19:41:41 -07002260 if (handler) {
2261 ++trace->nr_events;
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04002262 handler(trace, evsel, event, sample);
David Ahern31605652013-12-04 19:41:41 -07002263 }
David Ahern6810fc92013-08-28 22:29:52 -06002264
2265 return err;
2266}
2267
David Ahernbdc89662013-08-28 22:29:53 -06002268static int parse_target_str(struct trace *trace)
2269{
2270 if (trace->opts.target.pid) {
2271 trace->pid_list = intlist__new(trace->opts.target.pid);
2272 if (trace->pid_list == NULL) {
2273 pr_err("Error parsing process id string\n");
2274 return -EINVAL;
2275 }
2276 }
2277
2278 if (trace->opts.target.tid) {
2279 trace->tid_list = intlist__new(trace->opts.target.tid);
2280 if (trace->tid_list == NULL) {
2281 pr_err("Error parsing thread id string\n");
2282 return -EINVAL;
2283 }
2284 }
2285
2286 return 0;
2287}
2288
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002289static int trace__record(struct trace *trace, int argc, const char **argv)
David Ahern5e2485b2013-09-28 13:13:01 -06002290{
2291 unsigned int rec_argc, i, j;
2292 const char **rec_argv;
2293 const char * const record_args[] = {
2294 "record",
2295 "-R",
2296 "-m", "1024",
2297 "-c", "1",
David Ahern5e2485b2013-09-28 13:13:01 -06002298 };
2299
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002300 const char * const sc_args[] = { "-e", };
2301 unsigned int sc_args_nr = ARRAY_SIZE(sc_args);
2302 const char * const majpf_args[] = { "-e", "major-faults" };
2303 unsigned int majpf_args_nr = ARRAY_SIZE(majpf_args);
2304 const char * const minpf_args[] = { "-e", "minor-faults" };
2305 unsigned int minpf_args_nr = ARRAY_SIZE(minpf_args);
2306
David Ahern9aca7f12013-12-04 19:41:39 -07002307 /* +1 is for the event string below */
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002308 rec_argc = ARRAY_SIZE(record_args) + sc_args_nr + 1 +
2309 majpf_args_nr + minpf_args_nr + argc;
David Ahern5e2485b2013-09-28 13:13:01 -06002310 rec_argv = calloc(rec_argc + 1, sizeof(char *));
2311
2312 if (rec_argv == NULL)
2313 return -ENOMEM;
2314
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002315 j = 0;
David Ahern5e2485b2013-09-28 13:13:01 -06002316 for (i = 0; i < ARRAY_SIZE(record_args); i++)
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002317 rec_argv[j++] = record_args[i];
2318
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002319 if (trace->trace_syscalls) {
2320 for (i = 0; i < sc_args_nr; i++)
2321 rec_argv[j++] = sc_args[i];
David Ahern5e2485b2013-09-28 13:13:01 -06002322
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002323 /* event string may be different for older kernels - e.g., RHEL6 */
2324 if (is_valid_tracepoint("raw_syscalls:sys_enter"))
2325 rec_argv[j++] = "raw_syscalls:sys_enter,raw_syscalls:sys_exit";
2326 else if (is_valid_tracepoint("syscalls:sys_enter"))
2327 rec_argv[j++] = "syscalls:sys_enter,syscalls:sys_exit";
2328 else {
2329 pr_err("Neither raw_syscalls nor syscalls events exist.\n");
2330 return -1;
2331 }
David Ahern9aca7f12013-12-04 19:41:39 -07002332 }
David Ahern9aca7f12013-12-04 19:41:39 -07002333
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002334 if (trace->trace_pgfaults & TRACE_PFMAJ)
2335 for (i = 0; i < majpf_args_nr; i++)
2336 rec_argv[j++] = majpf_args[i];
David Ahern5e2485b2013-09-28 13:13:01 -06002337
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002338 if (trace->trace_pgfaults & TRACE_PFMIN)
2339 for (i = 0; i < minpf_args_nr; i++)
2340 rec_argv[j++] = minpf_args[i];
2341
2342 for (i = 0; i < (unsigned int)argc; i++)
2343 rec_argv[j++] = argv[i];
2344
2345 return cmd_record(j, rec_argv, NULL);
David Ahern5e2485b2013-09-28 13:13:01 -06002346}
2347
David Ahernbf2575c2013-10-08 21:26:53 -06002348static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp);
2349
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002350static bool perf_evlist__add_vfs_getname(struct perf_evlist *evlist)
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002351{
Arnaldo Carvalho de Meloef503832013-11-07 16:41:19 -03002352 struct perf_evsel *evsel = perf_evsel__newtp("probe", "vfs_getname");
Jiri Olsa8dd2a132015-09-07 10:38:06 +02002353
2354 if (IS_ERR(evsel))
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002355 return false;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002356
2357 if (perf_evsel__field(evsel, "pathname") == NULL) {
2358 perf_evsel__delete(evsel);
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002359 return false;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002360 }
2361
Arnaldo Carvalho de Melo744a9712013-11-06 10:17:38 -03002362 evsel->handler = trace__vfs_getname;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002363 perf_evlist__add(evlist, evsel);
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002364 return true;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002365}
2366
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002367static int perf_evlist__add_pgfault(struct perf_evlist *evlist,
2368 u64 config)
2369{
2370 struct perf_evsel *evsel;
2371 struct perf_event_attr attr = {
2372 .type = PERF_TYPE_SOFTWARE,
2373 .mmap_data = 1,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002374 };
2375
2376 attr.config = config;
Arnaldo Carvalho de Melo05247982014-07-23 18:15:09 -03002377 attr.sample_period = 1;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002378
2379 event_attr_init(&attr);
2380
2381 evsel = perf_evsel__new(&attr);
2382 if (!evsel)
2383 return -ENOMEM;
2384
2385 evsel->handler = trace__pgfault;
2386 perf_evlist__add(evlist, evsel);
2387
2388 return 0;
2389}
2390
Arnaldo Carvalho de Meloddbb1b12015-02-21 12:10:29 -08002391static void trace__handle_event(struct trace *trace, union perf_event *event, struct perf_sample *sample)
2392{
2393 const u32 type = event->header.type;
2394 struct perf_evsel *evsel;
2395
Arnaldo Carvalho de Meloddbb1b12015-02-21 12:10:29 -08002396 if (type != PERF_RECORD_SAMPLE) {
2397 trace__process_event(trace, trace->host, event, sample);
2398 return;
2399 }
2400
2401 evsel = perf_evlist__id2evsel(trace->evlist, sample->id);
2402 if (evsel == NULL) {
2403 fprintf(trace->output, "Unknown tp ID %" PRIu64 ", skipping...\n", sample->id);
2404 return;
2405 }
2406
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03002407 trace__set_base_time(trace, evsel, sample);
2408
Arnaldo Carvalho de Meloddbb1b12015-02-21 12:10:29 -08002409 if (evsel->attr.type == PERF_TYPE_TRACEPOINT &&
2410 sample->raw_data == NULL) {
2411 fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n",
2412 perf_evsel__name(evsel), sample->tid,
2413 sample->cpu, sample->raw_size);
2414 } else {
2415 tracepoint_handler handler = evsel->handler;
2416 handler(trace, evsel, event, sample);
2417 }
2418}
2419
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03002420static int trace__add_syscall_newtp(struct trace *trace)
2421{
2422 int ret = -1;
2423 struct perf_evlist *evlist = trace->evlist;
2424 struct perf_evsel *sys_enter, *sys_exit;
2425
2426 sys_enter = perf_evsel__syscall_newtp("sys_enter", trace__sys_enter);
2427 if (sys_enter == NULL)
2428 goto out;
2429
2430 if (perf_evsel__init_sc_tp_ptr_field(sys_enter, args))
2431 goto out_delete_sys_enter;
2432
2433 sys_exit = perf_evsel__syscall_newtp("sys_exit", trace__sys_exit);
2434 if (sys_exit == NULL)
2435 goto out_delete_sys_enter;
2436
2437 if (perf_evsel__init_sc_tp_uint_field(sys_exit, ret))
2438 goto out_delete_sys_exit;
2439
2440 perf_evlist__add(evlist, sys_enter);
2441 perf_evlist__add(evlist, sys_exit);
2442
Arnaldo Carvalho de Melo44621812016-04-11 15:49:11 -03002443 if (trace->opts.callgraph_set && !trace->kernel_syscallchains) {
2444 /*
2445 * We're interested only in the user space callchain
2446 * leading to the syscall, allow overriding that for
2447 * debugging reasons using --kernel_syscall_callchains
2448 */
2449 sys_exit->attr.exclude_callchain_kernel = 1;
2450 }
2451
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03002452 trace->syscalls.events.sys_enter = sys_enter;
2453 trace->syscalls.events.sys_exit = sys_exit;
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03002454
2455 ret = 0;
2456out:
2457 return ret;
2458
2459out_delete_sys_exit:
2460 perf_evsel__delete_priv(sys_exit);
2461out_delete_sys_enter:
2462 perf_evsel__delete_priv(sys_enter);
2463 goto out;
2464}
2465
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002466static int trace__set_ev_qualifier_filter(struct trace *trace)
2467{
2468 int err = -1;
2469 char *filter = asprintf_expr_inout_ints("id", !trace->not_ev_qualifier,
2470 trace->ev_qualifier_ids.nr,
2471 trace->ev_qualifier_ids.entries);
2472
2473 if (filter == NULL)
2474 goto out_enomem;
2475
2476 if (!perf_evsel__append_filter(trace->syscalls.events.sys_enter, "&&", filter))
2477 err = perf_evsel__append_filter(trace->syscalls.events.sys_exit, "&&", filter);
2478
2479 free(filter);
2480out:
2481 return err;
2482out_enomem:
2483 errno = ENOMEM;
2484 goto out;
2485}
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03002486
Namhyung Kimf15eb532012-10-05 14:02:16 +09002487static int trace__run(struct trace *trace, int argc, const char **argv)
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002488{
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002489 struct perf_evlist *evlist = trace->evlist;
Arnaldo Carvalho de Melo94ad89b2015-07-03 17:42:03 -03002490 struct perf_evsel *evsel;
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03002491 int err = -1, i;
2492 unsigned long before;
Namhyung Kimf15eb532012-10-05 14:02:16 +09002493 const bool forks = argc > 0;
Arnaldo Carvalho de Melo46fb3c22014-09-22 14:39:48 -03002494 bool draining = false;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002495
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03002496 trace->live = true;
2497
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03002498 if (trace->trace_syscalls && trace__add_syscall_newtp(trace))
Arnaldo Carvalho de Melo801c67b2015-01-22 10:52:55 -03002499 goto out_error_raw_syscalls;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002500
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002501 if (trace->trace_syscalls)
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002502 trace->vfs_getname = perf_evlist__add_vfs_getname(evlist);
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002503
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002504 if ((trace->trace_pgfaults & TRACE_PFMAJ) &&
Arnaldo Carvalho de Meloe2726d92015-01-22 10:34:22 -03002505 perf_evlist__add_pgfault(evlist, PERF_COUNT_SW_PAGE_FAULTS_MAJ)) {
Arnaldo Carvalho de Melo5ed08da2015-01-22 11:08:04 -03002506 goto out_error_mem;
Arnaldo Carvalho de Meloe2726d92015-01-22 10:34:22 -03002507 }
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002508
2509 if ((trace->trace_pgfaults & TRACE_PFMIN) &&
2510 perf_evlist__add_pgfault(evlist, PERF_COUNT_SW_PAGE_FAULTS_MIN))
Arnaldo Carvalho de Melo5ed08da2015-01-22 11:08:04 -03002511 goto out_error_mem;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002512
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002513 if (trace->sched &&
Arnaldo Carvalho de Melo2cc990b2015-01-22 11:13:43 -03002514 perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime",
2515 trace__sched_stat_runtime))
2516 goto out_error_sched_stat_runtime;
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002517
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002518 err = perf_evlist__create_maps(evlist, &trace->opts.target);
2519 if (err < 0) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002520 fprintf(trace->output, "Problems parsing the target to trace, check your options!\n");
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002521 goto out_delete_evlist;
2522 }
2523
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03002524 err = trace__symbols_init(trace, evlist);
2525 if (err < 0) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002526 fprintf(trace->output, "Problems initializing symbol libraries!\n");
Arnaldo Carvalho de Melo03ad9742014-01-03 15:56:06 -03002527 goto out_delete_evlist;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03002528 }
2529
Arnaldo Carvalho de Melofde54b72016-04-11 18:42:37 -03002530 perf_evlist__config(evlist, &trace->opts, NULL);
2531
2532 if (trace->opts.callgraph_set && trace->syscalls.events.sys_exit) {
2533 perf_evsel__config_callchain(trace->syscalls.events.sys_exit,
2534 &trace->opts, &callchain_param);
2535 /*
2536 * Now we have evsels with different sample_ids, use
2537 * PERF_SAMPLE_IDENTIFIER to map from sample to evsel
2538 * from a fixed position in each ring buffer record.
2539 *
2540 * As of this the changeset introducing this comment, this
2541 * isn't strictly needed, as the fields that can come before
2542 * PERF_SAMPLE_ID are all used, but we'll probably disable
2543 * some of those for things like copying the payload of
2544 * pointer syscall arguments, and for vfs_getname we don't
2545 * need PERF_SAMPLE_ADDR and PERF_SAMPLE_IP, so do this
2546 * here as a warning we need to use PERF_SAMPLE_IDENTIFIER.
2547 */
2548 perf_evlist__set_sample_bit(evlist, IDENTIFIER);
2549 perf_evlist__reset_sample_bit(evlist, ID);
2550 }
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002551
Namhyung Kimf15eb532012-10-05 14:02:16 +09002552 signal(SIGCHLD, sig_handler);
2553 signal(SIGINT, sig_handler);
2554
2555 if (forks) {
Namhyung Kim6ef73ec2013-03-11 16:43:15 +09002556 err = perf_evlist__prepare_workload(evlist, &trace->opts.target,
Arnaldo Carvalho de Melo735f7e02014-01-03 14:56:49 -03002557 argv, false, NULL);
Namhyung Kimf15eb532012-10-05 14:02:16 +09002558 if (err < 0) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002559 fprintf(trace->output, "Couldn't run the workload!\n");
Arnaldo Carvalho de Melo03ad9742014-01-03 15:56:06 -03002560 goto out_delete_evlist;
Namhyung Kimf15eb532012-10-05 14:02:16 +09002561 }
2562 }
2563
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002564 err = perf_evlist__open(evlist);
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002565 if (err < 0)
2566 goto out_error_open;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002567
Wang Nanba504232016-02-26 09:31:54 +00002568 err = bpf__apply_obj_config();
2569 if (err) {
2570 char errbuf[BUFSIZ];
2571
2572 bpf__strerror_apply_obj_config(err, errbuf, sizeof(errbuf));
2573 pr_err("ERROR: Apply config to BPF failed: %s\n",
2574 errbuf);
2575 goto out_error_open;
2576 }
2577
Arnaldo Carvalho de Melo241b0572015-02-21 10:15:21 -08002578 /*
2579 * Better not use !target__has_task() here because we need to cover the
2580 * case where no threads were specified in the command line, but a
2581 * workload was, and in that case we will fill in the thread_map when
2582 * we fork the workload in perf_evlist__prepare_workload.
2583 */
Arnaldo Carvalho de Melof078c382015-02-21 11:36:52 -08002584 if (trace->filter_pids.nr > 0)
2585 err = perf_evlist__set_filter_pids(evlist, trace->filter_pids.nr, trace->filter_pids.entries);
Jiri Olsae13798c2015-06-23 00:36:02 +02002586 else if (thread_map__pid(evlist->threads, 0) == -1)
Arnaldo Carvalho de Melof078c382015-02-21 11:36:52 -08002587 err = perf_evlist__set_filter_pid(evlist, getpid());
2588
Arnaldo Carvalho de Melo94ad89b2015-07-03 17:42:03 -03002589 if (err < 0)
2590 goto out_error_mem;
2591
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002592 if (trace->ev_qualifier_ids.nr > 0) {
2593 err = trace__set_ev_qualifier_filter(trace);
2594 if (err < 0)
2595 goto out_errno;
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002596
Arnaldo Carvalho de Melo2e5e5f82015-08-03 17:12:29 -03002597 pr_debug("event qualifier tracepoint filter: %s\n",
2598 trace->syscalls.events.sys_exit->filter);
2599 }
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002600
Arnaldo Carvalho de Melo94ad89b2015-07-03 17:42:03 -03002601 err = perf_evlist__apply_filters(evlist, &evsel);
2602 if (err < 0)
2603 goto out_error_apply_filters;
Arnaldo Carvalho de Melo241b0572015-02-21 10:15:21 -08002604
Jiri Olsaf8850372013-11-28 17:57:22 +01002605 err = perf_evlist__mmap(evlist, trace->opts.mmap_pages, false);
Arnaldo Carvalho de Meloe09b18d2014-12-11 18:04:10 -03002606 if (err < 0)
2607 goto out_error_mmap;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002608
Arnaldo Carvalho de Melocb24d012015-04-22 10:04:23 -03002609 if (!target__none(&trace->opts.target))
2610 perf_evlist__enable(evlist);
2611
Namhyung Kimf15eb532012-10-05 14:02:16 +09002612 if (forks)
2613 perf_evlist__start_workload(evlist);
2614
Jiri Olsae13798c2015-06-23 00:36:02 +02002615 trace->multiple_threads = thread_map__pid(evlist->threads, 0) == -1 ||
Arnaldo Carvalho de Melo42052be2015-02-13 12:32:45 -03002616 evlist->threads->nr > 1 ||
2617 perf_evlist__first(evlist)->attr.inherit;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002618again:
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03002619 before = trace->nr_events;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002620
2621 for (i = 0; i < evlist->nr_mmaps; i++) {
2622 union perf_event *event;
2623
2624 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002625 struct perf_sample sample;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002626
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03002627 ++trace->nr_events;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002628
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002629 err = perf_evlist__parse_sample(evlist, event, &sample);
2630 if (err) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002631 fprintf(trace->output, "Can't parse sample, err = %d, skipping...\n", err);
Zhouyi Zhou8e50d382013-10-24 15:43:33 +08002632 goto next_event;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002633 }
2634
Arnaldo Carvalho de Meloddbb1b12015-02-21 12:10:29 -08002635 trace__handle_event(trace, event, &sample);
Zhouyi Zhou8e50d382013-10-24 15:43:33 +08002636next_event:
2637 perf_evlist__mmap_consume(evlist, i);
Arnaldo Carvalho de Melo20c5f102013-09-03 11:55:07 -03002638
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002639 if (interrupted)
2640 goto out_disable;
Arnaldo Carvalho de Melo02ac5422015-04-22 11:11:57 -03002641
2642 if (done && !draining) {
2643 perf_evlist__disable(evlist);
2644 draining = true;
2645 }
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002646 }
2647 }
2648
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03002649 if (trace->nr_events == before) {
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002650 int timeout = done ? 100 : -1;
Namhyung Kimf15eb532012-10-05 14:02:16 +09002651
Arnaldo Carvalho de Melo46fb3c22014-09-22 14:39:48 -03002652 if (!draining && perf_evlist__poll(evlist, timeout) > 0) {
2653 if (perf_evlist__filter_pollfd(evlist, POLLERR | POLLHUP) == 0)
2654 draining = true;
2655
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002656 goto again;
Arnaldo Carvalho de Melo46fb3c22014-09-22 14:39:48 -03002657 }
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002658 } else {
2659 goto again;
Namhyung Kimf15eb532012-10-05 14:02:16 +09002660 }
2661
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002662out_disable:
Arnaldo Carvalho de Melof3b623b2015-03-02 22:21:35 -03002663 thread__zput(trace->current);
2664
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002665 perf_evlist__disable(evlist);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002666
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002667 if (!err) {
2668 if (trace->summary)
2669 trace__fprintf_thread_summary(trace, trace->output);
2670
2671 if (trace->show_tool_stats) {
2672 fprintf(trace->output, "Stats:\n "
2673 " vfs_getname : %" PRIu64 "\n"
2674 " proc_getname: %" PRIu64 "\n",
2675 trace->stats.vfs_getname,
2676 trace->stats.proc_getname);
2677 }
2678 }
David Ahernbf2575c2013-10-08 21:26:53 -06002679
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002680out_delete_evlist:
2681 perf_evlist__delete(evlist);
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002682 trace->evlist = NULL;
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03002683 trace->live = false;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002684 return err;
Arnaldo Carvalho de Melo6ef068c2013-10-17 12:07:58 -03002685{
2686 char errbuf[BUFSIZ];
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002687
Arnaldo Carvalho de Melo2cc990b2015-01-22 11:13:43 -03002688out_error_sched_stat_runtime:
Jiri Olsa988bdb32015-09-02 09:56:35 +02002689 tracing_path__strerror_open_tp(errno, errbuf, sizeof(errbuf), "sched", "sched_stat_runtime");
Arnaldo Carvalho de Melo2cc990b2015-01-22 11:13:43 -03002690 goto out_error;
2691
Arnaldo Carvalho de Melo801c67b2015-01-22 10:52:55 -03002692out_error_raw_syscalls:
Jiri Olsa988bdb32015-09-02 09:56:35 +02002693 tracing_path__strerror_open_tp(errno, errbuf, sizeof(errbuf), "raw_syscalls", "sys_(enter|exit)");
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002694 goto out_error;
2695
Arnaldo Carvalho de Meloe09b18d2014-12-11 18:04:10 -03002696out_error_mmap:
2697 perf_evlist__strerror_mmap(evlist, errno, errbuf, sizeof(errbuf));
2698 goto out_error;
2699
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002700out_error_open:
2701 perf_evlist__strerror_open(evlist, errno, errbuf, sizeof(errbuf));
2702
2703out_error:
Arnaldo Carvalho de Melo6ef068c2013-10-17 12:07:58 -03002704 fprintf(trace->output, "%s\n", errbuf);
Ramkumar Ramachandra87f91862013-10-04 10:47:31 +05302705 goto out_delete_evlist;
Arnaldo Carvalho de Melo94ad89b2015-07-03 17:42:03 -03002706
2707out_error_apply_filters:
2708 fprintf(trace->output,
2709 "Failed to set filter \"%s\" on event %s with %d (%s)\n",
2710 evsel->filter, perf_evsel__name(evsel), errno,
2711 strerror_r(errno, errbuf, sizeof(errbuf)));
2712 goto out_delete_evlist;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002713}
Arnaldo Carvalho de Melo5ed08da2015-01-22 11:08:04 -03002714out_error_mem:
2715 fprintf(trace->output, "Not enough memory to run!\n");
2716 goto out_delete_evlist;
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002717
2718out_errno:
2719 fprintf(trace->output, "errno=%d,%s\n", errno, strerror(errno));
2720 goto out_delete_evlist;
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002721}
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002722
David Ahern6810fc92013-08-28 22:29:52 -06002723static int trace__replay(struct trace *trace)
2724{
2725 const struct perf_evsel_str_handler handlers[] = {
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002726 { "probe:vfs_getname", trace__vfs_getname, },
David Ahern6810fc92013-08-28 22:29:52 -06002727 };
Jiri Olsaf5fc14122013-10-15 16:27:32 +02002728 struct perf_data_file file = {
2729 .path = input_name,
2730 .mode = PERF_DATA_MODE_READ,
Yunlong Songe366a6d2015-04-02 21:47:18 +08002731 .force = trace->force,
Jiri Olsaf5fc14122013-10-15 16:27:32 +02002732 };
David Ahern6810fc92013-08-28 22:29:52 -06002733 struct perf_session *session;
Namhyung Kim003824e2013-11-12 15:25:00 +09002734 struct perf_evsel *evsel;
David Ahern6810fc92013-08-28 22:29:52 -06002735 int err = -1;
2736
2737 trace->tool.sample = trace__process_sample;
2738 trace->tool.mmap = perf_event__process_mmap;
David Ahern384c6712013-09-22 19:44:58 -06002739 trace->tool.mmap2 = perf_event__process_mmap2;
David Ahern6810fc92013-08-28 22:29:52 -06002740 trace->tool.comm = perf_event__process_comm;
2741 trace->tool.exit = perf_event__process_exit;
2742 trace->tool.fork = perf_event__process_fork;
2743 trace->tool.attr = perf_event__process_attr;
2744 trace->tool.tracing_data = perf_event__process_tracing_data;
2745 trace->tool.build_id = perf_event__process_build_id;
2746
Jiri Olsa0a8cb852014-07-06 14:18:21 +02002747 trace->tool.ordered_events = true;
David Ahern6810fc92013-08-28 22:29:52 -06002748 trace->tool.ordering_requires_timestamps = true;
2749
2750 /* add tid to output */
2751 trace->multiple_threads = true;
2752
Jiri Olsaf5fc14122013-10-15 16:27:32 +02002753 session = perf_session__new(&file, false, &trace->tool);
David Ahern6810fc92013-08-28 22:29:52 -06002754 if (session == NULL)
Taeung Song52e028342014-09-24 10:33:37 +09002755 return -1;
David Ahern6810fc92013-08-28 22:29:52 -06002756
Namhyung Kim0a7e6d12014-08-12 15:40:45 +09002757 if (symbol__init(&session->header.env) < 0)
Namhyung Kimcb2ffae2014-08-12 15:40:44 +09002758 goto out;
2759
David Ahern8fb598e2013-09-28 13:13:00 -06002760 trace->host = &session->machines.host;
2761
David Ahern6810fc92013-08-28 22:29:52 -06002762 err = perf_session__set_tracepoints_handlers(session, handlers);
2763 if (err)
2764 goto out;
2765
Namhyung Kim003824e2013-11-12 15:25:00 +09002766 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2767 "raw_syscalls:sys_enter");
David Ahern9aca7f12013-12-04 19:41:39 -07002768 /* older kernels have syscalls tp versus raw_syscalls */
2769 if (evsel == NULL)
2770 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2771 "syscalls:sys_enter");
David Ahern6810fc92013-08-28 22:29:52 -06002772
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002773 if (evsel &&
2774 (perf_evsel__init_syscall_tp(evsel, trace__sys_enter) < 0 ||
2775 perf_evsel__init_sc_tp_ptr_field(evsel, args))) {
Namhyung Kim003824e2013-11-12 15:25:00 +09002776 pr_err("Error during initialize raw_syscalls:sys_enter event\n");
2777 goto out;
2778 }
2779
2780 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2781 "raw_syscalls:sys_exit");
David Ahern9aca7f12013-12-04 19:41:39 -07002782 if (evsel == NULL)
2783 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2784 "syscalls:sys_exit");
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002785 if (evsel &&
2786 (perf_evsel__init_syscall_tp(evsel, trace__sys_exit) < 0 ||
2787 perf_evsel__init_sc_tp_uint_field(evsel, ret))) {
Namhyung Kim003824e2013-11-12 15:25:00 +09002788 pr_err("Error during initialize raw_syscalls:sys_exit event\n");
David Ahern6810fc92013-08-28 22:29:52 -06002789 goto out;
2790 }
2791
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002792 evlist__for_each(session->evlist, evsel) {
2793 if (evsel->attr.type == PERF_TYPE_SOFTWARE &&
2794 (evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ||
2795 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MIN ||
2796 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS))
2797 evsel->handler = trace__pgfault;
2798 }
2799
David Ahernbdc89662013-08-28 22:29:53 -06002800 err = parse_target_str(trace);
2801 if (err != 0)
2802 goto out;
2803
David Ahern6810fc92013-08-28 22:29:52 -06002804 setup_pager();
2805
Arnaldo Carvalho de Melob7b61cb2015-03-03 11:58:45 -03002806 err = perf_session__process_events(session);
David Ahern6810fc92013-08-28 22:29:52 -06002807 if (err)
2808 pr_err("Failed to process events, error %d", err);
2809
David Ahernbf2575c2013-10-08 21:26:53 -06002810 else if (trace->summary)
2811 trace__fprintf_thread_summary(trace, trace->output);
2812
David Ahern6810fc92013-08-28 22:29:52 -06002813out:
2814 perf_session__delete(session);
2815
2816 return err;
2817}
2818
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002819static size_t trace__fprintf_threads_header(FILE *fp)
2820{
2821 size_t printed;
2822
Pekka Enberg99ff7152013-11-12 16:42:14 +02002823 printed = fprintf(fp, "\n Summary of events:\n\n");
David Ahernbf2575c2013-10-08 21:26:53 -06002824
2825 return printed;
2826}
2827
2828static size_t thread__dump_stats(struct thread_trace *ttrace,
2829 struct trace *trace, FILE *fp)
2830{
2831 struct stats *stats;
2832 size_t printed = 0;
2833 struct syscall *sc;
2834 struct int_node *inode = intlist__first(ttrace->syscall_stats);
2835
2836 if (inode == NULL)
2837 return 0;
2838
2839 printed += fprintf(fp, "\n");
2840
Milian Wolff834fd462015-08-06 11:24:29 +02002841 printed += fprintf(fp, " syscall calls total min avg max stddev\n");
2842 printed += fprintf(fp, " (msec) (msec) (msec) (msec) (%%)\n");
2843 printed += fprintf(fp, " --------------- -------- --------- --------- --------- --------- ------\n");
Pekka Enberg99ff7152013-11-12 16:42:14 +02002844
David Ahernbf2575c2013-10-08 21:26:53 -06002845 /* each int_node is a syscall */
2846 while (inode) {
2847 stats = inode->priv;
2848 if (stats) {
2849 double min = (double)(stats->min) / NSEC_PER_MSEC;
2850 double max = (double)(stats->max) / NSEC_PER_MSEC;
2851 double avg = avg_stats(stats);
2852 double pct;
2853 u64 n = (u64) stats->n;
2854
2855 pct = avg ? 100.0 * stddev_stats(stats)/avg : 0.0;
2856 avg /= NSEC_PER_MSEC;
2857
2858 sc = &trace->syscalls.table[inode->i];
Pekka Enberg99ff7152013-11-12 16:42:14 +02002859 printed += fprintf(fp, " %-15s", sc->name);
Milian Wolff834fd462015-08-06 11:24:29 +02002860 printed += fprintf(fp, " %8" PRIu64 " %9.3f %9.3f %9.3f",
2861 n, avg * n, min, avg);
Pekka Enberg27a778b2013-11-13 14:21:48 +02002862 printed += fprintf(fp, " %9.3f %9.2f%%\n", max, pct);
David Ahernbf2575c2013-10-08 21:26:53 -06002863 }
2864
2865 inode = intlist__next(inode);
2866 }
2867
2868 printed += fprintf(fp, "\n\n");
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002869
2870 return printed;
2871}
2872
David Ahern896cbb52013-09-28 13:12:59 -06002873/* struct used to pass data to per-thread function */
2874struct summary_data {
2875 FILE *fp;
2876 struct trace *trace;
2877 size_t printed;
2878};
2879
2880static int trace__fprintf_one_thread(struct thread *thread, void *priv)
2881{
2882 struct summary_data *data = priv;
2883 FILE *fp = data->fp;
2884 size_t printed = data->printed;
2885 struct trace *trace = data->trace;
Namhyung Kim89dceb22014-10-06 09:46:03 +09002886 struct thread_trace *ttrace = thread__priv(thread);
David Ahern896cbb52013-09-28 13:12:59 -06002887 double ratio;
2888
2889 if (ttrace == NULL)
2890 return 0;
2891
2892 ratio = (double)ttrace->nr_events / trace->nr_events * 100.0;
2893
Pekka Enberg15e65c62013-11-14 18:43:30 +02002894 printed += fprintf(fp, " %s (%d), ", thread__comm_str(thread), thread->tid);
Pekka Enberg99ff7152013-11-12 16:42:14 +02002895 printed += fprintf(fp, "%lu events, ", ttrace->nr_events);
Pekka Enberg15e65c62013-11-14 18:43:30 +02002896 printed += fprintf(fp, "%.1f%%", ratio);
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04002897 if (ttrace->pfmaj)
2898 printed += fprintf(fp, ", %lu majfaults", ttrace->pfmaj);
2899 if (ttrace->pfmin)
2900 printed += fprintf(fp, ", %lu minfaults", ttrace->pfmin);
Pekka Enberg99ff7152013-11-12 16:42:14 +02002901 printed += fprintf(fp, ", %.3f msec\n", ttrace->runtime_ms);
David Ahernbf2575c2013-10-08 21:26:53 -06002902 printed += thread__dump_stats(ttrace, trace, fp);
David Ahern896cbb52013-09-28 13:12:59 -06002903
2904 data->printed += printed;
2905
2906 return 0;
2907}
2908
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002909static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp)
2910{
David Ahern896cbb52013-09-28 13:12:59 -06002911 struct summary_data data = {
2912 .fp = fp,
2913 .trace = trace
2914 };
2915 data.printed = trace__fprintf_threads_header(fp);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002916
David Ahern896cbb52013-09-28 13:12:59 -06002917 machine__for_each_thread(trace->host, trace__fprintf_one_thread, &data);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002918
David Ahern896cbb52013-09-28 13:12:59 -06002919 return data.printed;
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002920}
2921
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03002922static int trace__set_duration(const struct option *opt, const char *str,
2923 int unset __maybe_unused)
2924{
2925 struct trace *trace = opt->value;
2926
2927 trace->duration_filter = atof(str);
2928 return 0;
2929}
2930
Arnaldo Carvalho de Melof078c382015-02-21 11:36:52 -08002931static int trace__set_filter_pids(const struct option *opt, const char *str,
2932 int unset __maybe_unused)
2933{
2934 int ret = -1;
2935 size_t i;
2936 struct trace *trace = opt->value;
2937 /*
2938 * FIXME: introduce a intarray class, plain parse csv and create a
2939 * { int nr, int entries[] } struct...
2940 */
2941 struct intlist *list = intlist__new(str);
2942
2943 if (list == NULL)
2944 return -1;
2945
2946 i = trace->filter_pids.nr = intlist__nr_entries(list) + 1;
2947 trace->filter_pids.entries = calloc(i, sizeof(pid_t));
2948
2949 if (trace->filter_pids.entries == NULL)
2950 goto out;
2951
2952 trace->filter_pids.entries[0] = getpid();
2953
2954 for (i = 1; i < trace->filter_pids.nr; ++i)
2955 trace->filter_pids.entries[i] = intlist__entry(list, i - 1)->i;
2956
2957 intlist__delete(list);
2958 ret = 0;
2959out:
2960 return ret;
2961}
2962
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002963static int trace__open_output(struct trace *trace, const char *filename)
2964{
2965 struct stat st;
2966
2967 if (!stat(filename, &st) && st.st_size) {
2968 char oldname[PATH_MAX];
2969
2970 scnprintf(oldname, sizeof(oldname), "%s.old", filename);
2971 unlink(oldname);
2972 rename(filename, oldname);
2973 }
2974
2975 trace->output = fopen(filename, "w");
2976
2977 return trace->output == NULL ? -errno : 0;
2978}
2979
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002980static int parse_pagefaults(const struct option *opt, const char *str,
2981 int unset __maybe_unused)
2982{
2983 int *trace_pgfaults = opt->value;
2984
2985 if (strcmp(str, "all") == 0)
2986 *trace_pgfaults |= TRACE_PFMAJ | TRACE_PFMIN;
2987 else if (strcmp(str, "maj") == 0)
2988 *trace_pgfaults |= TRACE_PFMAJ;
2989 else if (strcmp(str, "min") == 0)
2990 *trace_pgfaults |= TRACE_PFMIN;
2991 else
2992 return -1;
2993
2994 return 0;
2995}
2996
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002997static void evlist__set_evsel_handler(struct perf_evlist *evlist, void *handler)
2998{
2999 struct perf_evsel *evsel;
3000
3001 evlist__for_each(evlist, evsel)
3002 evsel->handler = handler;
3003}
3004
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003005int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
3006{
Yunlong Song6fdd9cb2015-03-18 21:35:57 +08003007 const char *trace_usage[] = {
Namhyung Kimf15eb532012-10-05 14:02:16 +09003008 "perf trace [<options>] [<command>]",
3009 "perf trace [<options>] -- <command> [<options>]",
David Ahern5e2485b2013-09-28 13:13:01 -06003010 "perf trace record [<options>] [<command>]",
3011 "perf trace record [<options>] -- <command> [<options>]",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003012 NULL
3013 };
3014 struct trace trace = {
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003015 .syscalls = {
3016 . max = -1,
3017 },
3018 .opts = {
3019 .target = {
3020 .uid = UINT_MAX,
3021 .uses_mmap = true,
3022 },
3023 .user_freq = UINT_MAX,
3024 .user_interval = ULLONG_MAX,
Arnaldo Carvalho de Melo509051e2014-01-14 17:52:14 -03003025 .no_buffering = true,
Arnaldo Carvalho de Melo38d54472014-12-12 17:28:32 -03003026 .mmap_pages = UINT_MAX,
Kan Liang9d9cad72015-06-17 09:51:11 -04003027 .proc_map_timeout = 500,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003028 },
Milian Wolff007d66a2015-08-05 16:52:23 -03003029 .output = stderr,
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -03003030 .show_comm = true,
Stanislav Fomicheve281a962014-06-26 20:14:28 +04003031 .trace_syscalls = true,
Arnaldo Carvalho de Melo44621812016-04-11 15:49:11 -03003032 .kernel_syscallchains = false,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003033 };
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003034 const char *output_name = NULL;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03003035 const char *ev_qualifier_str = NULL;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003036 const struct option trace_options[] = {
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003037 OPT_CALLBACK(0, "event", &trace.evlist, "event",
3038 "event selector. use 'perf list' to list available events",
3039 parse_events_option),
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -03003040 OPT_BOOLEAN(0, "comm", &trace.show_comm,
3041 "show the thread COMM next to its id"),
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03003042 OPT_BOOLEAN(0, "tool_stats", &trace.show_tool_stats, "show tool stats"),
Arnaldo Carvalho de Melod303e852015-04-23 12:02:07 -03003043 OPT_STRING('e', "expr", &ev_qualifier_str, "expr", "list of syscalls to trace"),
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003044 OPT_STRING('o', "output", &output_name, "file", "output file name"),
David Ahern6810fc92013-08-28 22:29:52 -06003045 OPT_STRING('i', "input", &input_name, "file", "Analyze events in file"),
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003046 OPT_STRING('p', "pid", &trace.opts.target.pid, "pid",
3047 "trace events on existing process id"),
David Ahernac9be8e2013-08-20 11:15:45 -06003048 OPT_STRING('t', "tid", &trace.opts.target.tid, "tid",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003049 "trace events on existing thread id"),
Arnaldo Carvalho de Melofa0e4ff2015-04-23 11:59:20 -03003050 OPT_CALLBACK(0, "filter-pids", &trace, "CSV list of pids",
3051 "pids to filter (by the kernel)", trace__set_filter_pids),
David Ahernac9be8e2013-08-20 11:15:45 -06003052 OPT_BOOLEAN('a', "all-cpus", &trace.opts.target.system_wide,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003053 "system-wide collection from all CPUs"),
David Ahernac9be8e2013-08-20 11:15:45 -06003054 OPT_STRING('C', "cpu", &trace.opts.target.cpu_list, "cpu",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003055 "list of cpus to monitor"),
David Ahern6810fc92013-08-28 22:29:52 -06003056 OPT_BOOLEAN(0, "no-inherit", &trace.opts.no_inherit,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003057 "child tasks do not inherit counters"),
Jiri Olsa994a1f72013-09-01 12:36:12 +02003058 OPT_CALLBACK('m', "mmap-pages", &trace.opts.mmap_pages, "pages",
3059 "number of mmap data pages",
3060 perf_evlist__parse_mmap_pages),
David Ahernac9be8e2013-08-20 11:15:45 -06003061 OPT_STRING('u', "uid", &trace.opts.target.uid_str, "user",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003062 "user to profile"),
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03003063 OPT_CALLBACK(0, "duration", &trace, "float",
3064 "show only events with duration > N.M ms",
3065 trace__set_duration),
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03003066 OPT_BOOLEAN(0, "sched", &trace.sched, "show blocking scheduler events"),
Arnaldo Carvalho de Melo7c304ee02013-08-22 16:49:54 -03003067 OPT_INCR('v', "verbose", &verbose, "be more verbose"),
David Ahern4bb09192013-09-04 12:37:43 -06003068 OPT_BOOLEAN('T', "time", &trace.full_time,
3069 "Show full timestamp, not time relative to first start"),
David Ahernfd2eaba2013-11-12 09:31:15 -07003070 OPT_BOOLEAN('s', "summary", &trace.summary_only,
3071 "Show only syscall summary with statistics"),
3072 OPT_BOOLEAN('S', "with-summary", &trace.summary,
3073 "Show all syscalls and summary with statistics"),
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04003074 OPT_CALLBACK_DEFAULT('F', "pf", &trace.trace_pgfaults, "all|maj|min",
3075 "Trace pagefaults", parse_pagefaults, "maj"),
Stanislav Fomicheve281a962014-06-26 20:14:28 +04003076 OPT_BOOLEAN(0, "syscalls", &trace.trace_syscalls, "Trace syscalls"),
Yunlong Songe366a6d2015-04-02 21:47:18 +08003077 OPT_BOOLEAN('f', "force", &trace.force, "don't complain, do it"),
Milian Wolff566a0882016-04-08 13:34:15 +02003078 OPT_CALLBACK(0, "call-graph", &trace.opts,
3079 "record_mode[,record_size]", record_callchain_help,
3080 &record_parse_callchain_opt),
Arnaldo Carvalho de Melo44621812016-04-11 15:49:11 -03003081 OPT_BOOLEAN(0, "kernel-syscall-graph", &trace.kernel_syscallchains,
3082 "Show the kernel callchains on the syscall exit path"),
Kan Liang9d9cad72015-06-17 09:51:11 -04003083 OPT_UINTEGER(0, "proc-map-timeout", &trace.opts.proc_map_timeout,
3084 "per thread proc mmap processing timeout in ms"),
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003085 OPT_END()
3086 };
Yunlong Song6fdd9cb2015-03-18 21:35:57 +08003087 const char * const trace_subcommands[] = { "record", NULL };
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003088 int err;
Namhyung Kim32caf0d2012-10-05 14:02:13 +09003089 char bf[BUFSIZ];
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003090
Arnaldo Carvalho de Melo4d08cb82015-02-24 15:35:55 -03003091 signal(SIGSEGV, sighandler_dump_stack);
3092 signal(SIGFPE, sighandler_dump_stack);
3093
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003094 trace.evlist = perf_evlist__new();
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03003095 trace.sctbl = syscalltbl__new();
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003096
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03003097 if (trace.evlist == NULL || trace.sctbl == NULL) {
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003098 pr_err("Not enough memory to run!\n");
He Kuangff8f6952015-05-11 12:28:36 +00003099 err = -ENOMEM;
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003100 goto out;
3101 }
3102
Yunlong Song6fdd9cb2015-03-18 21:35:57 +08003103 argc = parse_options_subcommand(argc, argv, trace_options, trace_subcommands,
3104 trace_usage, PARSE_OPT_STOP_AT_NON_OPTION);
David Ahernfd2eaba2013-11-12 09:31:15 -07003105
Wang Nand7888572016-04-08 15:07:24 +00003106 err = bpf__setup_stdout(trace.evlist);
3107 if (err) {
3108 bpf__strerror_setup_stdout(trace.evlist, err, bf, sizeof(bf));
3109 pr_err("ERROR: Setup BPF stdout failed: %s\n", bf);
3110 goto out;
3111 }
3112
Arnaldo Carvalho de Melo59247e32016-04-12 16:05:02 -03003113 err = -1;
3114
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04003115 if (trace.trace_pgfaults) {
3116 trace.opts.sample_address = true;
3117 trace.opts.sample_time = true;
3118 }
3119
Milian Wolff566a0882016-04-08 13:34:15 +02003120 if (trace.opts.callgraph_set)
3121 symbol_conf.use_callchain = true;
3122
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003123 if (trace.evlist->nr_entries > 0)
3124 evlist__set_evsel_handler(trace.evlist, trace__event_handler);
3125
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04003126 if ((argc >= 1) && (strcmp(argv[0], "record") == 0))
3127 return trace__record(&trace, argc-1, &argv[1]);
3128
3129 /* summary_only implies summary option, but don't overwrite summary if set */
3130 if (trace.summary_only)
3131 trace.summary = trace.summary_only;
3132
Arnaldo Carvalho de Melo726f3232015-02-06 10:16:45 +01003133 if (!trace.trace_syscalls && !trace.trace_pgfaults &&
3134 trace.evlist->nr_entries == 0 /* Was --events used? */) {
Stanislav Fomicheve281a962014-06-26 20:14:28 +04003135 pr_err("Please specify something to trace.\n");
3136 return -1;
3137 }
3138
Arnaldo Carvalho de Melo59247e32016-04-12 16:05:02 -03003139 if (!trace.trace_syscalls && ev_qualifier_str) {
3140 pr_err("The -e option can't be used with --no-syscalls.\n");
3141 goto out;
3142 }
3143
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003144 if (output_name != NULL) {
3145 err = trace__open_output(&trace, output_name);
3146 if (err < 0) {
3147 perror("failed to create output file");
3148 goto out;
3149 }
3150 }
3151
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03003152 trace.open_id = syscalltbl__id(trace.sctbl, "open");
3153
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03003154 if (ev_qualifier_str != NULL) {
Arnaldo Carvalho de Melob059efd2013-08-21 12:56:21 -03003155 const char *s = ev_qualifier_str;
Arnaldo Carvalho de Melo005438a82015-07-20 12:02:09 -03003156 struct strlist_config slist_config = {
3157 .dirname = system_path(STRACE_GROUPS_DIR),
3158 };
Arnaldo Carvalho de Melob059efd2013-08-21 12:56:21 -03003159
3160 trace.not_ev_qualifier = *s == '!';
3161 if (trace.not_ev_qualifier)
3162 ++s;
Arnaldo Carvalho de Melo005438a82015-07-20 12:02:09 -03003163 trace.ev_qualifier = strlist__new(s, &slist_config);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03003164 if (trace.ev_qualifier == NULL) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003165 fputs("Not enough memory to parse event qualifier",
3166 trace.output);
3167 err = -ENOMEM;
3168 goto out_close;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03003169 }
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03003170
3171 err = trace__validate_ev_qualifier(&trace);
3172 if (err)
3173 goto out_close;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03003174 }
3175
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003176 err = target__validate(&trace.opts.target);
Namhyung Kim32caf0d2012-10-05 14:02:13 +09003177 if (err) {
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003178 target__strerror(&trace.opts.target, err, bf, sizeof(bf));
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003179 fprintf(trace.output, "%s", bf);
3180 goto out_close;
Namhyung Kim32caf0d2012-10-05 14:02:13 +09003181 }
3182
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003183 err = target__parse_uid(&trace.opts.target);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003184 if (err) {
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003185 target__strerror(&trace.opts.target, err, bf, sizeof(bf));
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003186 fprintf(trace.output, "%s", bf);
3187 goto out_close;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003188 }
3189
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003190 if (!argc && target__none(&trace.opts.target))
Namhyung Kimee761202012-10-05 14:02:14 +09003191 trace.opts.target.system_wide = true;
3192
David Ahern6810fc92013-08-28 22:29:52 -06003193 if (input_name)
3194 err = trace__replay(&trace);
3195 else
3196 err = trace__run(&trace, argc, argv);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03003197
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003198out_close:
3199 if (output_name != NULL)
3200 fclose(trace.output);
3201out:
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03003202 return err;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003203}