blob: 5e5a95e34a5319cd729c4102d3f14322b482df13 [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 Melod327e602016-04-14 17:53:49 -03001901 return sample__fprintf_callchain(sample, 38, print_opts, &callchain_cursor, trace->output);
Arnaldo Carvalho de Melo202ff962016-04-12 10:11:07 -03001902}
1903
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001904static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04001905 union perf_event *event __maybe_unused,
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001906 struct perf_sample *sample)
1907{
Chang Hyun Park2c82c3a2014-09-26 21:54:01 +09001908 long ret;
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001909 u64 duration = 0;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001910 struct thread *thread;
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001911 int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
David Ahernbf2575c2013-10-08 21:26:53 -06001912 struct syscall *sc = trace__syscall_info(trace, evsel, id);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001913 struct thread_trace *ttrace;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001914
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001915 if (sc == NULL)
1916 return -1;
1917
David Ahern8fb598e2013-09-28 13:13:00 -06001918 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001919 ttrace = thread__trace(thread, trace->output);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001920 if (ttrace == NULL)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001921 goto out_put;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001922
David Ahernbf2575c2013-10-08 21:26:53 -06001923 if (trace->summary)
1924 thread__update_stats(ttrace, id, sample);
1925
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -03001926 ret = perf_evsel__sc_tp_uint(evsel, ret, sample);
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001927
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03001928 if (id == trace->open_id && ret >= 0 && ttrace->filename.pending_open) {
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03001929 trace__set_fd_pathname(thread, ret, ttrace->filename.name);
1930 ttrace->filename.pending_open = false;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001931 ++trace->stats.vfs_getname;
1932 }
1933
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001934 ttrace->exit_time = sample->time;
1935
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001936 if (ttrace->entry_time) {
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001937 duration = sample->time - ttrace->entry_time;
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001938 if (trace__filter_duration(trace, duration))
1939 goto out;
1940 } else if (trace->duration_filter)
1941 goto out;
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001942
David Ahernfd2eaba2013-11-12 09:31:15 -07001943 if (trace->summary_only)
1944 goto out;
1945
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001946 trace__fprintf_entry_head(trace, thread, duration, sample->time, trace->output);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001947
1948 if (ttrace->entry_pending) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001949 fprintf(trace->output, "%-70s", ttrace->entry_str);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001950 } else {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001951 fprintf(trace->output, " ... [");
1952 color_fprintf(trace->output, PERF_COLOR_YELLOW, "continued");
1953 fprintf(trace->output, "]: %s()", sc->name);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001954 }
1955
Arnaldo Carvalho de Meloda3c9a42013-08-26 11:28:34 -03001956 if (sc->fmt == NULL) {
1957signed_print:
Chang Hyun Park2c82c3a2014-09-26 21:54:01 +09001958 fprintf(trace->output, ") = %ld", ret);
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -03001959 } else if (ret < 0 && (sc->fmt->errmsg || sc->fmt->errpid)) {
Masami Hiramatsu942a91e2014-08-14 02:22:41 +00001960 char bf[STRERR_BUFSIZE];
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001961 const char *emsg = strerror_r(-ret, bf, sizeof(bf)),
1962 *e = audit_errno_to_name(-ret);
1963
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001964 fprintf(trace->output, ") = -1 %s %s", e, emsg);
Arnaldo Carvalho de Meloda3c9a42013-08-26 11:28:34 -03001965 } else if (ret == 0 && sc->fmt->timeout)
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001966 fprintf(trace->output, ") = 0 Timeout");
Arnaldo Carvalho de Melo04b34722013-08-26 11:36:30 -03001967 else if (sc->fmt->hexret)
Chang Hyun Park2c82c3a2014-09-26 21:54:01 +09001968 fprintf(trace->output, ") = %#lx", ret);
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -03001969 else if (sc->fmt->errpid) {
1970 struct thread *child = machine__find_thread(trace->host, ret, ret);
1971
1972 if (child != NULL) {
1973 fprintf(trace->output, ") = %ld", ret);
1974 if (child->comm_set)
1975 fprintf(trace->output, " (%s)", thread__comm_str(child));
1976 thread__put(child);
1977 }
1978 } else
Arnaldo Carvalho de Meloda3c9a42013-08-26 11:28:34 -03001979 goto signed_print;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001980
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001981 fputc('\n', trace->output);
Milian Wolff566a0882016-04-08 13:34:15 +02001982
Arnaldo Carvalho de Melo202ff962016-04-12 10:11:07 -03001983 trace__fprintf_callchain(trace, evsel, sample);
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001984out:
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001985 ttrace->entry_pending = false;
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001986 err = 0;
1987out_put:
1988 thread__put(thread);
1989 return err;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001990}
1991
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001992static int trace__vfs_getname(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04001993 union perf_event *event __maybe_unused,
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001994 struct perf_sample *sample)
1995{
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001996 struct thread *thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
1997 struct thread_trace *ttrace;
1998 size_t filename_len, entry_str_len, to_move;
1999 ssize_t remaining_space;
2000 char *pos;
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03002001 const char *filename = perf_evsel__rawptr(evsel, sample, "pathname");
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03002002
2003 if (!thread)
2004 goto out;
2005
2006 ttrace = thread__priv(thread);
2007 if (!ttrace)
2008 goto out;
2009
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03002010 filename_len = strlen(filename);
2011
2012 if (ttrace->filename.namelen < filename_len) {
2013 char *f = realloc(ttrace->filename.name, filename_len + 1);
2014
2015 if (f == NULL)
2016 goto out;
2017
2018 ttrace->filename.namelen = filename_len;
2019 ttrace->filename.name = f;
2020 }
2021
2022 strcpy(ttrace->filename.name, filename);
2023 ttrace->filename.pending_open = true;
2024
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03002025 if (!ttrace->filename.ptr)
2026 goto out;
2027
2028 entry_str_len = strlen(ttrace->entry_str);
2029 remaining_space = trace__entry_str_size - entry_str_len - 1; /* \0 */
2030 if (remaining_space <= 0)
2031 goto out;
2032
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03002033 if (filename_len > (size_t)remaining_space) {
2034 filename += filename_len - remaining_space;
2035 filename_len = remaining_space;
2036 }
2037
2038 to_move = entry_str_len - ttrace->filename.entry_str_pos + 1; /* \0 */
2039 pos = ttrace->entry_str + ttrace->filename.entry_str_pos;
2040 memmove(pos + filename_len, pos, to_move);
2041 memcpy(pos, filename, filename_len);
2042
2043 ttrace->filename.ptr = 0;
2044 ttrace->filename.entry_str_pos = 0;
2045out:
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002046 return 0;
2047}
2048
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002049static int trace__sched_stat_runtime(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04002050 union perf_event *event __maybe_unused,
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002051 struct perf_sample *sample)
2052{
2053 u64 runtime = perf_evsel__intval(evsel, sample, "runtime");
2054 double runtime_ms = (double)runtime / NSEC_PER_MSEC;
David Ahern8fb598e2013-09-28 13:13:00 -06002055 struct thread *thread = machine__findnew_thread(trace->host,
Adrian Hunter314add62013-08-27 11:23:03 +03002056 sample->pid,
2057 sample->tid);
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002058 struct thread_trace *ttrace = thread__trace(thread, trace->output);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002059
2060 if (ttrace == NULL)
2061 goto out_dump;
2062
2063 ttrace->runtime_ms += runtime_ms;
2064 trace->runtime_ms += runtime_ms;
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002065 thread__put(thread);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002066 return 0;
2067
2068out_dump:
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002069 fprintf(trace->output, "%s: comm=%s,pid=%u,runtime=%" PRIu64 ",vruntime=%" PRIu64 ")\n",
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002070 evsel->name,
2071 perf_evsel__strval(evsel, sample, "comm"),
2072 (pid_t)perf_evsel__intval(evsel, sample, "pid"),
2073 runtime,
2074 perf_evsel__intval(evsel, sample, "vruntime"));
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002075 thread__put(thread);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002076 return 0;
2077}
2078
Wang Nan1d6c9402016-02-26 09:31:55 +00002079static void bpf_output__printer(enum binary_printer_ops op,
2080 unsigned int val, void *extra)
2081{
2082 FILE *output = extra;
2083 unsigned char ch = (unsigned char)val;
2084
2085 switch (op) {
2086 case BINARY_PRINT_CHAR_DATA:
2087 fprintf(output, "%c", isprint(ch) ? ch : '.');
2088 break;
2089 case BINARY_PRINT_DATA_BEGIN:
2090 case BINARY_PRINT_LINE_BEGIN:
2091 case BINARY_PRINT_ADDR:
2092 case BINARY_PRINT_NUM_DATA:
2093 case BINARY_PRINT_NUM_PAD:
2094 case BINARY_PRINT_SEP:
2095 case BINARY_PRINT_CHAR_PAD:
2096 case BINARY_PRINT_LINE_END:
2097 case BINARY_PRINT_DATA_END:
2098 default:
2099 break;
2100 }
2101}
2102
2103static void bpf_output__fprintf(struct trace *trace,
2104 struct perf_sample *sample)
2105{
2106 print_binary(sample->raw_data, sample->raw_size, 8,
2107 bpf_output__printer, trace->output);
2108}
2109
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002110static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
2111 union perf_event *event __maybe_unused,
2112 struct perf_sample *sample)
2113{
2114 trace__printf_interrupted_entry(trace, sample);
2115 trace__fprintf_tstamp(trace, sample->time, trace->output);
Arnaldo Carvalho de Melo08089212015-02-19 21:51:50 -08002116
2117 if (trace->trace_syscalls)
2118 fprintf(trace->output, "( ): ");
2119
2120 fprintf(trace->output, "%s:", evsel->name);
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002121
Wang Nan1d6c9402016-02-26 09:31:55 +00002122 if (perf_evsel__is_bpf_output(evsel)) {
2123 bpf_output__fprintf(trace, sample);
2124 } else if (evsel->tp_format) {
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002125 event_format__fprintf(evsel->tp_format, sample->cpu,
2126 sample->raw_data, sample->raw_size,
2127 trace->output);
2128 }
2129
2130 fprintf(trace->output, ")\n");
Arnaldo Carvalho de Melo202ff962016-04-12 10:11:07 -03002131
2132 trace__fprintf_callchain(trace, evsel, sample);
2133
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002134 return 0;
2135}
2136
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002137static void print_location(FILE *f, struct perf_sample *sample,
2138 struct addr_location *al,
2139 bool print_dso, bool print_sym)
2140{
2141
2142 if ((verbose || print_dso) && al->map)
2143 fprintf(f, "%s@", al->map->dso->long_name);
2144
2145 if ((verbose || print_sym) && al->sym)
Arnaldo Carvalho de Melo4414a3c2014-07-08 15:39:21 -03002146 fprintf(f, "%s+0x%" PRIx64, al->sym->name,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002147 al->addr - al->sym->start);
2148 else if (al->map)
Arnaldo Carvalho de Melo4414a3c2014-07-08 15:39:21 -03002149 fprintf(f, "0x%" PRIx64, al->addr);
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002150 else
Arnaldo Carvalho de Melo4414a3c2014-07-08 15:39:21 -03002151 fprintf(f, "0x%" PRIx64, sample->addr);
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002152}
2153
2154static int trace__pgfault(struct trace *trace,
2155 struct perf_evsel *evsel,
Arnaldo Carvalho de Melo473398a2016-03-22 18:23:43 -03002156 union perf_event *event __maybe_unused,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002157 struct perf_sample *sample)
2158{
2159 struct thread *thread;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002160 struct addr_location al;
2161 char map_type = 'd';
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04002162 struct thread_trace *ttrace;
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002163 int err = -1;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002164
2165 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04002166 ttrace = thread__trace(thread, trace->output);
2167 if (ttrace == NULL)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002168 goto out_put;
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04002169
2170 if (evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ)
2171 ttrace->pfmaj++;
2172 else
2173 ttrace->pfmin++;
2174
2175 if (trace->summary_only)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002176 goto out;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002177
Arnaldo Carvalho de Melo473398a2016-03-22 18:23:43 -03002178 thread__find_addr_location(thread, sample->cpumode, MAP__FUNCTION,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002179 sample->ip, &al);
2180
2181 trace__fprintf_entry_head(trace, thread, 0, sample->time, trace->output);
2182
2183 fprintf(trace->output, "%sfault [",
2184 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ?
2185 "maj" : "min");
2186
2187 print_location(trace->output, sample, &al, false, true);
2188
2189 fprintf(trace->output, "] => ");
2190
Arnaldo Carvalho de Melo473398a2016-03-22 18:23:43 -03002191 thread__find_addr_location(thread, sample->cpumode, MAP__VARIABLE,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002192 sample->addr, &al);
2193
2194 if (!al.map) {
Arnaldo Carvalho de Melo473398a2016-03-22 18:23:43 -03002195 thread__find_addr_location(thread, sample->cpumode,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002196 MAP__FUNCTION, sample->addr, &al);
2197
2198 if (al.map)
2199 map_type = 'x';
2200 else
2201 map_type = '?';
2202 }
2203
2204 print_location(trace->output, sample, &al, true, false);
2205
2206 fprintf(trace->output, " (%c%c)\n", map_type, al.level);
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002207out:
2208 err = 0;
2209out_put:
2210 thread__put(thread);
2211 return err;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002212}
2213
David Ahernbdc89662013-08-28 22:29:53 -06002214static bool skip_sample(struct trace *trace, struct perf_sample *sample)
2215{
2216 if ((trace->pid_list && intlist__find(trace->pid_list, sample->pid)) ||
2217 (trace->tid_list && intlist__find(trace->tid_list, sample->tid)))
2218 return false;
2219
2220 if (trace->pid_list || trace->tid_list)
2221 return true;
2222
2223 return false;
2224}
2225
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03002226static void trace__set_base_time(struct trace *trace,
Arnaldo Carvalho de Melo8a07a802016-03-31 15:19:39 -03002227 struct perf_evsel *evsel,
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03002228 struct perf_sample *sample)
2229{
Arnaldo Carvalho de Melo8a07a802016-03-31 15:19:39 -03002230 /*
2231 * BPF events were not setting PERF_SAMPLE_TIME, so be more robust
2232 * and don't use sample->time unconditionally, we may end up having
2233 * some other event in the future without PERF_SAMPLE_TIME for good
2234 * reason, i.e. we may not be interested in its timestamps, just in
2235 * it taking place, picking some piece of information when it
2236 * appears in our event stream (vfs_getname comes to mind).
2237 */
2238 if (trace->base_time == 0 && !trace->full_time &&
2239 (evsel->attr.sample_type & PERF_SAMPLE_TIME))
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03002240 trace->base_time = sample->time;
2241}
2242
David Ahern6810fc92013-08-28 22:29:52 -06002243static int trace__process_sample(struct perf_tool *tool,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04002244 union perf_event *event,
David Ahern6810fc92013-08-28 22:29:52 -06002245 struct perf_sample *sample,
2246 struct perf_evsel *evsel,
2247 struct machine *machine __maybe_unused)
2248{
2249 struct trace *trace = container_of(tool, struct trace, tool);
2250 int err = 0;
2251
Arnaldo Carvalho de Melo744a9712013-11-06 10:17:38 -03002252 tracepoint_handler handler = evsel->handler;
David Ahern6810fc92013-08-28 22:29:52 -06002253
David Ahernbdc89662013-08-28 22:29:53 -06002254 if (skip_sample(trace, sample))
2255 return 0;
2256
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03002257 trace__set_base_time(trace, evsel, sample);
David Ahern6810fc92013-08-28 22:29:52 -06002258
David Ahern31605652013-12-04 19:41:41 -07002259 if (handler) {
2260 ++trace->nr_events;
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04002261 handler(trace, evsel, event, sample);
David Ahern31605652013-12-04 19:41:41 -07002262 }
David Ahern6810fc92013-08-28 22:29:52 -06002263
2264 return err;
2265}
2266
David Ahernbdc89662013-08-28 22:29:53 -06002267static int parse_target_str(struct trace *trace)
2268{
2269 if (trace->opts.target.pid) {
2270 trace->pid_list = intlist__new(trace->opts.target.pid);
2271 if (trace->pid_list == NULL) {
2272 pr_err("Error parsing process id string\n");
2273 return -EINVAL;
2274 }
2275 }
2276
2277 if (trace->opts.target.tid) {
2278 trace->tid_list = intlist__new(trace->opts.target.tid);
2279 if (trace->tid_list == NULL) {
2280 pr_err("Error parsing thread id string\n");
2281 return -EINVAL;
2282 }
2283 }
2284
2285 return 0;
2286}
2287
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002288static int trace__record(struct trace *trace, int argc, const char **argv)
David Ahern5e2485b2013-09-28 13:13:01 -06002289{
2290 unsigned int rec_argc, i, j;
2291 const char **rec_argv;
2292 const char * const record_args[] = {
2293 "record",
2294 "-R",
2295 "-m", "1024",
2296 "-c", "1",
David Ahern5e2485b2013-09-28 13:13:01 -06002297 };
2298
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002299 const char * const sc_args[] = { "-e", };
2300 unsigned int sc_args_nr = ARRAY_SIZE(sc_args);
2301 const char * const majpf_args[] = { "-e", "major-faults" };
2302 unsigned int majpf_args_nr = ARRAY_SIZE(majpf_args);
2303 const char * const minpf_args[] = { "-e", "minor-faults" };
2304 unsigned int minpf_args_nr = ARRAY_SIZE(minpf_args);
2305
David Ahern9aca7f12013-12-04 19:41:39 -07002306 /* +1 is for the event string below */
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002307 rec_argc = ARRAY_SIZE(record_args) + sc_args_nr + 1 +
2308 majpf_args_nr + minpf_args_nr + argc;
David Ahern5e2485b2013-09-28 13:13:01 -06002309 rec_argv = calloc(rec_argc + 1, sizeof(char *));
2310
2311 if (rec_argv == NULL)
2312 return -ENOMEM;
2313
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002314 j = 0;
David Ahern5e2485b2013-09-28 13:13:01 -06002315 for (i = 0; i < ARRAY_SIZE(record_args); i++)
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002316 rec_argv[j++] = record_args[i];
2317
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002318 if (trace->trace_syscalls) {
2319 for (i = 0; i < sc_args_nr; i++)
2320 rec_argv[j++] = sc_args[i];
David Ahern5e2485b2013-09-28 13:13:01 -06002321
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002322 /* event string may be different for older kernels - e.g., RHEL6 */
2323 if (is_valid_tracepoint("raw_syscalls:sys_enter"))
2324 rec_argv[j++] = "raw_syscalls:sys_enter,raw_syscalls:sys_exit";
2325 else if (is_valid_tracepoint("syscalls:sys_enter"))
2326 rec_argv[j++] = "syscalls:sys_enter,syscalls:sys_exit";
2327 else {
2328 pr_err("Neither raw_syscalls nor syscalls events exist.\n");
2329 return -1;
2330 }
David Ahern9aca7f12013-12-04 19:41:39 -07002331 }
David Ahern9aca7f12013-12-04 19:41:39 -07002332
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002333 if (trace->trace_pgfaults & TRACE_PFMAJ)
2334 for (i = 0; i < majpf_args_nr; i++)
2335 rec_argv[j++] = majpf_args[i];
David Ahern5e2485b2013-09-28 13:13:01 -06002336
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002337 if (trace->trace_pgfaults & TRACE_PFMIN)
2338 for (i = 0; i < minpf_args_nr; i++)
2339 rec_argv[j++] = minpf_args[i];
2340
2341 for (i = 0; i < (unsigned int)argc; i++)
2342 rec_argv[j++] = argv[i];
2343
2344 return cmd_record(j, rec_argv, NULL);
David Ahern5e2485b2013-09-28 13:13:01 -06002345}
2346
David Ahernbf2575c2013-10-08 21:26:53 -06002347static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp);
2348
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002349static bool perf_evlist__add_vfs_getname(struct perf_evlist *evlist)
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002350{
Arnaldo Carvalho de Meloef503832013-11-07 16:41:19 -03002351 struct perf_evsel *evsel = perf_evsel__newtp("probe", "vfs_getname");
Jiri Olsa8dd2a132015-09-07 10:38:06 +02002352
2353 if (IS_ERR(evsel))
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002354 return false;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002355
2356 if (perf_evsel__field(evsel, "pathname") == NULL) {
2357 perf_evsel__delete(evsel);
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002358 return false;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002359 }
2360
Arnaldo Carvalho de Melo744a9712013-11-06 10:17:38 -03002361 evsel->handler = trace__vfs_getname;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002362 perf_evlist__add(evlist, evsel);
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002363 return true;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002364}
2365
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002366static int perf_evlist__add_pgfault(struct perf_evlist *evlist,
2367 u64 config)
2368{
2369 struct perf_evsel *evsel;
2370 struct perf_event_attr attr = {
2371 .type = PERF_TYPE_SOFTWARE,
2372 .mmap_data = 1,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002373 };
2374
2375 attr.config = config;
Arnaldo Carvalho de Melo05247982014-07-23 18:15:09 -03002376 attr.sample_period = 1;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002377
2378 event_attr_init(&attr);
2379
2380 evsel = perf_evsel__new(&attr);
2381 if (!evsel)
2382 return -ENOMEM;
2383
2384 evsel->handler = trace__pgfault;
2385 perf_evlist__add(evlist, evsel);
2386
2387 return 0;
2388}
2389
Arnaldo Carvalho de Meloddbb1b12015-02-21 12:10:29 -08002390static void trace__handle_event(struct trace *trace, union perf_event *event, struct perf_sample *sample)
2391{
2392 const u32 type = event->header.type;
2393 struct perf_evsel *evsel;
2394
Arnaldo Carvalho de Meloddbb1b12015-02-21 12:10:29 -08002395 if (type != PERF_RECORD_SAMPLE) {
2396 trace__process_event(trace, trace->host, event, sample);
2397 return;
2398 }
2399
2400 evsel = perf_evlist__id2evsel(trace->evlist, sample->id);
2401 if (evsel == NULL) {
2402 fprintf(trace->output, "Unknown tp ID %" PRIu64 ", skipping...\n", sample->id);
2403 return;
2404 }
2405
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03002406 trace__set_base_time(trace, evsel, sample);
2407
Arnaldo Carvalho de Meloddbb1b12015-02-21 12:10:29 -08002408 if (evsel->attr.type == PERF_TYPE_TRACEPOINT &&
2409 sample->raw_data == NULL) {
2410 fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n",
2411 perf_evsel__name(evsel), sample->tid,
2412 sample->cpu, sample->raw_size);
2413 } else {
2414 tracepoint_handler handler = evsel->handler;
2415 handler(trace, evsel, event, sample);
2416 }
2417}
2418
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03002419static int trace__add_syscall_newtp(struct trace *trace)
2420{
2421 int ret = -1;
2422 struct perf_evlist *evlist = trace->evlist;
2423 struct perf_evsel *sys_enter, *sys_exit;
2424
2425 sys_enter = perf_evsel__syscall_newtp("sys_enter", trace__sys_enter);
2426 if (sys_enter == NULL)
2427 goto out;
2428
2429 if (perf_evsel__init_sc_tp_ptr_field(sys_enter, args))
2430 goto out_delete_sys_enter;
2431
2432 sys_exit = perf_evsel__syscall_newtp("sys_exit", trace__sys_exit);
2433 if (sys_exit == NULL)
2434 goto out_delete_sys_enter;
2435
2436 if (perf_evsel__init_sc_tp_uint_field(sys_exit, ret))
2437 goto out_delete_sys_exit;
2438
2439 perf_evlist__add(evlist, sys_enter);
2440 perf_evlist__add(evlist, sys_exit);
2441
Arnaldo Carvalho de Melo44621812016-04-11 15:49:11 -03002442 if (trace->opts.callgraph_set && !trace->kernel_syscallchains) {
2443 /*
2444 * We're interested only in the user space callchain
2445 * leading to the syscall, allow overriding that for
2446 * debugging reasons using --kernel_syscall_callchains
2447 */
2448 sys_exit->attr.exclude_callchain_kernel = 1;
2449 }
2450
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03002451 trace->syscalls.events.sys_enter = sys_enter;
2452 trace->syscalls.events.sys_exit = sys_exit;
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03002453
2454 ret = 0;
2455out:
2456 return ret;
2457
2458out_delete_sys_exit:
2459 perf_evsel__delete_priv(sys_exit);
2460out_delete_sys_enter:
2461 perf_evsel__delete_priv(sys_enter);
2462 goto out;
2463}
2464
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002465static int trace__set_ev_qualifier_filter(struct trace *trace)
2466{
2467 int err = -1;
2468 char *filter = asprintf_expr_inout_ints("id", !trace->not_ev_qualifier,
2469 trace->ev_qualifier_ids.nr,
2470 trace->ev_qualifier_ids.entries);
2471
2472 if (filter == NULL)
2473 goto out_enomem;
2474
2475 if (!perf_evsel__append_filter(trace->syscalls.events.sys_enter, "&&", filter))
2476 err = perf_evsel__append_filter(trace->syscalls.events.sys_exit, "&&", filter);
2477
2478 free(filter);
2479out:
2480 return err;
2481out_enomem:
2482 errno = ENOMEM;
2483 goto out;
2484}
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03002485
Namhyung Kimf15eb532012-10-05 14:02:16 +09002486static int trace__run(struct trace *trace, int argc, const char **argv)
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002487{
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002488 struct perf_evlist *evlist = trace->evlist;
Arnaldo Carvalho de Melo94ad89b2015-07-03 17:42:03 -03002489 struct perf_evsel *evsel;
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03002490 int err = -1, i;
2491 unsigned long before;
Namhyung Kimf15eb532012-10-05 14:02:16 +09002492 const bool forks = argc > 0;
Arnaldo Carvalho de Melo46fb3c22014-09-22 14:39:48 -03002493 bool draining = false;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002494
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03002495 trace->live = true;
2496
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03002497 if (trace->trace_syscalls && trace__add_syscall_newtp(trace))
Arnaldo Carvalho de Melo801c67b2015-01-22 10:52:55 -03002498 goto out_error_raw_syscalls;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002499
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002500 if (trace->trace_syscalls)
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002501 trace->vfs_getname = perf_evlist__add_vfs_getname(evlist);
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002502
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002503 if ((trace->trace_pgfaults & TRACE_PFMAJ) &&
Arnaldo Carvalho de Meloe2726d92015-01-22 10:34:22 -03002504 perf_evlist__add_pgfault(evlist, PERF_COUNT_SW_PAGE_FAULTS_MAJ)) {
Arnaldo Carvalho de Melo5ed08da2015-01-22 11:08:04 -03002505 goto out_error_mem;
Arnaldo Carvalho de Meloe2726d92015-01-22 10:34:22 -03002506 }
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002507
2508 if ((trace->trace_pgfaults & TRACE_PFMIN) &&
2509 perf_evlist__add_pgfault(evlist, PERF_COUNT_SW_PAGE_FAULTS_MIN))
Arnaldo Carvalho de Melo5ed08da2015-01-22 11:08:04 -03002510 goto out_error_mem;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002511
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002512 if (trace->sched &&
Arnaldo Carvalho de Melo2cc990b2015-01-22 11:13:43 -03002513 perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime",
2514 trace__sched_stat_runtime))
2515 goto out_error_sched_stat_runtime;
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002516
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002517 err = perf_evlist__create_maps(evlist, &trace->opts.target);
2518 if (err < 0) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002519 fprintf(trace->output, "Problems parsing the target to trace, check your options!\n");
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002520 goto out_delete_evlist;
2521 }
2522
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03002523 err = trace__symbols_init(trace, evlist);
2524 if (err < 0) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002525 fprintf(trace->output, "Problems initializing symbol libraries!\n");
Arnaldo Carvalho de Melo03ad9742014-01-03 15:56:06 -03002526 goto out_delete_evlist;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03002527 }
2528
Arnaldo Carvalho de Melofde54b72016-04-11 18:42:37 -03002529 perf_evlist__config(evlist, &trace->opts, NULL);
2530
2531 if (trace->opts.callgraph_set && trace->syscalls.events.sys_exit) {
2532 perf_evsel__config_callchain(trace->syscalls.events.sys_exit,
2533 &trace->opts, &callchain_param);
2534 /*
2535 * Now we have evsels with different sample_ids, use
2536 * PERF_SAMPLE_IDENTIFIER to map from sample to evsel
2537 * from a fixed position in each ring buffer record.
2538 *
2539 * As of this the changeset introducing this comment, this
2540 * isn't strictly needed, as the fields that can come before
2541 * PERF_SAMPLE_ID are all used, but we'll probably disable
2542 * some of those for things like copying the payload of
2543 * pointer syscall arguments, and for vfs_getname we don't
2544 * need PERF_SAMPLE_ADDR and PERF_SAMPLE_IP, so do this
2545 * here as a warning we need to use PERF_SAMPLE_IDENTIFIER.
2546 */
2547 perf_evlist__set_sample_bit(evlist, IDENTIFIER);
2548 perf_evlist__reset_sample_bit(evlist, ID);
2549 }
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002550
Namhyung Kimf15eb532012-10-05 14:02:16 +09002551 signal(SIGCHLD, sig_handler);
2552 signal(SIGINT, sig_handler);
2553
2554 if (forks) {
Namhyung Kim6ef73ec2013-03-11 16:43:15 +09002555 err = perf_evlist__prepare_workload(evlist, &trace->opts.target,
Arnaldo Carvalho de Melo735f7e02014-01-03 14:56:49 -03002556 argv, false, NULL);
Namhyung Kimf15eb532012-10-05 14:02:16 +09002557 if (err < 0) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002558 fprintf(trace->output, "Couldn't run the workload!\n");
Arnaldo Carvalho de Melo03ad9742014-01-03 15:56:06 -03002559 goto out_delete_evlist;
Namhyung Kimf15eb532012-10-05 14:02:16 +09002560 }
2561 }
2562
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002563 err = perf_evlist__open(evlist);
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002564 if (err < 0)
2565 goto out_error_open;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002566
Wang Nanba504232016-02-26 09:31:54 +00002567 err = bpf__apply_obj_config();
2568 if (err) {
2569 char errbuf[BUFSIZ];
2570
2571 bpf__strerror_apply_obj_config(err, errbuf, sizeof(errbuf));
2572 pr_err("ERROR: Apply config to BPF failed: %s\n",
2573 errbuf);
2574 goto out_error_open;
2575 }
2576
Arnaldo Carvalho de Melo241b0572015-02-21 10:15:21 -08002577 /*
2578 * Better not use !target__has_task() here because we need to cover the
2579 * case where no threads were specified in the command line, but a
2580 * workload was, and in that case we will fill in the thread_map when
2581 * we fork the workload in perf_evlist__prepare_workload.
2582 */
Arnaldo Carvalho de Melof078c382015-02-21 11:36:52 -08002583 if (trace->filter_pids.nr > 0)
2584 err = perf_evlist__set_filter_pids(evlist, trace->filter_pids.nr, trace->filter_pids.entries);
Jiri Olsae13798c2015-06-23 00:36:02 +02002585 else if (thread_map__pid(evlist->threads, 0) == -1)
Arnaldo Carvalho de Melof078c382015-02-21 11:36:52 -08002586 err = perf_evlist__set_filter_pid(evlist, getpid());
2587
Arnaldo Carvalho de Melo94ad89b2015-07-03 17:42:03 -03002588 if (err < 0)
2589 goto out_error_mem;
2590
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002591 if (trace->ev_qualifier_ids.nr > 0) {
2592 err = trace__set_ev_qualifier_filter(trace);
2593 if (err < 0)
2594 goto out_errno;
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002595
Arnaldo Carvalho de Melo2e5e5f82015-08-03 17:12:29 -03002596 pr_debug("event qualifier tracepoint filter: %s\n",
2597 trace->syscalls.events.sys_exit->filter);
2598 }
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002599
Arnaldo Carvalho de Melo94ad89b2015-07-03 17:42:03 -03002600 err = perf_evlist__apply_filters(evlist, &evsel);
2601 if (err < 0)
2602 goto out_error_apply_filters;
Arnaldo Carvalho de Melo241b0572015-02-21 10:15:21 -08002603
Jiri Olsaf8850372013-11-28 17:57:22 +01002604 err = perf_evlist__mmap(evlist, trace->opts.mmap_pages, false);
Arnaldo Carvalho de Meloe09b18d2014-12-11 18:04:10 -03002605 if (err < 0)
2606 goto out_error_mmap;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002607
Arnaldo Carvalho de Melocb24d012015-04-22 10:04:23 -03002608 if (!target__none(&trace->opts.target))
2609 perf_evlist__enable(evlist);
2610
Namhyung Kimf15eb532012-10-05 14:02:16 +09002611 if (forks)
2612 perf_evlist__start_workload(evlist);
2613
Jiri Olsae13798c2015-06-23 00:36:02 +02002614 trace->multiple_threads = thread_map__pid(evlist->threads, 0) == -1 ||
Arnaldo Carvalho de Melo42052be2015-02-13 12:32:45 -03002615 evlist->threads->nr > 1 ||
2616 perf_evlist__first(evlist)->attr.inherit;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002617again:
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03002618 before = trace->nr_events;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002619
2620 for (i = 0; i < evlist->nr_mmaps; i++) {
2621 union perf_event *event;
2622
2623 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002624 struct perf_sample sample;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002625
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03002626 ++trace->nr_events;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002627
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002628 err = perf_evlist__parse_sample(evlist, event, &sample);
2629 if (err) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002630 fprintf(trace->output, "Can't parse sample, err = %d, skipping...\n", err);
Zhouyi Zhou8e50d382013-10-24 15:43:33 +08002631 goto next_event;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002632 }
2633
Arnaldo Carvalho de Meloddbb1b12015-02-21 12:10:29 -08002634 trace__handle_event(trace, event, &sample);
Zhouyi Zhou8e50d382013-10-24 15:43:33 +08002635next_event:
2636 perf_evlist__mmap_consume(evlist, i);
Arnaldo Carvalho de Melo20c5f102013-09-03 11:55:07 -03002637
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002638 if (interrupted)
2639 goto out_disable;
Arnaldo Carvalho de Melo02ac5422015-04-22 11:11:57 -03002640
2641 if (done && !draining) {
2642 perf_evlist__disable(evlist);
2643 draining = true;
2644 }
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002645 }
2646 }
2647
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03002648 if (trace->nr_events == before) {
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002649 int timeout = done ? 100 : -1;
Namhyung Kimf15eb532012-10-05 14:02:16 +09002650
Arnaldo Carvalho de Melo46fb3c22014-09-22 14:39:48 -03002651 if (!draining && perf_evlist__poll(evlist, timeout) > 0) {
2652 if (perf_evlist__filter_pollfd(evlist, POLLERR | POLLHUP) == 0)
2653 draining = true;
2654
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002655 goto again;
Arnaldo Carvalho de Melo46fb3c22014-09-22 14:39:48 -03002656 }
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002657 } else {
2658 goto again;
Namhyung Kimf15eb532012-10-05 14:02:16 +09002659 }
2660
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002661out_disable:
Arnaldo Carvalho de Melof3b623b2015-03-02 22:21:35 -03002662 thread__zput(trace->current);
2663
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002664 perf_evlist__disable(evlist);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002665
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002666 if (!err) {
2667 if (trace->summary)
2668 trace__fprintf_thread_summary(trace, trace->output);
2669
2670 if (trace->show_tool_stats) {
2671 fprintf(trace->output, "Stats:\n "
2672 " vfs_getname : %" PRIu64 "\n"
2673 " proc_getname: %" PRIu64 "\n",
2674 trace->stats.vfs_getname,
2675 trace->stats.proc_getname);
2676 }
2677 }
David Ahernbf2575c2013-10-08 21:26:53 -06002678
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002679out_delete_evlist:
2680 perf_evlist__delete(evlist);
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002681 trace->evlist = NULL;
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03002682 trace->live = false;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002683 return err;
Arnaldo Carvalho de Melo6ef068c2013-10-17 12:07:58 -03002684{
2685 char errbuf[BUFSIZ];
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002686
Arnaldo Carvalho de Melo2cc990b2015-01-22 11:13:43 -03002687out_error_sched_stat_runtime:
Jiri Olsa988bdb32015-09-02 09:56:35 +02002688 tracing_path__strerror_open_tp(errno, errbuf, sizeof(errbuf), "sched", "sched_stat_runtime");
Arnaldo Carvalho de Melo2cc990b2015-01-22 11:13:43 -03002689 goto out_error;
2690
Arnaldo Carvalho de Melo801c67b2015-01-22 10:52:55 -03002691out_error_raw_syscalls:
Jiri Olsa988bdb32015-09-02 09:56:35 +02002692 tracing_path__strerror_open_tp(errno, errbuf, sizeof(errbuf), "raw_syscalls", "sys_(enter|exit)");
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002693 goto out_error;
2694
Arnaldo Carvalho de Meloe09b18d2014-12-11 18:04:10 -03002695out_error_mmap:
2696 perf_evlist__strerror_mmap(evlist, errno, errbuf, sizeof(errbuf));
2697 goto out_error;
2698
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002699out_error_open:
2700 perf_evlist__strerror_open(evlist, errno, errbuf, sizeof(errbuf));
2701
2702out_error:
Arnaldo Carvalho de Melo6ef068c2013-10-17 12:07:58 -03002703 fprintf(trace->output, "%s\n", errbuf);
Ramkumar Ramachandra87f91862013-10-04 10:47:31 +05302704 goto out_delete_evlist;
Arnaldo Carvalho de Melo94ad89b2015-07-03 17:42:03 -03002705
2706out_error_apply_filters:
2707 fprintf(trace->output,
2708 "Failed to set filter \"%s\" on event %s with %d (%s)\n",
2709 evsel->filter, perf_evsel__name(evsel), errno,
2710 strerror_r(errno, errbuf, sizeof(errbuf)));
2711 goto out_delete_evlist;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002712}
Arnaldo Carvalho de Melo5ed08da2015-01-22 11:08:04 -03002713out_error_mem:
2714 fprintf(trace->output, "Not enough memory to run!\n");
2715 goto out_delete_evlist;
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002716
2717out_errno:
2718 fprintf(trace->output, "errno=%d,%s\n", errno, strerror(errno));
2719 goto out_delete_evlist;
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002720}
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002721
David Ahern6810fc92013-08-28 22:29:52 -06002722static int trace__replay(struct trace *trace)
2723{
2724 const struct perf_evsel_str_handler handlers[] = {
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002725 { "probe:vfs_getname", trace__vfs_getname, },
David Ahern6810fc92013-08-28 22:29:52 -06002726 };
Jiri Olsaf5fc14122013-10-15 16:27:32 +02002727 struct perf_data_file file = {
2728 .path = input_name,
2729 .mode = PERF_DATA_MODE_READ,
Yunlong Songe366a6d2015-04-02 21:47:18 +08002730 .force = trace->force,
Jiri Olsaf5fc14122013-10-15 16:27:32 +02002731 };
David Ahern6810fc92013-08-28 22:29:52 -06002732 struct perf_session *session;
Namhyung Kim003824e2013-11-12 15:25:00 +09002733 struct perf_evsel *evsel;
David Ahern6810fc92013-08-28 22:29:52 -06002734 int err = -1;
2735
2736 trace->tool.sample = trace__process_sample;
2737 trace->tool.mmap = perf_event__process_mmap;
David Ahern384c6712013-09-22 19:44:58 -06002738 trace->tool.mmap2 = perf_event__process_mmap2;
David Ahern6810fc92013-08-28 22:29:52 -06002739 trace->tool.comm = perf_event__process_comm;
2740 trace->tool.exit = perf_event__process_exit;
2741 trace->tool.fork = perf_event__process_fork;
2742 trace->tool.attr = perf_event__process_attr;
2743 trace->tool.tracing_data = perf_event__process_tracing_data;
2744 trace->tool.build_id = perf_event__process_build_id;
2745
Jiri Olsa0a8cb852014-07-06 14:18:21 +02002746 trace->tool.ordered_events = true;
David Ahern6810fc92013-08-28 22:29:52 -06002747 trace->tool.ordering_requires_timestamps = true;
2748
2749 /* add tid to output */
2750 trace->multiple_threads = true;
2751
Jiri Olsaf5fc14122013-10-15 16:27:32 +02002752 session = perf_session__new(&file, false, &trace->tool);
David Ahern6810fc92013-08-28 22:29:52 -06002753 if (session == NULL)
Taeung Song52e028342014-09-24 10:33:37 +09002754 return -1;
David Ahern6810fc92013-08-28 22:29:52 -06002755
Namhyung Kim0a7e6d12014-08-12 15:40:45 +09002756 if (symbol__init(&session->header.env) < 0)
Namhyung Kimcb2ffae2014-08-12 15:40:44 +09002757 goto out;
2758
David Ahern8fb598e2013-09-28 13:13:00 -06002759 trace->host = &session->machines.host;
2760
David Ahern6810fc92013-08-28 22:29:52 -06002761 err = perf_session__set_tracepoints_handlers(session, handlers);
2762 if (err)
2763 goto out;
2764
Namhyung Kim003824e2013-11-12 15:25:00 +09002765 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2766 "raw_syscalls:sys_enter");
David Ahern9aca7f12013-12-04 19:41:39 -07002767 /* older kernels have syscalls tp versus raw_syscalls */
2768 if (evsel == NULL)
2769 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2770 "syscalls:sys_enter");
David Ahern6810fc92013-08-28 22:29:52 -06002771
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002772 if (evsel &&
2773 (perf_evsel__init_syscall_tp(evsel, trace__sys_enter) < 0 ||
2774 perf_evsel__init_sc_tp_ptr_field(evsel, args))) {
Namhyung Kim003824e2013-11-12 15:25:00 +09002775 pr_err("Error during initialize raw_syscalls:sys_enter event\n");
2776 goto out;
2777 }
2778
2779 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2780 "raw_syscalls:sys_exit");
David Ahern9aca7f12013-12-04 19:41:39 -07002781 if (evsel == NULL)
2782 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2783 "syscalls:sys_exit");
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002784 if (evsel &&
2785 (perf_evsel__init_syscall_tp(evsel, trace__sys_exit) < 0 ||
2786 perf_evsel__init_sc_tp_uint_field(evsel, ret))) {
Namhyung Kim003824e2013-11-12 15:25:00 +09002787 pr_err("Error during initialize raw_syscalls:sys_exit event\n");
David Ahern6810fc92013-08-28 22:29:52 -06002788 goto out;
2789 }
2790
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002791 evlist__for_each(session->evlist, evsel) {
2792 if (evsel->attr.type == PERF_TYPE_SOFTWARE &&
2793 (evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ||
2794 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MIN ||
2795 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS))
2796 evsel->handler = trace__pgfault;
2797 }
2798
David Ahernbdc89662013-08-28 22:29:53 -06002799 err = parse_target_str(trace);
2800 if (err != 0)
2801 goto out;
2802
David Ahern6810fc92013-08-28 22:29:52 -06002803 setup_pager();
2804
Arnaldo Carvalho de Melob7b61cb2015-03-03 11:58:45 -03002805 err = perf_session__process_events(session);
David Ahern6810fc92013-08-28 22:29:52 -06002806 if (err)
2807 pr_err("Failed to process events, error %d", err);
2808
David Ahernbf2575c2013-10-08 21:26:53 -06002809 else if (trace->summary)
2810 trace__fprintf_thread_summary(trace, trace->output);
2811
David Ahern6810fc92013-08-28 22:29:52 -06002812out:
2813 perf_session__delete(session);
2814
2815 return err;
2816}
2817
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002818static size_t trace__fprintf_threads_header(FILE *fp)
2819{
2820 size_t printed;
2821
Pekka Enberg99ff7152013-11-12 16:42:14 +02002822 printed = fprintf(fp, "\n Summary of events:\n\n");
David Ahernbf2575c2013-10-08 21:26:53 -06002823
2824 return printed;
2825}
2826
2827static size_t thread__dump_stats(struct thread_trace *ttrace,
2828 struct trace *trace, FILE *fp)
2829{
2830 struct stats *stats;
2831 size_t printed = 0;
2832 struct syscall *sc;
2833 struct int_node *inode = intlist__first(ttrace->syscall_stats);
2834
2835 if (inode == NULL)
2836 return 0;
2837
2838 printed += fprintf(fp, "\n");
2839
Milian Wolff834fd462015-08-06 11:24:29 +02002840 printed += fprintf(fp, " syscall calls total min avg max stddev\n");
2841 printed += fprintf(fp, " (msec) (msec) (msec) (msec) (%%)\n");
2842 printed += fprintf(fp, " --------------- -------- --------- --------- --------- --------- ------\n");
Pekka Enberg99ff7152013-11-12 16:42:14 +02002843
David Ahernbf2575c2013-10-08 21:26:53 -06002844 /* each int_node is a syscall */
2845 while (inode) {
2846 stats = inode->priv;
2847 if (stats) {
2848 double min = (double)(stats->min) / NSEC_PER_MSEC;
2849 double max = (double)(stats->max) / NSEC_PER_MSEC;
2850 double avg = avg_stats(stats);
2851 double pct;
2852 u64 n = (u64) stats->n;
2853
2854 pct = avg ? 100.0 * stddev_stats(stats)/avg : 0.0;
2855 avg /= NSEC_PER_MSEC;
2856
2857 sc = &trace->syscalls.table[inode->i];
Pekka Enberg99ff7152013-11-12 16:42:14 +02002858 printed += fprintf(fp, " %-15s", sc->name);
Milian Wolff834fd462015-08-06 11:24:29 +02002859 printed += fprintf(fp, " %8" PRIu64 " %9.3f %9.3f %9.3f",
2860 n, avg * n, min, avg);
Pekka Enberg27a778b2013-11-13 14:21:48 +02002861 printed += fprintf(fp, " %9.3f %9.2f%%\n", max, pct);
David Ahernbf2575c2013-10-08 21:26:53 -06002862 }
2863
2864 inode = intlist__next(inode);
2865 }
2866
2867 printed += fprintf(fp, "\n\n");
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002868
2869 return printed;
2870}
2871
David Ahern896cbb52013-09-28 13:12:59 -06002872/* struct used to pass data to per-thread function */
2873struct summary_data {
2874 FILE *fp;
2875 struct trace *trace;
2876 size_t printed;
2877};
2878
2879static int trace__fprintf_one_thread(struct thread *thread, void *priv)
2880{
2881 struct summary_data *data = priv;
2882 FILE *fp = data->fp;
2883 size_t printed = data->printed;
2884 struct trace *trace = data->trace;
Namhyung Kim89dceb22014-10-06 09:46:03 +09002885 struct thread_trace *ttrace = thread__priv(thread);
David Ahern896cbb52013-09-28 13:12:59 -06002886 double ratio;
2887
2888 if (ttrace == NULL)
2889 return 0;
2890
2891 ratio = (double)ttrace->nr_events / trace->nr_events * 100.0;
2892
Pekka Enberg15e65c62013-11-14 18:43:30 +02002893 printed += fprintf(fp, " %s (%d), ", thread__comm_str(thread), thread->tid);
Pekka Enberg99ff7152013-11-12 16:42:14 +02002894 printed += fprintf(fp, "%lu events, ", ttrace->nr_events);
Pekka Enberg15e65c62013-11-14 18:43:30 +02002895 printed += fprintf(fp, "%.1f%%", ratio);
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04002896 if (ttrace->pfmaj)
2897 printed += fprintf(fp, ", %lu majfaults", ttrace->pfmaj);
2898 if (ttrace->pfmin)
2899 printed += fprintf(fp, ", %lu minfaults", ttrace->pfmin);
Pekka Enberg99ff7152013-11-12 16:42:14 +02002900 printed += fprintf(fp, ", %.3f msec\n", ttrace->runtime_ms);
David Ahernbf2575c2013-10-08 21:26:53 -06002901 printed += thread__dump_stats(ttrace, trace, fp);
David Ahern896cbb52013-09-28 13:12:59 -06002902
2903 data->printed += printed;
2904
2905 return 0;
2906}
2907
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002908static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp)
2909{
David Ahern896cbb52013-09-28 13:12:59 -06002910 struct summary_data data = {
2911 .fp = fp,
2912 .trace = trace
2913 };
2914 data.printed = trace__fprintf_threads_header(fp);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002915
David Ahern896cbb52013-09-28 13:12:59 -06002916 machine__for_each_thread(trace->host, trace__fprintf_one_thread, &data);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002917
David Ahern896cbb52013-09-28 13:12:59 -06002918 return data.printed;
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002919}
2920
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03002921static int trace__set_duration(const struct option *opt, const char *str,
2922 int unset __maybe_unused)
2923{
2924 struct trace *trace = opt->value;
2925
2926 trace->duration_filter = atof(str);
2927 return 0;
2928}
2929
Arnaldo Carvalho de Melof078c382015-02-21 11:36:52 -08002930static int trace__set_filter_pids(const struct option *opt, const char *str,
2931 int unset __maybe_unused)
2932{
2933 int ret = -1;
2934 size_t i;
2935 struct trace *trace = opt->value;
2936 /*
2937 * FIXME: introduce a intarray class, plain parse csv and create a
2938 * { int nr, int entries[] } struct...
2939 */
2940 struct intlist *list = intlist__new(str);
2941
2942 if (list == NULL)
2943 return -1;
2944
2945 i = trace->filter_pids.nr = intlist__nr_entries(list) + 1;
2946 trace->filter_pids.entries = calloc(i, sizeof(pid_t));
2947
2948 if (trace->filter_pids.entries == NULL)
2949 goto out;
2950
2951 trace->filter_pids.entries[0] = getpid();
2952
2953 for (i = 1; i < trace->filter_pids.nr; ++i)
2954 trace->filter_pids.entries[i] = intlist__entry(list, i - 1)->i;
2955
2956 intlist__delete(list);
2957 ret = 0;
2958out:
2959 return ret;
2960}
2961
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002962static int trace__open_output(struct trace *trace, const char *filename)
2963{
2964 struct stat st;
2965
2966 if (!stat(filename, &st) && st.st_size) {
2967 char oldname[PATH_MAX];
2968
2969 scnprintf(oldname, sizeof(oldname), "%s.old", filename);
2970 unlink(oldname);
2971 rename(filename, oldname);
2972 }
2973
2974 trace->output = fopen(filename, "w");
2975
2976 return trace->output == NULL ? -errno : 0;
2977}
2978
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002979static int parse_pagefaults(const struct option *opt, const char *str,
2980 int unset __maybe_unused)
2981{
2982 int *trace_pgfaults = opt->value;
2983
2984 if (strcmp(str, "all") == 0)
2985 *trace_pgfaults |= TRACE_PFMAJ | TRACE_PFMIN;
2986 else if (strcmp(str, "maj") == 0)
2987 *trace_pgfaults |= TRACE_PFMAJ;
2988 else if (strcmp(str, "min") == 0)
2989 *trace_pgfaults |= TRACE_PFMIN;
2990 else
2991 return -1;
2992
2993 return 0;
2994}
2995
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002996static void evlist__set_evsel_handler(struct perf_evlist *evlist, void *handler)
2997{
2998 struct perf_evsel *evsel;
2999
3000 evlist__for_each(evlist, evsel)
3001 evsel->handler = handler;
3002}
3003
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003004int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
3005{
Yunlong Song6fdd9cb2015-03-18 21:35:57 +08003006 const char *trace_usage[] = {
Namhyung Kimf15eb532012-10-05 14:02:16 +09003007 "perf trace [<options>] [<command>]",
3008 "perf trace [<options>] -- <command> [<options>]",
David Ahern5e2485b2013-09-28 13:13:01 -06003009 "perf trace record [<options>] [<command>]",
3010 "perf trace record [<options>] -- <command> [<options>]",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003011 NULL
3012 };
3013 struct trace trace = {
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003014 .syscalls = {
3015 . max = -1,
3016 },
3017 .opts = {
3018 .target = {
3019 .uid = UINT_MAX,
3020 .uses_mmap = true,
3021 },
3022 .user_freq = UINT_MAX,
3023 .user_interval = ULLONG_MAX,
Arnaldo Carvalho de Melo509051e2014-01-14 17:52:14 -03003024 .no_buffering = true,
Arnaldo Carvalho de Melo38d54472014-12-12 17:28:32 -03003025 .mmap_pages = UINT_MAX,
Kan Liang9d9cad72015-06-17 09:51:11 -04003026 .proc_map_timeout = 500,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003027 },
Milian Wolff007d66a2015-08-05 16:52:23 -03003028 .output = stderr,
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -03003029 .show_comm = true,
Stanislav Fomicheve281a962014-06-26 20:14:28 +04003030 .trace_syscalls = true,
Arnaldo Carvalho de Melo44621812016-04-11 15:49:11 -03003031 .kernel_syscallchains = false,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003032 };
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003033 const char *output_name = NULL;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03003034 const char *ev_qualifier_str = NULL;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003035 const struct option trace_options[] = {
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003036 OPT_CALLBACK(0, "event", &trace.evlist, "event",
3037 "event selector. use 'perf list' to list available events",
3038 parse_events_option),
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -03003039 OPT_BOOLEAN(0, "comm", &trace.show_comm,
3040 "show the thread COMM next to its id"),
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03003041 OPT_BOOLEAN(0, "tool_stats", &trace.show_tool_stats, "show tool stats"),
Arnaldo Carvalho de Melod303e852015-04-23 12:02:07 -03003042 OPT_STRING('e', "expr", &ev_qualifier_str, "expr", "list of syscalls to trace"),
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003043 OPT_STRING('o', "output", &output_name, "file", "output file name"),
David Ahern6810fc92013-08-28 22:29:52 -06003044 OPT_STRING('i', "input", &input_name, "file", "Analyze events in file"),
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003045 OPT_STRING('p', "pid", &trace.opts.target.pid, "pid",
3046 "trace events on existing process id"),
David Ahernac9be8e2013-08-20 11:15:45 -06003047 OPT_STRING('t', "tid", &trace.opts.target.tid, "tid",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003048 "trace events on existing thread id"),
Arnaldo Carvalho de Melofa0e4ff2015-04-23 11:59:20 -03003049 OPT_CALLBACK(0, "filter-pids", &trace, "CSV list of pids",
3050 "pids to filter (by the kernel)", trace__set_filter_pids),
David Ahernac9be8e2013-08-20 11:15:45 -06003051 OPT_BOOLEAN('a', "all-cpus", &trace.opts.target.system_wide,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003052 "system-wide collection from all CPUs"),
David Ahernac9be8e2013-08-20 11:15:45 -06003053 OPT_STRING('C', "cpu", &trace.opts.target.cpu_list, "cpu",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003054 "list of cpus to monitor"),
David Ahern6810fc92013-08-28 22:29:52 -06003055 OPT_BOOLEAN(0, "no-inherit", &trace.opts.no_inherit,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003056 "child tasks do not inherit counters"),
Jiri Olsa994a1f72013-09-01 12:36:12 +02003057 OPT_CALLBACK('m', "mmap-pages", &trace.opts.mmap_pages, "pages",
3058 "number of mmap data pages",
3059 perf_evlist__parse_mmap_pages),
David Ahernac9be8e2013-08-20 11:15:45 -06003060 OPT_STRING('u', "uid", &trace.opts.target.uid_str, "user",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003061 "user to profile"),
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03003062 OPT_CALLBACK(0, "duration", &trace, "float",
3063 "show only events with duration > N.M ms",
3064 trace__set_duration),
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03003065 OPT_BOOLEAN(0, "sched", &trace.sched, "show blocking scheduler events"),
Arnaldo Carvalho de Melo7c304ee02013-08-22 16:49:54 -03003066 OPT_INCR('v', "verbose", &verbose, "be more verbose"),
David Ahern4bb09192013-09-04 12:37:43 -06003067 OPT_BOOLEAN('T', "time", &trace.full_time,
3068 "Show full timestamp, not time relative to first start"),
David Ahernfd2eaba2013-11-12 09:31:15 -07003069 OPT_BOOLEAN('s', "summary", &trace.summary_only,
3070 "Show only syscall summary with statistics"),
3071 OPT_BOOLEAN('S', "with-summary", &trace.summary,
3072 "Show all syscalls and summary with statistics"),
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04003073 OPT_CALLBACK_DEFAULT('F', "pf", &trace.trace_pgfaults, "all|maj|min",
3074 "Trace pagefaults", parse_pagefaults, "maj"),
Stanislav Fomicheve281a962014-06-26 20:14:28 +04003075 OPT_BOOLEAN(0, "syscalls", &trace.trace_syscalls, "Trace syscalls"),
Yunlong Songe366a6d2015-04-02 21:47:18 +08003076 OPT_BOOLEAN('f', "force", &trace.force, "don't complain, do it"),
Milian Wolff566a0882016-04-08 13:34:15 +02003077 OPT_CALLBACK(0, "call-graph", &trace.opts,
3078 "record_mode[,record_size]", record_callchain_help,
3079 &record_parse_callchain_opt),
Arnaldo Carvalho de Melo44621812016-04-11 15:49:11 -03003080 OPT_BOOLEAN(0, "kernel-syscall-graph", &trace.kernel_syscallchains,
3081 "Show the kernel callchains on the syscall exit path"),
Kan Liang9d9cad72015-06-17 09:51:11 -04003082 OPT_UINTEGER(0, "proc-map-timeout", &trace.opts.proc_map_timeout,
3083 "per thread proc mmap processing timeout in ms"),
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003084 OPT_END()
3085 };
Yunlong Song6fdd9cb2015-03-18 21:35:57 +08003086 const char * const trace_subcommands[] = { "record", NULL };
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003087 int err;
Namhyung Kim32caf0d2012-10-05 14:02:13 +09003088 char bf[BUFSIZ];
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003089
Arnaldo Carvalho de Melo4d08cb82015-02-24 15:35:55 -03003090 signal(SIGSEGV, sighandler_dump_stack);
3091 signal(SIGFPE, sighandler_dump_stack);
3092
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003093 trace.evlist = perf_evlist__new();
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03003094 trace.sctbl = syscalltbl__new();
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003095
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03003096 if (trace.evlist == NULL || trace.sctbl == NULL) {
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003097 pr_err("Not enough memory to run!\n");
He Kuangff8f6952015-05-11 12:28:36 +00003098 err = -ENOMEM;
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003099 goto out;
3100 }
3101
Yunlong Song6fdd9cb2015-03-18 21:35:57 +08003102 argc = parse_options_subcommand(argc, argv, trace_options, trace_subcommands,
3103 trace_usage, PARSE_OPT_STOP_AT_NON_OPTION);
David Ahernfd2eaba2013-11-12 09:31:15 -07003104
Wang Nand7888572016-04-08 15:07:24 +00003105 err = bpf__setup_stdout(trace.evlist);
3106 if (err) {
3107 bpf__strerror_setup_stdout(trace.evlist, err, bf, sizeof(bf));
3108 pr_err("ERROR: Setup BPF stdout failed: %s\n", bf);
3109 goto out;
3110 }
3111
Arnaldo Carvalho de Melo59247e32016-04-12 16:05:02 -03003112 err = -1;
3113
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04003114 if (trace.trace_pgfaults) {
3115 trace.opts.sample_address = true;
3116 trace.opts.sample_time = true;
3117 }
3118
Milian Wolff566a0882016-04-08 13:34:15 +02003119 if (trace.opts.callgraph_set)
3120 symbol_conf.use_callchain = true;
3121
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003122 if (trace.evlist->nr_entries > 0)
3123 evlist__set_evsel_handler(trace.evlist, trace__event_handler);
3124
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04003125 if ((argc >= 1) && (strcmp(argv[0], "record") == 0))
3126 return trace__record(&trace, argc-1, &argv[1]);
3127
3128 /* summary_only implies summary option, but don't overwrite summary if set */
3129 if (trace.summary_only)
3130 trace.summary = trace.summary_only;
3131
Arnaldo Carvalho de Melo726f3232015-02-06 10:16:45 +01003132 if (!trace.trace_syscalls && !trace.trace_pgfaults &&
3133 trace.evlist->nr_entries == 0 /* Was --events used? */) {
Stanislav Fomicheve281a962014-06-26 20:14:28 +04003134 pr_err("Please specify something to trace.\n");
3135 return -1;
3136 }
3137
Arnaldo Carvalho de Melo59247e32016-04-12 16:05:02 -03003138 if (!trace.trace_syscalls && ev_qualifier_str) {
3139 pr_err("The -e option can't be used with --no-syscalls.\n");
3140 goto out;
3141 }
3142
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003143 if (output_name != NULL) {
3144 err = trace__open_output(&trace, output_name);
3145 if (err < 0) {
3146 perror("failed to create output file");
3147 goto out;
3148 }
3149 }
3150
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03003151 trace.open_id = syscalltbl__id(trace.sctbl, "open");
3152
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03003153 if (ev_qualifier_str != NULL) {
Arnaldo Carvalho de Melob059efd2013-08-21 12:56:21 -03003154 const char *s = ev_qualifier_str;
Arnaldo Carvalho de Melo005438a82015-07-20 12:02:09 -03003155 struct strlist_config slist_config = {
3156 .dirname = system_path(STRACE_GROUPS_DIR),
3157 };
Arnaldo Carvalho de Melob059efd2013-08-21 12:56:21 -03003158
3159 trace.not_ev_qualifier = *s == '!';
3160 if (trace.not_ev_qualifier)
3161 ++s;
Arnaldo Carvalho de Melo005438a82015-07-20 12:02:09 -03003162 trace.ev_qualifier = strlist__new(s, &slist_config);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03003163 if (trace.ev_qualifier == NULL) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003164 fputs("Not enough memory to parse event qualifier",
3165 trace.output);
3166 err = -ENOMEM;
3167 goto out_close;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03003168 }
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03003169
3170 err = trace__validate_ev_qualifier(&trace);
3171 if (err)
3172 goto out_close;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03003173 }
3174
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003175 err = target__validate(&trace.opts.target);
Namhyung Kim32caf0d2012-10-05 14:02:13 +09003176 if (err) {
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003177 target__strerror(&trace.opts.target, err, bf, sizeof(bf));
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003178 fprintf(trace.output, "%s", bf);
3179 goto out_close;
Namhyung Kim32caf0d2012-10-05 14:02:13 +09003180 }
3181
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003182 err = target__parse_uid(&trace.opts.target);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003183 if (err) {
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003184 target__strerror(&trace.opts.target, err, bf, sizeof(bf));
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003185 fprintf(trace.output, "%s", bf);
3186 goto out_close;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003187 }
3188
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003189 if (!argc && target__none(&trace.opts.target))
Namhyung Kimee761202012-10-05 14:02:14 +09003190 trace.opts.target.system_wide = true;
3191
David Ahern6810fc92013-08-28 22:29:52 -06003192 if (input_name)
3193 err = trace__replay(&trace);
3194 else
3195 err = trace__run(&trace, argc, argv);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03003196
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003197out_close:
3198 if (output_name != NULL)
3199 fclose(trace.output);
3200out:
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03003201 return err;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003202}