blob: e5f0cc16bb93378b89eb0cceade5d053be37f6a2 [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 Ahern13f22a2d2015-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
1893 if (machine__resolve(trace->host, &al, sample) < 0) {
1894 pr_err("Problem processing %s callchain, skipping...\n",
1895 perf_evsel__name(evsel));
1896 return 0;
1897 }
1898
1899 return perf_evsel__fprintf_callchain(evsel, sample, &al, 38, print_opts,
1900 scripting_max_stack, trace->output);
1901}
1902
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001903static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04001904 union perf_event *event __maybe_unused,
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001905 struct perf_sample *sample)
1906{
Chang Hyun Park2c82c3a2014-09-26 21:54:01 +09001907 long ret;
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001908 u64 duration = 0;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001909 struct thread *thread;
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001910 int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
David Ahernbf2575c2013-10-08 21:26:53 -06001911 struct syscall *sc = trace__syscall_info(trace, evsel, id);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001912 struct thread_trace *ttrace;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001913
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001914 if (sc == NULL)
1915 return -1;
1916
David Ahern8fb598e2013-09-28 13:13:00 -06001917 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001918 ttrace = thread__trace(thread, trace->output);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001919 if (ttrace == NULL)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001920 goto out_put;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001921
David Ahernbf2575c2013-10-08 21:26:53 -06001922 if (trace->summary)
1923 thread__update_stats(ttrace, id, sample);
1924
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -03001925 ret = perf_evsel__sc_tp_uint(evsel, ret, sample);
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001926
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03001927 if (id == trace->open_id && ret >= 0 && ttrace->filename.pending_open) {
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03001928 trace__set_fd_pathname(thread, ret, ttrace->filename.name);
1929 ttrace->filename.pending_open = false;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001930 ++trace->stats.vfs_getname;
1931 }
1932
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001933 ttrace->exit_time = sample->time;
1934
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001935 if (ttrace->entry_time) {
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001936 duration = sample->time - ttrace->entry_time;
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001937 if (trace__filter_duration(trace, duration))
1938 goto out;
1939 } else if (trace->duration_filter)
1940 goto out;
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001941
David Ahernfd2eaba2013-11-12 09:31:15 -07001942 if (trace->summary_only)
1943 goto out;
1944
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001945 trace__fprintf_entry_head(trace, thread, duration, sample->time, trace->output);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001946
1947 if (ttrace->entry_pending) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001948 fprintf(trace->output, "%-70s", ttrace->entry_str);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001949 } else {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001950 fprintf(trace->output, " ... [");
1951 color_fprintf(trace->output, PERF_COLOR_YELLOW, "continued");
1952 fprintf(trace->output, "]: %s()", sc->name);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001953 }
1954
Arnaldo Carvalho de Meloda3c9a42013-08-26 11:28:34 -03001955 if (sc->fmt == NULL) {
1956signed_print:
Chang Hyun Park2c82c3a2014-09-26 21:54:01 +09001957 fprintf(trace->output, ") = %ld", ret);
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -03001958 } else if (ret < 0 && (sc->fmt->errmsg || sc->fmt->errpid)) {
Masami Hiramatsu942a91e2014-08-14 02:22:41 +00001959 char bf[STRERR_BUFSIZE];
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001960 const char *emsg = strerror_r(-ret, bf, sizeof(bf)),
1961 *e = audit_errno_to_name(-ret);
1962
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001963 fprintf(trace->output, ") = -1 %s %s", e, emsg);
Arnaldo Carvalho de Meloda3c9a42013-08-26 11:28:34 -03001964 } else if (ret == 0 && sc->fmt->timeout)
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001965 fprintf(trace->output, ") = 0 Timeout");
Arnaldo Carvalho de Melo04b34722013-08-26 11:36:30 -03001966 else if (sc->fmt->hexret)
Chang Hyun Park2c82c3a2014-09-26 21:54:01 +09001967 fprintf(trace->output, ") = %#lx", ret);
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -03001968 else if (sc->fmt->errpid) {
1969 struct thread *child = machine__find_thread(trace->host, ret, ret);
1970
1971 if (child != NULL) {
1972 fprintf(trace->output, ") = %ld", ret);
1973 if (child->comm_set)
1974 fprintf(trace->output, " (%s)", thread__comm_str(child));
1975 thread__put(child);
1976 }
1977 } else
Arnaldo Carvalho de Meloda3c9a42013-08-26 11:28:34 -03001978 goto signed_print;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001979
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001980 fputc('\n', trace->output);
Milian Wolff566a0882016-04-08 13:34:15 +02001981
Arnaldo Carvalho de Melo202ff962016-04-12 10:11:07 -03001982 trace__fprintf_callchain(trace, evsel, sample);
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001983out:
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001984 ttrace->entry_pending = false;
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001985 err = 0;
1986out_put:
1987 thread__put(thread);
1988 return err;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001989}
1990
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001991static int trace__vfs_getname(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04001992 union perf_event *event __maybe_unused,
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001993 struct perf_sample *sample)
1994{
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001995 struct thread *thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
1996 struct thread_trace *ttrace;
1997 size_t filename_len, entry_str_len, to_move;
1998 ssize_t remaining_space;
1999 char *pos;
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03002000 const char *filename = perf_evsel__rawptr(evsel, sample, "pathname");
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03002001
2002 if (!thread)
2003 goto out;
2004
2005 ttrace = thread__priv(thread);
2006 if (!ttrace)
2007 goto out;
2008
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03002009 filename_len = strlen(filename);
2010
2011 if (ttrace->filename.namelen < filename_len) {
2012 char *f = realloc(ttrace->filename.name, filename_len + 1);
2013
2014 if (f == NULL)
2015 goto out;
2016
2017 ttrace->filename.namelen = filename_len;
2018 ttrace->filename.name = f;
2019 }
2020
2021 strcpy(ttrace->filename.name, filename);
2022 ttrace->filename.pending_open = true;
2023
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03002024 if (!ttrace->filename.ptr)
2025 goto out;
2026
2027 entry_str_len = strlen(ttrace->entry_str);
2028 remaining_space = trace__entry_str_size - entry_str_len - 1; /* \0 */
2029 if (remaining_space <= 0)
2030 goto out;
2031
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03002032 if (filename_len > (size_t)remaining_space) {
2033 filename += filename_len - remaining_space;
2034 filename_len = remaining_space;
2035 }
2036
2037 to_move = entry_str_len - ttrace->filename.entry_str_pos + 1; /* \0 */
2038 pos = ttrace->entry_str + ttrace->filename.entry_str_pos;
2039 memmove(pos + filename_len, pos, to_move);
2040 memcpy(pos, filename, filename_len);
2041
2042 ttrace->filename.ptr = 0;
2043 ttrace->filename.entry_str_pos = 0;
2044out:
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002045 return 0;
2046}
2047
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002048static int trace__sched_stat_runtime(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04002049 union perf_event *event __maybe_unused,
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002050 struct perf_sample *sample)
2051{
2052 u64 runtime = perf_evsel__intval(evsel, sample, "runtime");
2053 double runtime_ms = (double)runtime / NSEC_PER_MSEC;
David Ahern8fb598e2013-09-28 13:13:00 -06002054 struct thread *thread = machine__findnew_thread(trace->host,
Adrian Hunter314add62013-08-27 11:23:03 +03002055 sample->pid,
2056 sample->tid);
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002057 struct thread_trace *ttrace = thread__trace(thread, trace->output);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002058
2059 if (ttrace == NULL)
2060 goto out_dump;
2061
2062 ttrace->runtime_ms += runtime_ms;
2063 trace->runtime_ms += runtime_ms;
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002064 thread__put(thread);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002065 return 0;
2066
2067out_dump:
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002068 fprintf(trace->output, "%s: comm=%s,pid=%u,runtime=%" PRIu64 ",vruntime=%" PRIu64 ")\n",
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002069 evsel->name,
2070 perf_evsel__strval(evsel, sample, "comm"),
2071 (pid_t)perf_evsel__intval(evsel, sample, "pid"),
2072 runtime,
2073 perf_evsel__intval(evsel, sample, "vruntime"));
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002074 thread__put(thread);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002075 return 0;
2076}
2077
Wang Nan1d6c9402016-02-26 09:31:55 +00002078static void bpf_output__printer(enum binary_printer_ops op,
2079 unsigned int val, void *extra)
2080{
2081 FILE *output = extra;
2082 unsigned char ch = (unsigned char)val;
2083
2084 switch (op) {
2085 case BINARY_PRINT_CHAR_DATA:
2086 fprintf(output, "%c", isprint(ch) ? ch : '.');
2087 break;
2088 case BINARY_PRINT_DATA_BEGIN:
2089 case BINARY_PRINT_LINE_BEGIN:
2090 case BINARY_PRINT_ADDR:
2091 case BINARY_PRINT_NUM_DATA:
2092 case BINARY_PRINT_NUM_PAD:
2093 case BINARY_PRINT_SEP:
2094 case BINARY_PRINT_CHAR_PAD:
2095 case BINARY_PRINT_LINE_END:
2096 case BINARY_PRINT_DATA_END:
2097 default:
2098 break;
2099 }
2100}
2101
2102static void bpf_output__fprintf(struct trace *trace,
2103 struct perf_sample *sample)
2104{
2105 print_binary(sample->raw_data, sample->raw_size, 8,
2106 bpf_output__printer, trace->output);
2107}
2108
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002109static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
2110 union perf_event *event __maybe_unused,
2111 struct perf_sample *sample)
2112{
2113 trace__printf_interrupted_entry(trace, sample);
2114 trace__fprintf_tstamp(trace, sample->time, trace->output);
Arnaldo Carvalho de Melo08089212015-02-19 21:51:50 -08002115
2116 if (trace->trace_syscalls)
2117 fprintf(trace->output, "( ): ");
2118
2119 fprintf(trace->output, "%s:", evsel->name);
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002120
Wang Nan1d6c9402016-02-26 09:31:55 +00002121 if (perf_evsel__is_bpf_output(evsel)) {
2122 bpf_output__fprintf(trace, sample);
2123 } else if (evsel->tp_format) {
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002124 event_format__fprintf(evsel->tp_format, sample->cpu,
2125 sample->raw_data, sample->raw_size,
2126 trace->output);
2127 }
2128
2129 fprintf(trace->output, ")\n");
Arnaldo Carvalho de Melo202ff962016-04-12 10:11:07 -03002130
2131 trace__fprintf_callchain(trace, evsel, sample);
2132
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002133 return 0;
2134}
2135
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002136static void print_location(FILE *f, struct perf_sample *sample,
2137 struct addr_location *al,
2138 bool print_dso, bool print_sym)
2139{
2140
2141 if ((verbose || print_dso) && al->map)
2142 fprintf(f, "%s@", al->map->dso->long_name);
2143
2144 if ((verbose || print_sym) && al->sym)
Arnaldo Carvalho de Melo4414a3c2014-07-08 15:39:21 -03002145 fprintf(f, "%s+0x%" PRIx64, al->sym->name,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002146 al->addr - al->sym->start);
2147 else if (al->map)
Arnaldo Carvalho de Melo4414a3c2014-07-08 15:39:21 -03002148 fprintf(f, "0x%" PRIx64, al->addr);
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002149 else
Arnaldo Carvalho de Melo4414a3c2014-07-08 15:39:21 -03002150 fprintf(f, "0x%" PRIx64, sample->addr);
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002151}
2152
2153static int trace__pgfault(struct trace *trace,
2154 struct perf_evsel *evsel,
Arnaldo Carvalho de Melo473398a2016-03-22 18:23:43 -03002155 union perf_event *event __maybe_unused,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002156 struct perf_sample *sample)
2157{
2158 struct thread *thread;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002159 struct addr_location al;
2160 char map_type = 'd';
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04002161 struct thread_trace *ttrace;
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002162 int err = -1;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002163
2164 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04002165 ttrace = thread__trace(thread, trace->output);
2166 if (ttrace == NULL)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002167 goto out_put;
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04002168
2169 if (evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ)
2170 ttrace->pfmaj++;
2171 else
2172 ttrace->pfmin++;
2173
2174 if (trace->summary_only)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002175 goto out;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002176
Arnaldo Carvalho de Melo473398a2016-03-22 18:23:43 -03002177 thread__find_addr_location(thread, sample->cpumode, MAP__FUNCTION,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002178 sample->ip, &al);
2179
2180 trace__fprintf_entry_head(trace, thread, 0, sample->time, trace->output);
2181
2182 fprintf(trace->output, "%sfault [",
2183 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ?
2184 "maj" : "min");
2185
2186 print_location(trace->output, sample, &al, false, true);
2187
2188 fprintf(trace->output, "] => ");
2189
Arnaldo Carvalho de Melo473398a2016-03-22 18:23:43 -03002190 thread__find_addr_location(thread, sample->cpumode, MAP__VARIABLE,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002191 sample->addr, &al);
2192
2193 if (!al.map) {
Arnaldo Carvalho de Melo473398a2016-03-22 18:23:43 -03002194 thread__find_addr_location(thread, sample->cpumode,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002195 MAP__FUNCTION, sample->addr, &al);
2196
2197 if (al.map)
2198 map_type = 'x';
2199 else
2200 map_type = '?';
2201 }
2202
2203 print_location(trace->output, sample, &al, true, false);
2204
2205 fprintf(trace->output, " (%c%c)\n", map_type, al.level);
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002206out:
2207 err = 0;
2208out_put:
2209 thread__put(thread);
2210 return err;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002211}
2212
David Ahernbdc89662013-08-28 22:29:53 -06002213static bool skip_sample(struct trace *trace, struct perf_sample *sample)
2214{
2215 if ((trace->pid_list && intlist__find(trace->pid_list, sample->pid)) ||
2216 (trace->tid_list && intlist__find(trace->tid_list, sample->tid)))
2217 return false;
2218
2219 if (trace->pid_list || trace->tid_list)
2220 return true;
2221
2222 return false;
2223}
2224
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03002225static void trace__set_base_time(struct trace *trace,
Arnaldo Carvalho de Melo8a07a802016-03-31 15:19:39 -03002226 struct perf_evsel *evsel,
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03002227 struct perf_sample *sample)
2228{
Arnaldo Carvalho de Melo8a07a802016-03-31 15:19:39 -03002229 /*
2230 * BPF events were not setting PERF_SAMPLE_TIME, so be more robust
2231 * and don't use sample->time unconditionally, we may end up having
2232 * some other event in the future without PERF_SAMPLE_TIME for good
2233 * reason, i.e. we may not be interested in its timestamps, just in
2234 * it taking place, picking some piece of information when it
2235 * appears in our event stream (vfs_getname comes to mind).
2236 */
2237 if (trace->base_time == 0 && !trace->full_time &&
2238 (evsel->attr.sample_type & PERF_SAMPLE_TIME))
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03002239 trace->base_time = sample->time;
2240}
2241
David Ahern6810fc92013-08-28 22:29:52 -06002242static int trace__process_sample(struct perf_tool *tool,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04002243 union perf_event *event,
David Ahern6810fc92013-08-28 22:29:52 -06002244 struct perf_sample *sample,
2245 struct perf_evsel *evsel,
2246 struct machine *machine __maybe_unused)
2247{
2248 struct trace *trace = container_of(tool, struct trace, tool);
2249 int err = 0;
2250
Arnaldo Carvalho de Melo744a9712013-11-06 10:17:38 -03002251 tracepoint_handler handler = evsel->handler;
David Ahern6810fc92013-08-28 22:29:52 -06002252
David Ahernbdc89662013-08-28 22:29:53 -06002253 if (skip_sample(trace, sample))
2254 return 0;
2255
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03002256 trace__set_base_time(trace, evsel, sample);
David Ahern6810fc92013-08-28 22:29:52 -06002257
David Ahern31605652013-12-04 19:41:41 -07002258 if (handler) {
2259 ++trace->nr_events;
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04002260 handler(trace, evsel, event, sample);
David Ahern31605652013-12-04 19:41:41 -07002261 }
David Ahern6810fc92013-08-28 22:29:52 -06002262
2263 return err;
2264}
2265
David Ahernbdc89662013-08-28 22:29:53 -06002266static int parse_target_str(struct trace *trace)
2267{
2268 if (trace->opts.target.pid) {
2269 trace->pid_list = intlist__new(trace->opts.target.pid);
2270 if (trace->pid_list == NULL) {
2271 pr_err("Error parsing process id string\n");
2272 return -EINVAL;
2273 }
2274 }
2275
2276 if (trace->opts.target.tid) {
2277 trace->tid_list = intlist__new(trace->opts.target.tid);
2278 if (trace->tid_list == NULL) {
2279 pr_err("Error parsing thread id string\n");
2280 return -EINVAL;
2281 }
2282 }
2283
2284 return 0;
2285}
2286
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002287static int trace__record(struct trace *trace, int argc, const char **argv)
David Ahern5e2485b2013-09-28 13:13:01 -06002288{
2289 unsigned int rec_argc, i, j;
2290 const char **rec_argv;
2291 const char * const record_args[] = {
2292 "record",
2293 "-R",
2294 "-m", "1024",
2295 "-c", "1",
David Ahern5e2485b2013-09-28 13:13:01 -06002296 };
2297
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002298 const char * const sc_args[] = { "-e", };
2299 unsigned int sc_args_nr = ARRAY_SIZE(sc_args);
2300 const char * const majpf_args[] = { "-e", "major-faults" };
2301 unsigned int majpf_args_nr = ARRAY_SIZE(majpf_args);
2302 const char * const minpf_args[] = { "-e", "minor-faults" };
2303 unsigned int minpf_args_nr = ARRAY_SIZE(minpf_args);
2304
David Ahern9aca7f12013-12-04 19:41:39 -07002305 /* +1 is for the event string below */
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002306 rec_argc = ARRAY_SIZE(record_args) + sc_args_nr + 1 +
2307 majpf_args_nr + minpf_args_nr + argc;
David Ahern5e2485b2013-09-28 13:13:01 -06002308 rec_argv = calloc(rec_argc + 1, sizeof(char *));
2309
2310 if (rec_argv == NULL)
2311 return -ENOMEM;
2312
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002313 j = 0;
David Ahern5e2485b2013-09-28 13:13:01 -06002314 for (i = 0; i < ARRAY_SIZE(record_args); i++)
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002315 rec_argv[j++] = record_args[i];
2316
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002317 if (trace->trace_syscalls) {
2318 for (i = 0; i < sc_args_nr; i++)
2319 rec_argv[j++] = sc_args[i];
David Ahern5e2485b2013-09-28 13:13:01 -06002320
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002321 /* event string may be different for older kernels - e.g., RHEL6 */
2322 if (is_valid_tracepoint("raw_syscalls:sys_enter"))
2323 rec_argv[j++] = "raw_syscalls:sys_enter,raw_syscalls:sys_exit";
2324 else if (is_valid_tracepoint("syscalls:sys_enter"))
2325 rec_argv[j++] = "syscalls:sys_enter,syscalls:sys_exit";
2326 else {
2327 pr_err("Neither raw_syscalls nor syscalls events exist.\n");
2328 return -1;
2329 }
David Ahern9aca7f12013-12-04 19:41:39 -07002330 }
David Ahern9aca7f12013-12-04 19:41:39 -07002331
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002332 if (trace->trace_pgfaults & TRACE_PFMAJ)
2333 for (i = 0; i < majpf_args_nr; i++)
2334 rec_argv[j++] = majpf_args[i];
David Ahern5e2485b2013-09-28 13:13:01 -06002335
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002336 if (trace->trace_pgfaults & TRACE_PFMIN)
2337 for (i = 0; i < minpf_args_nr; i++)
2338 rec_argv[j++] = minpf_args[i];
2339
2340 for (i = 0; i < (unsigned int)argc; i++)
2341 rec_argv[j++] = argv[i];
2342
2343 return cmd_record(j, rec_argv, NULL);
David Ahern5e2485b2013-09-28 13:13:01 -06002344}
2345
David Ahernbf2575c2013-10-08 21:26:53 -06002346static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp);
2347
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002348static bool perf_evlist__add_vfs_getname(struct perf_evlist *evlist)
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002349{
Arnaldo Carvalho de Meloef503832013-11-07 16:41:19 -03002350 struct perf_evsel *evsel = perf_evsel__newtp("probe", "vfs_getname");
Jiri Olsa8dd2a132015-09-07 10:38:06 +02002351
2352 if (IS_ERR(evsel))
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002353 return false;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002354
2355 if (perf_evsel__field(evsel, "pathname") == NULL) {
2356 perf_evsel__delete(evsel);
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002357 return false;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002358 }
2359
Arnaldo Carvalho de Melo744a9712013-11-06 10:17:38 -03002360 evsel->handler = trace__vfs_getname;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002361 perf_evlist__add(evlist, evsel);
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002362 return true;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002363}
2364
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002365static int perf_evlist__add_pgfault(struct perf_evlist *evlist,
2366 u64 config)
2367{
2368 struct perf_evsel *evsel;
2369 struct perf_event_attr attr = {
2370 .type = PERF_TYPE_SOFTWARE,
2371 .mmap_data = 1,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002372 };
2373
2374 attr.config = config;
Arnaldo Carvalho de Melo05247982014-07-23 18:15:09 -03002375 attr.sample_period = 1;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002376
2377 event_attr_init(&attr);
2378
2379 evsel = perf_evsel__new(&attr);
2380 if (!evsel)
2381 return -ENOMEM;
2382
2383 evsel->handler = trace__pgfault;
2384 perf_evlist__add(evlist, evsel);
2385
2386 return 0;
2387}
2388
Arnaldo Carvalho de Meloddbb1b12015-02-21 12:10:29 -08002389static void trace__handle_event(struct trace *trace, union perf_event *event, struct perf_sample *sample)
2390{
2391 const u32 type = event->header.type;
2392 struct perf_evsel *evsel;
2393
Arnaldo Carvalho de Meloddbb1b12015-02-21 12:10:29 -08002394 if (type != PERF_RECORD_SAMPLE) {
2395 trace__process_event(trace, trace->host, event, sample);
2396 return;
2397 }
2398
2399 evsel = perf_evlist__id2evsel(trace->evlist, sample->id);
2400 if (evsel == NULL) {
2401 fprintf(trace->output, "Unknown tp ID %" PRIu64 ", skipping...\n", sample->id);
2402 return;
2403 }
2404
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03002405 trace__set_base_time(trace, evsel, sample);
2406
Arnaldo Carvalho de Meloddbb1b12015-02-21 12:10:29 -08002407 if (evsel->attr.type == PERF_TYPE_TRACEPOINT &&
2408 sample->raw_data == NULL) {
2409 fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n",
2410 perf_evsel__name(evsel), sample->tid,
2411 sample->cpu, sample->raw_size);
2412 } else {
2413 tracepoint_handler handler = evsel->handler;
2414 handler(trace, evsel, event, sample);
2415 }
2416}
2417
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03002418static int trace__add_syscall_newtp(struct trace *trace)
2419{
2420 int ret = -1;
2421 struct perf_evlist *evlist = trace->evlist;
2422 struct perf_evsel *sys_enter, *sys_exit;
2423
2424 sys_enter = perf_evsel__syscall_newtp("sys_enter", trace__sys_enter);
2425 if (sys_enter == NULL)
2426 goto out;
2427
2428 if (perf_evsel__init_sc_tp_ptr_field(sys_enter, args))
2429 goto out_delete_sys_enter;
2430
2431 sys_exit = perf_evsel__syscall_newtp("sys_exit", trace__sys_exit);
2432 if (sys_exit == NULL)
2433 goto out_delete_sys_enter;
2434
2435 if (perf_evsel__init_sc_tp_uint_field(sys_exit, ret))
2436 goto out_delete_sys_exit;
2437
2438 perf_evlist__add(evlist, sys_enter);
2439 perf_evlist__add(evlist, sys_exit);
2440
Arnaldo Carvalho de Melo44621812016-04-11 15:49:11 -03002441 if (trace->opts.callgraph_set && !trace->kernel_syscallchains) {
2442 /*
2443 * We're interested only in the user space callchain
2444 * leading to the syscall, allow overriding that for
2445 * debugging reasons using --kernel_syscall_callchains
2446 */
2447 sys_exit->attr.exclude_callchain_kernel = 1;
2448 }
2449
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03002450 trace->syscalls.events.sys_enter = sys_enter;
2451 trace->syscalls.events.sys_exit = sys_exit;
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03002452
2453 ret = 0;
2454out:
2455 return ret;
2456
2457out_delete_sys_exit:
2458 perf_evsel__delete_priv(sys_exit);
2459out_delete_sys_enter:
2460 perf_evsel__delete_priv(sys_enter);
2461 goto out;
2462}
2463
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002464static int trace__set_ev_qualifier_filter(struct trace *trace)
2465{
2466 int err = -1;
2467 char *filter = asprintf_expr_inout_ints("id", !trace->not_ev_qualifier,
2468 trace->ev_qualifier_ids.nr,
2469 trace->ev_qualifier_ids.entries);
2470
2471 if (filter == NULL)
2472 goto out_enomem;
2473
2474 if (!perf_evsel__append_filter(trace->syscalls.events.sys_enter, "&&", filter))
2475 err = perf_evsel__append_filter(trace->syscalls.events.sys_exit, "&&", filter);
2476
2477 free(filter);
2478out:
2479 return err;
2480out_enomem:
2481 errno = ENOMEM;
2482 goto out;
2483}
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03002484
Namhyung Kimf15eb532012-10-05 14:02:16 +09002485static int trace__run(struct trace *trace, int argc, const char **argv)
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002486{
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002487 struct perf_evlist *evlist = trace->evlist;
Arnaldo Carvalho de Melo94ad89b2015-07-03 17:42:03 -03002488 struct perf_evsel *evsel;
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03002489 int err = -1, i;
2490 unsigned long before;
Namhyung Kimf15eb532012-10-05 14:02:16 +09002491 const bool forks = argc > 0;
Arnaldo Carvalho de Melo46fb3c22014-09-22 14:39:48 -03002492 bool draining = false;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002493
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03002494 trace->live = true;
2495
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03002496 if (trace->trace_syscalls && trace__add_syscall_newtp(trace))
Arnaldo Carvalho de Melo801c67b2015-01-22 10:52:55 -03002497 goto out_error_raw_syscalls;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002498
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002499 if (trace->trace_syscalls)
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002500 trace->vfs_getname = perf_evlist__add_vfs_getname(evlist);
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002501
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002502 if ((trace->trace_pgfaults & TRACE_PFMAJ) &&
Arnaldo Carvalho de Meloe2726d92015-01-22 10:34:22 -03002503 perf_evlist__add_pgfault(evlist, PERF_COUNT_SW_PAGE_FAULTS_MAJ)) {
Arnaldo Carvalho de Melo5ed08da2015-01-22 11:08:04 -03002504 goto out_error_mem;
Arnaldo Carvalho de Meloe2726d92015-01-22 10:34:22 -03002505 }
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002506
2507 if ((trace->trace_pgfaults & TRACE_PFMIN) &&
2508 perf_evlist__add_pgfault(evlist, PERF_COUNT_SW_PAGE_FAULTS_MIN))
Arnaldo Carvalho de Melo5ed08da2015-01-22 11:08:04 -03002509 goto out_error_mem;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002510
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002511 if (trace->sched &&
Arnaldo Carvalho de Melo2cc990b2015-01-22 11:13:43 -03002512 perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime",
2513 trace__sched_stat_runtime))
2514 goto out_error_sched_stat_runtime;
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002515
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002516 err = perf_evlist__create_maps(evlist, &trace->opts.target);
2517 if (err < 0) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002518 fprintf(trace->output, "Problems parsing the target to trace, check your options!\n");
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002519 goto out_delete_evlist;
2520 }
2521
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03002522 err = trace__symbols_init(trace, evlist);
2523 if (err < 0) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002524 fprintf(trace->output, "Problems initializing symbol libraries!\n");
Arnaldo Carvalho de Melo03ad9742014-01-03 15:56:06 -03002525 goto out_delete_evlist;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03002526 }
2527
Arnaldo Carvalho de Melofde54b72016-04-11 18:42:37 -03002528 perf_evlist__config(evlist, &trace->opts, NULL);
2529
2530 if (trace->opts.callgraph_set && trace->syscalls.events.sys_exit) {
2531 perf_evsel__config_callchain(trace->syscalls.events.sys_exit,
2532 &trace->opts, &callchain_param);
2533 /*
2534 * Now we have evsels with different sample_ids, use
2535 * PERF_SAMPLE_IDENTIFIER to map from sample to evsel
2536 * from a fixed position in each ring buffer record.
2537 *
2538 * As of this the changeset introducing this comment, this
2539 * isn't strictly needed, as the fields that can come before
2540 * PERF_SAMPLE_ID are all used, but we'll probably disable
2541 * some of those for things like copying the payload of
2542 * pointer syscall arguments, and for vfs_getname we don't
2543 * need PERF_SAMPLE_ADDR and PERF_SAMPLE_IP, so do this
2544 * here as a warning we need to use PERF_SAMPLE_IDENTIFIER.
2545 */
2546 perf_evlist__set_sample_bit(evlist, IDENTIFIER);
2547 perf_evlist__reset_sample_bit(evlist, ID);
2548 }
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002549
Namhyung Kimf15eb532012-10-05 14:02:16 +09002550 signal(SIGCHLD, sig_handler);
2551 signal(SIGINT, sig_handler);
2552
2553 if (forks) {
Namhyung Kim6ef73ec2013-03-11 16:43:15 +09002554 err = perf_evlist__prepare_workload(evlist, &trace->opts.target,
Arnaldo Carvalho de Melo735f7e02014-01-03 14:56:49 -03002555 argv, false, NULL);
Namhyung Kimf15eb532012-10-05 14:02:16 +09002556 if (err < 0) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002557 fprintf(trace->output, "Couldn't run the workload!\n");
Arnaldo Carvalho de Melo03ad9742014-01-03 15:56:06 -03002558 goto out_delete_evlist;
Namhyung Kimf15eb532012-10-05 14:02:16 +09002559 }
2560 }
2561
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002562 err = perf_evlist__open(evlist);
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002563 if (err < 0)
2564 goto out_error_open;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002565
Wang Nanba504232016-02-26 09:31:54 +00002566 err = bpf__apply_obj_config();
2567 if (err) {
2568 char errbuf[BUFSIZ];
2569
2570 bpf__strerror_apply_obj_config(err, errbuf, sizeof(errbuf));
2571 pr_err("ERROR: Apply config to BPF failed: %s\n",
2572 errbuf);
2573 goto out_error_open;
2574 }
2575
Arnaldo Carvalho de Melo241b0572015-02-21 10:15:21 -08002576 /*
2577 * Better not use !target__has_task() here because we need to cover the
2578 * case where no threads were specified in the command line, but a
2579 * workload was, and in that case we will fill in the thread_map when
2580 * we fork the workload in perf_evlist__prepare_workload.
2581 */
Arnaldo Carvalho de Melof078c382015-02-21 11:36:52 -08002582 if (trace->filter_pids.nr > 0)
2583 err = perf_evlist__set_filter_pids(evlist, trace->filter_pids.nr, trace->filter_pids.entries);
Jiri Olsae13798c2015-06-23 00:36:02 +02002584 else if (thread_map__pid(evlist->threads, 0) == -1)
Arnaldo Carvalho de Melof078c382015-02-21 11:36:52 -08002585 err = perf_evlist__set_filter_pid(evlist, getpid());
2586
Arnaldo Carvalho de Melo94ad89b2015-07-03 17:42:03 -03002587 if (err < 0)
2588 goto out_error_mem;
2589
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002590 if (trace->ev_qualifier_ids.nr > 0) {
2591 err = trace__set_ev_qualifier_filter(trace);
2592 if (err < 0)
2593 goto out_errno;
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002594
Arnaldo Carvalho de Melo2e5e5f82015-08-03 17:12:29 -03002595 pr_debug("event qualifier tracepoint filter: %s\n",
2596 trace->syscalls.events.sys_exit->filter);
2597 }
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002598
Arnaldo Carvalho de Melo94ad89b2015-07-03 17:42:03 -03002599 err = perf_evlist__apply_filters(evlist, &evsel);
2600 if (err < 0)
2601 goto out_error_apply_filters;
Arnaldo Carvalho de Melo241b0572015-02-21 10:15:21 -08002602
Jiri Olsaf8850372013-11-28 17:57:22 +01002603 err = perf_evlist__mmap(evlist, trace->opts.mmap_pages, false);
Arnaldo Carvalho de Meloe09b18d2014-12-11 18:04:10 -03002604 if (err < 0)
2605 goto out_error_mmap;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002606
Arnaldo Carvalho de Melocb24d012015-04-22 10:04:23 -03002607 if (!target__none(&trace->opts.target))
2608 perf_evlist__enable(evlist);
2609
Namhyung Kimf15eb532012-10-05 14:02:16 +09002610 if (forks)
2611 perf_evlist__start_workload(evlist);
2612
Jiri Olsae13798c2015-06-23 00:36:02 +02002613 trace->multiple_threads = thread_map__pid(evlist->threads, 0) == -1 ||
Arnaldo Carvalho de Melo42052be2015-02-13 12:32:45 -03002614 evlist->threads->nr > 1 ||
2615 perf_evlist__first(evlist)->attr.inherit;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002616again:
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03002617 before = trace->nr_events;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002618
2619 for (i = 0; i < evlist->nr_mmaps; i++) {
2620 union perf_event *event;
2621
2622 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002623 struct perf_sample sample;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002624
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03002625 ++trace->nr_events;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002626
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002627 err = perf_evlist__parse_sample(evlist, event, &sample);
2628 if (err) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002629 fprintf(trace->output, "Can't parse sample, err = %d, skipping...\n", err);
Zhouyi Zhou8e50d382013-10-24 15:43:33 +08002630 goto next_event;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002631 }
2632
Arnaldo Carvalho de Meloddbb1b12015-02-21 12:10:29 -08002633 trace__handle_event(trace, event, &sample);
Zhouyi Zhou8e50d382013-10-24 15:43:33 +08002634next_event:
2635 perf_evlist__mmap_consume(evlist, i);
Arnaldo Carvalho de Melo20c5f102013-09-03 11:55:07 -03002636
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002637 if (interrupted)
2638 goto out_disable;
Arnaldo Carvalho de Melo02ac5422015-04-22 11:11:57 -03002639
2640 if (done && !draining) {
2641 perf_evlist__disable(evlist);
2642 draining = true;
2643 }
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002644 }
2645 }
2646
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03002647 if (trace->nr_events == before) {
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002648 int timeout = done ? 100 : -1;
Namhyung Kimf15eb532012-10-05 14:02:16 +09002649
Arnaldo Carvalho de Melo46fb3c22014-09-22 14:39:48 -03002650 if (!draining && perf_evlist__poll(evlist, timeout) > 0) {
2651 if (perf_evlist__filter_pollfd(evlist, POLLERR | POLLHUP) == 0)
2652 draining = true;
2653
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002654 goto again;
Arnaldo Carvalho de Melo46fb3c22014-09-22 14:39:48 -03002655 }
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002656 } else {
2657 goto again;
Namhyung Kimf15eb532012-10-05 14:02:16 +09002658 }
2659
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002660out_disable:
Arnaldo Carvalho de Melof3b623b2015-03-02 22:21:35 -03002661 thread__zput(trace->current);
2662
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002663 perf_evlist__disable(evlist);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002664
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002665 if (!err) {
2666 if (trace->summary)
2667 trace__fprintf_thread_summary(trace, trace->output);
2668
2669 if (trace->show_tool_stats) {
2670 fprintf(trace->output, "Stats:\n "
2671 " vfs_getname : %" PRIu64 "\n"
2672 " proc_getname: %" PRIu64 "\n",
2673 trace->stats.vfs_getname,
2674 trace->stats.proc_getname);
2675 }
2676 }
David Ahernbf2575c2013-10-08 21:26:53 -06002677
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002678out_delete_evlist:
2679 perf_evlist__delete(evlist);
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002680 trace->evlist = NULL;
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03002681 trace->live = false;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002682 return err;
Arnaldo Carvalho de Melo6ef068c2013-10-17 12:07:58 -03002683{
2684 char errbuf[BUFSIZ];
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002685
Arnaldo Carvalho de Melo2cc990b2015-01-22 11:13:43 -03002686out_error_sched_stat_runtime:
Jiri Olsa988bdb32015-09-02 09:56:35 +02002687 tracing_path__strerror_open_tp(errno, errbuf, sizeof(errbuf), "sched", "sched_stat_runtime");
Arnaldo Carvalho de Melo2cc990b2015-01-22 11:13:43 -03002688 goto out_error;
2689
Arnaldo Carvalho de Melo801c67b2015-01-22 10:52:55 -03002690out_error_raw_syscalls:
Jiri Olsa988bdb32015-09-02 09:56:35 +02002691 tracing_path__strerror_open_tp(errno, errbuf, sizeof(errbuf), "raw_syscalls", "sys_(enter|exit)");
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002692 goto out_error;
2693
Arnaldo Carvalho de Meloe09b18d2014-12-11 18:04:10 -03002694out_error_mmap:
2695 perf_evlist__strerror_mmap(evlist, errno, errbuf, sizeof(errbuf));
2696 goto out_error;
2697
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002698out_error_open:
2699 perf_evlist__strerror_open(evlist, errno, errbuf, sizeof(errbuf));
2700
2701out_error:
Arnaldo Carvalho de Melo6ef068c2013-10-17 12:07:58 -03002702 fprintf(trace->output, "%s\n", errbuf);
Ramkumar Ramachandra87f91862013-10-04 10:47:31 +05302703 goto out_delete_evlist;
Arnaldo Carvalho de Melo94ad89b2015-07-03 17:42:03 -03002704
2705out_error_apply_filters:
2706 fprintf(trace->output,
2707 "Failed to set filter \"%s\" on event %s with %d (%s)\n",
2708 evsel->filter, perf_evsel__name(evsel), errno,
2709 strerror_r(errno, errbuf, sizeof(errbuf)));
2710 goto out_delete_evlist;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002711}
Arnaldo Carvalho de Melo5ed08da2015-01-22 11:08:04 -03002712out_error_mem:
2713 fprintf(trace->output, "Not enough memory to run!\n");
2714 goto out_delete_evlist;
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002715
2716out_errno:
2717 fprintf(trace->output, "errno=%d,%s\n", errno, strerror(errno));
2718 goto out_delete_evlist;
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002719}
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002720
David Ahern6810fc92013-08-28 22:29:52 -06002721static int trace__replay(struct trace *trace)
2722{
2723 const struct perf_evsel_str_handler handlers[] = {
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002724 { "probe:vfs_getname", trace__vfs_getname, },
David Ahern6810fc92013-08-28 22:29:52 -06002725 };
Jiri Olsaf5fc14122013-10-15 16:27:32 +02002726 struct perf_data_file file = {
2727 .path = input_name,
2728 .mode = PERF_DATA_MODE_READ,
Yunlong Songe366a6d2015-04-02 21:47:18 +08002729 .force = trace->force,
Jiri Olsaf5fc14122013-10-15 16:27:32 +02002730 };
David Ahern6810fc92013-08-28 22:29:52 -06002731 struct perf_session *session;
Namhyung Kim003824e2013-11-12 15:25:00 +09002732 struct perf_evsel *evsel;
David Ahern6810fc92013-08-28 22:29:52 -06002733 int err = -1;
2734
2735 trace->tool.sample = trace__process_sample;
2736 trace->tool.mmap = perf_event__process_mmap;
David Ahern384c6712013-09-22 19:44:58 -06002737 trace->tool.mmap2 = perf_event__process_mmap2;
David Ahern6810fc92013-08-28 22:29:52 -06002738 trace->tool.comm = perf_event__process_comm;
2739 trace->tool.exit = perf_event__process_exit;
2740 trace->tool.fork = perf_event__process_fork;
2741 trace->tool.attr = perf_event__process_attr;
2742 trace->tool.tracing_data = perf_event__process_tracing_data;
2743 trace->tool.build_id = perf_event__process_build_id;
2744
Jiri Olsa0a8cb852014-07-06 14:18:21 +02002745 trace->tool.ordered_events = true;
David Ahern6810fc92013-08-28 22:29:52 -06002746 trace->tool.ordering_requires_timestamps = true;
2747
2748 /* add tid to output */
2749 trace->multiple_threads = true;
2750
Jiri Olsaf5fc14122013-10-15 16:27:32 +02002751 session = perf_session__new(&file, false, &trace->tool);
David Ahern6810fc92013-08-28 22:29:52 -06002752 if (session == NULL)
Taeung Song52e028342014-09-24 10:33:37 +09002753 return -1;
David Ahern6810fc92013-08-28 22:29:52 -06002754
Namhyung Kim0a7e6d12014-08-12 15:40:45 +09002755 if (symbol__init(&session->header.env) < 0)
Namhyung Kimcb2ffae2014-08-12 15:40:44 +09002756 goto out;
2757
David Ahern8fb598e2013-09-28 13:13:00 -06002758 trace->host = &session->machines.host;
2759
David Ahern6810fc92013-08-28 22:29:52 -06002760 err = perf_session__set_tracepoints_handlers(session, handlers);
2761 if (err)
2762 goto out;
2763
Namhyung Kim003824e2013-11-12 15:25:00 +09002764 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2765 "raw_syscalls:sys_enter");
David Ahern9aca7f12013-12-04 19:41:39 -07002766 /* older kernels have syscalls tp versus raw_syscalls */
2767 if (evsel == NULL)
2768 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2769 "syscalls:sys_enter");
David Ahern6810fc92013-08-28 22:29:52 -06002770
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002771 if (evsel &&
2772 (perf_evsel__init_syscall_tp(evsel, trace__sys_enter) < 0 ||
2773 perf_evsel__init_sc_tp_ptr_field(evsel, args))) {
Namhyung Kim003824e2013-11-12 15:25:00 +09002774 pr_err("Error during initialize raw_syscalls:sys_enter event\n");
2775 goto out;
2776 }
2777
2778 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2779 "raw_syscalls:sys_exit");
David Ahern9aca7f12013-12-04 19:41:39 -07002780 if (evsel == NULL)
2781 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2782 "syscalls:sys_exit");
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002783 if (evsel &&
2784 (perf_evsel__init_syscall_tp(evsel, trace__sys_exit) < 0 ||
2785 perf_evsel__init_sc_tp_uint_field(evsel, ret))) {
Namhyung Kim003824e2013-11-12 15:25:00 +09002786 pr_err("Error during initialize raw_syscalls:sys_exit event\n");
David Ahern6810fc92013-08-28 22:29:52 -06002787 goto out;
2788 }
2789
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002790 evlist__for_each(session->evlist, evsel) {
2791 if (evsel->attr.type == PERF_TYPE_SOFTWARE &&
2792 (evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ||
2793 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MIN ||
2794 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS))
2795 evsel->handler = trace__pgfault;
2796 }
2797
David Ahernbdc89662013-08-28 22:29:53 -06002798 err = parse_target_str(trace);
2799 if (err != 0)
2800 goto out;
2801
David Ahern6810fc92013-08-28 22:29:52 -06002802 setup_pager();
2803
Arnaldo Carvalho de Melob7b61cb2015-03-03 11:58:45 -03002804 err = perf_session__process_events(session);
David Ahern6810fc92013-08-28 22:29:52 -06002805 if (err)
2806 pr_err("Failed to process events, error %d", err);
2807
David Ahernbf2575c2013-10-08 21:26:53 -06002808 else if (trace->summary)
2809 trace__fprintf_thread_summary(trace, trace->output);
2810
David Ahern6810fc92013-08-28 22:29:52 -06002811out:
2812 perf_session__delete(session);
2813
2814 return err;
2815}
2816
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002817static size_t trace__fprintf_threads_header(FILE *fp)
2818{
2819 size_t printed;
2820
Pekka Enberg99ff7152013-11-12 16:42:14 +02002821 printed = fprintf(fp, "\n Summary of events:\n\n");
David Ahernbf2575c2013-10-08 21:26:53 -06002822
2823 return printed;
2824}
2825
2826static size_t thread__dump_stats(struct thread_trace *ttrace,
2827 struct trace *trace, FILE *fp)
2828{
2829 struct stats *stats;
2830 size_t printed = 0;
2831 struct syscall *sc;
2832 struct int_node *inode = intlist__first(ttrace->syscall_stats);
2833
2834 if (inode == NULL)
2835 return 0;
2836
2837 printed += fprintf(fp, "\n");
2838
Milian Wolff834fd462015-08-06 11:24:29 +02002839 printed += fprintf(fp, " syscall calls total min avg max stddev\n");
2840 printed += fprintf(fp, " (msec) (msec) (msec) (msec) (%%)\n");
2841 printed += fprintf(fp, " --------------- -------- --------- --------- --------- --------- ------\n");
Pekka Enberg99ff7152013-11-12 16:42:14 +02002842
David Ahernbf2575c2013-10-08 21:26:53 -06002843 /* each int_node is a syscall */
2844 while (inode) {
2845 stats = inode->priv;
2846 if (stats) {
2847 double min = (double)(stats->min) / NSEC_PER_MSEC;
2848 double max = (double)(stats->max) / NSEC_PER_MSEC;
2849 double avg = avg_stats(stats);
2850 double pct;
2851 u64 n = (u64) stats->n;
2852
2853 pct = avg ? 100.0 * stddev_stats(stats)/avg : 0.0;
2854 avg /= NSEC_PER_MSEC;
2855
2856 sc = &trace->syscalls.table[inode->i];
Pekka Enberg99ff7152013-11-12 16:42:14 +02002857 printed += fprintf(fp, " %-15s", sc->name);
Milian Wolff834fd462015-08-06 11:24:29 +02002858 printed += fprintf(fp, " %8" PRIu64 " %9.3f %9.3f %9.3f",
2859 n, avg * n, min, avg);
Pekka Enberg27a778b2013-11-13 14:21:48 +02002860 printed += fprintf(fp, " %9.3f %9.2f%%\n", max, pct);
David Ahernbf2575c2013-10-08 21:26:53 -06002861 }
2862
2863 inode = intlist__next(inode);
2864 }
2865
2866 printed += fprintf(fp, "\n\n");
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002867
2868 return printed;
2869}
2870
David Ahern896cbb52013-09-28 13:12:59 -06002871/* struct used to pass data to per-thread function */
2872struct summary_data {
2873 FILE *fp;
2874 struct trace *trace;
2875 size_t printed;
2876};
2877
2878static int trace__fprintf_one_thread(struct thread *thread, void *priv)
2879{
2880 struct summary_data *data = priv;
2881 FILE *fp = data->fp;
2882 size_t printed = data->printed;
2883 struct trace *trace = data->trace;
Namhyung Kim89dceb22014-10-06 09:46:03 +09002884 struct thread_trace *ttrace = thread__priv(thread);
David Ahern896cbb52013-09-28 13:12:59 -06002885 double ratio;
2886
2887 if (ttrace == NULL)
2888 return 0;
2889
2890 ratio = (double)ttrace->nr_events / trace->nr_events * 100.0;
2891
Pekka Enberg15e65c62013-11-14 18:43:30 +02002892 printed += fprintf(fp, " %s (%d), ", thread__comm_str(thread), thread->tid);
Pekka Enberg99ff7152013-11-12 16:42:14 +02002893 printed += fprintf(fp, "%lu events, ", ttrace->nr_events);
Pekka Enberg15e65c62013-11-14 18:43:30 +02002894 printed += fprintf(fp, "%.1f%%", ratio);
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04002895 if (ttrace->pfmaj)
2896 printed += fprintf(fp, ", %lu majfaults", ttrace->pfmaj);
2897 if (ttrace->pfmin)
2898 printed += fprintf(fp, ", %lu minfaults", ttrace->pfmin);
Pekka Enberg99ff7152013-11-12 16:42:14 +02002899 printed += fprintf(fp, ", %.3f msec\n", ttrace->runtime_ms);
David Ahernbf2575c2013-10-08 21:26:53 -06002900 printed += thread__dump_stats(ttrace, trace, fp);
David Ahern896cbb52013-09-28 13:12:59 -06002901
2902 data->printed += printed;
2903
2904 return 0;
2905}
2906
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002907static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp)
2908{
David Ahern896cbb52013-09-28 13:12:59 -06002909 struct summary_data data = {
2910 .fp = fp,
2911 .trace = trace
2912 };
2913 data.printed = trace__fprintf_threads_header(fp);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002914
David Ahern896cbb52013-09-28 13:12:59 -06002915 machine__for_each_thread(trace->host, trace__fprintf_one_thread, &data);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002916
David Ahern896cbb52013-09-28 13:12:59 -06002917 return data.printed;
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002918}
2919
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03002920static int trace__set_duration(const struct option *opt, const char *str,
2921 int unset __maybe_unused)
2922{
2923 struct trace *trace = opt->value;
2924
2925 trace->duration_filter = atof(str);
2926 return 0;
2927}
2928
Arnaldo Carvalho de Melof078c382015-02-21 11:36:52 -08002929static int trace__set_filter_pids(const struct option *opt, const char *str,
2930 int unset __maybe_unused)
2931{
2932 int ret = -1;
2933 size_t i;
2934 struct trace *trace = opt->value;
2935 /*
2936 * FIXME: introduce a intarray class, plain parse csv and create a
2937 * { int nr, int entries[] } struct...
2938 */
2939 struct intlist *list = intlist__new(str);
2940
2941 if (list == NULL)
2942 return -1;
2943
2944 i = trace->filter_pids.nr = intlist__nr_entries(list) + 1;
2945 trace->filter_pids.entries = calloc(i, sizeof(pid_t));
2946
2947 if (trace->filter_pids.entries == NULL)
2948 goto out;
2949
2950 trace->filter_pids.entries[0] = getpid();
2951
2952 for (i = 1; i < trace->filter_pids.nr; ++i)
2953 trace->filter_pids.entries[i] = intlist__entry(list, i - 1)->i;
2954
2955 intlist__delete(list);
2956 ret = 0;
2957out:
2958 return ret;
2959}
2960
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002961static int trace__open_output(struct trace *trace, const char *filename)
2962{
2963 struct stat st;
2964
2965 if (!stat(filename, &st) && st.st_size) {
2966 char oldname[PATH_MAX];
2967
2968 scnprintf(oldname, sizeof(oldname), "%s.old", filename);
2969 unlink(oldname);
2970 rename(filename, oldname);
2971 }
2972
2973 trace->output = fopen(filename, "w");
2974
2975 return trace->output == NULL ? -errno : 0;
2976}
2977
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002978static int parse_pagefaults(const struct option *opt, const char *str,
2979 int unset __maybe_unused)
2980{
2981 int *trace_pgfaults = opt->value;
2982
2983 if (strcmp(str, "all") == 0)
2984 *trace_pgfaults |= TRACE_PFMAJ | TRACE_PFMIN;
2985 else if (strcmp(str, "maj") == 0)
2986 *trace_pgfaults |= TRACE_PFMAJ;
2987 else if (strcmp(str, "min") == 0)
2988 *trace_pgfaults |= TRACE_PFMIN;
2989 else
2990 return -1;
2991
2992 return 0;
2993}
2994
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002995static void evlist__set_evsel_handler(struct perf_evlist *evlist, void *handler)
2996{
2997 struct perf_evsel *evsel;
2998
2999 evlist__for_each(evlist, evsel)
3000 evsel->handler = handler;
3001}
3002
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003003int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
3004{
Yunlong Song6fdd9cb2015-03-18 21:35:57 +08003005 const char *trace_usage[] = {
Namhyung Kimf15eb532012-10-05 14:02:16 +09003006 "perf trace [<options>] [<command>]",
3007 "perf trace [<options>] -- <command> [<options>]",
David Ahern5e2485b2013-09-28 13:13:01 -06003008 "perf trace record [<options>] [<command>]",
3009 "perf trace record [<options>] -- <command> [<options>]",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003010 NULL
3011 };
3012 struct trace trace = {
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003013 .syscalls = {
3014 . max = -1,
3015 },
3016 .opts = {
3017 .target = {
3018 .uid = UINT_MAX,
3019 .uses_mmap = true,
3020 },
3021 .user_freq = UINT_MAX,
3022 .user_interval = ULLONG_MAX,
Arnaldo Carvalho de Melo509051e2014-01-14 17:52:14 -03003023 .no_buffering = true,
Arnaldo Carvalho de Melo38d54472014-12-12 17:28:32 -03003024 .mmap_pages = UINT_MAX,
Kan Liang9d9cad72015-06-17 09:51:11 -04003025 .proc_map_timeout = 500,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003026 },
Milian Wolff007d66a2015-08-05 16:52:23 -03003027 .output = stderr,
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -03003028 .show_comm = true,
Stanislav Fomicheve281a962014-06-26 20:14:28 +04003029 .trace_syscalls = true,
Arnaldo Carvalho de Melo44621812016-04-11 15:49:11 -03003030 .kernel_syscallchains = false,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003031 };
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003032 const char *output_name = NULL;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03003033 const char *ev_qualifier_str = NULL;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003034 const struct option trace_options[] = {
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003035 OPT_CALLBACK(0, "event", &trace.evlist, "event",
3036 "event selector. use 'perf list' to list available events",
3037 parse_events_option),
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -03003038 OPT_BOOLEAN(0, "comm", &trace.show_comm,
3039 "show the thread COMM next to its id"),
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03003040 OPT_BOOLEAN(0, "tool_stats", &trace.show_tool_stats, "show tool stats"),
Arnaldo Carvalho de Melod303e852015-04-23 12:02:07 -03003041 OPT_STRING('e', "expr", &ev_qualifier_str, "expr", "list of syscalls to trace"),
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003042 OPT_STRING('o', "output", &output_name, "file", "output file name"),
David Ahern6810fc92013-08-28 22:29:52 -06003043 OPT_STRING('i', "input", &input_name, "file", "Analyze events in file"),
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003044 OPT_STRING('p', "pid", &trace.opts.target.pid, "pid",
3045 "trace events on existing process id"),
David Ahernac9be8e2013-08-20 11:15:45 -06003046 OPT_STRING('t', "tid", &trace.opts.target.tid, "tid",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003047 "trace events on existing thread id"),
Arnaldo Carvalho de Melofa0e4ff2015-04-23 11:59:20 -03003048 OPT_CALLBACK(0, "filter-pids", &trace, "CSV list of pids",
3049 "pids to filter (by the kernel)", trace__set_filter_pids),
David Ahernac9be8e2013-08-20 11:15:45 -06003050 OPT_BOOLEAN('a', "all-cpus", &trace.opts.target.system_wide,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003051 "system-wide collection from all CPUs"),
David Ahernac9be8e2013-08-20 11:15:45 -06003052 OPT_STRING('C', "cpu", &trace.opts.target.cpu_list, "cpu",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003053 "list of cpus to monitor"),
David Ahern6810fc92013-08-28 22:29:52 -06003054 OPT_BOOLEAN(0, "no-inherit", &trace.opts.no_inherit,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003055 "child tasks do not inherit counters"),
Jiri Olsa994a1f72013-09-01 12:36:12 +02003056 OPT_CALLBACK('m', "mmap-pages", &trace.opts.mmap_pages, "pages",
3057 "number of mmap data pages",
3058 perf_evlist__parse_mmap_pages),
David Ahernac9be8e2013-08-20 11:15:45 -06003059 OPT_STRING('u', "uid", &trace.opts.target.uid_str, "user",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003060 "user to profile"),
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03003061 OPT_CALLBACK(0, "duration", &trace, "float",
3062 "show only events with duration > N.M ms",
3063 trace__set_duration),
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03003064 OPT_BOOLEAN(0, "sched", &trace.sched, "show blocking scheduler events"),
Arnaldo Carvalho de Melo7c304ee02013-08-22 16:49:54 -03003065 OPT_INCR('v', "verbose", &verbose, "be more verbose"),
David Ahern4bb09192013-09-04 12:37:43 -06003066 OPT_BOOLEAN('T', "time", &trace.full_time,
3067 "Show full timestamp, not time relative to first start"),
David Ahernfd2eaba2013-11-12 09:31:15 -07003068 OPT_BOOLEAN('s', "summary", &trace.summary_only,
3069 "Show only syscall summary with statistics"),
3070 OPT_BOOLEAN('S', "with-summary", &trace.summary,
3071 "Show all syscalls and summary with statistics"),
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04003072 OPT_CALLBACK_DEFAULT('F', "pf", &trace.trace_pgfaults, "all|maj|min",
3073 "Trace pagefaults", parse_pagefaults, "maj"),
Stanislav Fomicheve281a962014-06-26 20:14:28 +04003074 OPT_BOOLEAN(0, "syscalls", &trace.trace_syscalls, "Trace syscalls"),
Yunlong Songe366a6d2015-04-02 21:47:18 +08003075 OPT_BOOLEAN('f', "force", &trace.force, "don't complain, do it"),
Milian Wolff566a0882016-04-08 13:34:15 +02003076 OPT_CALLBACK(0, "call-graph", &trace.opts,
3077 "record_mode[,record_size]", record_callchain_help,
3078 &record_parse_callchain_opt),
Arnaldo Carvalho de Melo44621812016-04-11 15:49:11 -03003079 OPT_BOOLEAN(0, "kernel-syscall-graph", &trace.kernel_syscallchains,
3080 "Show the kernel callchains on the syscall exit path"),
Kan Liang9d9cad72015-06-17 09:51:11 -04003081 OPT_UINTEGER(0, "proc-map-timeout", &trace.opts.proc_map_timeout,
3082 "per thread proc mmap processing timeout in ms"),
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003083 OPT_END()
3084 };
Yunlong Song6fdd9cb2015-03-18 21:35:57 +08003085 const char * const trace_subcommands[] = { "record", NULL };
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003086 int err;
Namhyung Kim32caf0d2012-10-05 14:02:13 +09003087 char bf[BUFSIZ];
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003088
Arnaldo Carvalho de Melo4d08cb82015-02-24 15:35:55 -03003089 signal(SIGSEGV, sighandler_dump_stack);
3090 signal(SIGFPE, sighandler_dump_stack);
3091
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003092 trace.evlist = perf_evlist__new();
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03003093 trace.sctbl = syscalltbl__new();
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003094
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03003095 if (trace.evlist == NULL || trace.sctbl == NULL) {
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003096 pr_err("Not enough memory to run!\n");
He Kuangff8f6952015-05-11 12:28:36 +00003097 err = -ENOMEM;
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003098 goto out;
3099 }
3100
Yunlong Song6fdd9cb2015-03-18 21:35:57 +08003101 argc = parse_options_subcommand(argc, argv, trace_options, trace_subcommands,
3102 trace_usage, PARSE_OPT_STOP_AT_NON_OPTION);
David Ahernfd2eaba2013-11-12 09:31:15 -07003103
Wang Nand7888572016-04-08 15:07:24 +00003104 err = bpf__setup_stdout(trace.evlist);
3105 if (err) {
3106 bpf__strerror_setup_stdout(trace.evlist, err, bf, sizeof(bf));
3107 pr_err("ERROR: Setup BPF stdout failed: %s\n", bf);
3108 goto out;
3109 }
3110
Arnaldo Carvalho de Melo59247e32016-04-12 16:05:02 -03003111 err = -1;
3112
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04003113 if (trace.trace_pgfaults) {
3114 trace.opts.sample_address = true;
3115 trace.opts.sample_time = true;
3116 }
3117
Milian Wolff566a0882016-04-08 13:34:15 +02003118 if (trace.opts.callgraph_set)
3119 symbol_conf.use_callchain = true;
3120
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003121 if (trace.evlist->nr_entries > 0)
3122 evlist__set_evsel_handler(trace.evlist, trace__event_handler);
3123
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04003124 if ((argc >= 1) && (strcmp(argv[0], "record") == 0))
3125 return trace__record(&trace, argc-1, &argv[1]);
3126
3127 /* summary_only implies summary option, but don't overwrite summary if set */
3128 if (trace.summary_only)
3129 trace.summary = trace.summary_only;
3130
Arnaldo Carvalho de Melo726f3232015-02-06 10:16:45 +01003131 if (!trace.trace_syscalls && !trace.trace_pgfaults &&
3132 trace.evlist->nr_entries == 0 /* Was --events used? */) {
Stanislav Fomicheve281a962014-06-26 20:14:28 +04003133 pr_err("Please specify something to trace.\n");
3134 return -1;
3135 }
3136
Arnaldo Carvalho de Melo59247e32016-04-12 16:05:02 -03003137 if (!trace.trace_syscalls && ev_qualifier_str) {
3138 pr_err("The -e option can't be used with --no-syscalls.\n");
3139 goto out;
3140 }
3141
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003142 if (output_name != NULL) {
3143 err = trace__open_output(&trace, output_name);
3144 if (err < 0) {
3145 perror("failed to create output file");
3146 goto out;
3147 }
3148 }
3149
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03003150 trace.open_id = syscalltbl__id(trace.sctbl, "open");
3151
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03003152 if (ev_qualifier_str != NULL) {
Arnaldo Carvalho de Melob059efd2013-08-21 12:56:21 -03003153 const char *s = ev_qualifier_str;
Arnaldo Carvalho de Melo005438a82015-07-20 12:02:09 -03003154 struct strlist_config slist_config = {
3155 .dirname = system_path(STRACE_GROUPS_DIR),
3156 };
Arnaldo Carvalho de Melob059efd2013-08-21 12:56:21 -03003157
3158 trace.not_ev_qualifier = *s == '!';
3159 if (trace.not_ev_qualifier)
3160 ++s;
Arnaldo Carvalho de Melo005438a82015-07-20 12:02:09 -03003161 trace.ev_qualifier = strlist__new(s, &slist_config);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03003162 if (trace.ev_qualifier == NULL) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003163 fputs("Not enough memory to parse event qualifier",
3164 trace.output);
3165 err = -ENOMEM;
3166 goto out_close;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03003167 }
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03003168
3169 err = trace__validate_ev_qualifier(&trace);
3170 if (err)
3171 goto out_close;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03003172 }
3173
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003174 err = target__validate(&trace.opts.target);
Namhyung Kim32caf0d2012-10-05 14:02:13 +09003175 if (err) {
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003176 target__strerror(&trace.opts.target, err, bf, sizeof(bf));
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003177 fprintf(trace.output, "%s", bf);
3178 goto out_close;
Namhyung Kim32caf0d2012-10-05 14:02:13 +09003179 }
3180
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003181 err = target__parse_uid(&trace.opts.target);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003182 if (err) {
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003183 target__strerror(&trace.opts.target, err, bf, sizeof(bf));
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003184 fprintf(trace.output, "%s", bf);
3185 goto out_close;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003186 }
3187
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003188 if (!argc && target__none(&trace.opts.target))
Namhyung Kimee761202012-10-05 14:02:14 +09003189 trace.opts.target.system_wide = true;
3190
David Ahern6810fc92013-08-28 22:29:52 -06003191 if (input_name)
3192 err = trace__replay(&trace);
3193 else
3194 err = trace__run(&trace, argc, argv);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03003195
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003196out_close:
3197 if (output_name != NULL)
3198 fclose(trace.output);
3199out:
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03003200 return err;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003201}