blob: 39a158923acf87812fce013a0a870c6938c48882 [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 Meloc6d4a492016-04-14 18:29:08 -030049#include <linux/stringify.h>
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -030050
Arnaldo Carvalho de Meloc188e7a2015-05-14 17:39:03 -030051#ifndef O_CLOEXEC
52# define O_CLOEXEC 02000000
53#endif
54
Arnaldo Carvalho de Meloc188e7a2015-05-14 17:39:03 -030055#ifndef MSG_CMSG_CLOEXEC
56# define MSG_CMSG_CLOEXEC 0x40000000
57#endif
58
Arnaldo Carvalho de Meloa1c25522015-06-11 22:47:54 -030059#ifndef PERF_FLAG_FD_NO_GROUP
60# define PERF_FLAG_FD_NO_GROUP (1UL << 0)
61#endif
62
63#ifndef PERF_FLAG_FD_OUTPUT
64# define PERF_FLAG_FD_OUTPUT (1UL << 1)
65#endif
66
67#ifndef PERF_FLAG_PID_CGROUP
68# define PERF_FLAG_PID_CGROUP (1UL << 2) /* pid=cgroup id, per-cpu mode only */
69#endif
70
71#ifndef PERF_FLAG_FD_CLOEXEC
72# define PERF_FLAG_FD_CLOEXEC (1UL << 3) /* O_CLOEXEC */
73#endif
74
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -030075struct trace {
76 struct perf_tool tool;
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -030077 struct syscalltbl *sctbl;
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -030078 struct {
79 int max;
80 struct syscall *table;
81 struct {
82 struct perf_evsel *sys_enter,
83 *sys_exit;
84 } events;
85 } syscalls;
86 struct record_opts opts;
87 struct perf_evlist *evlist;
88 struct machine *host;
89 struct thread *current;
90 u64 base_time;
91 FILE *output;
92 unsigned long nr_events;
93 struct strlist *ev_qualifier;
94 struct {
95 size_t nr;
96 int *entries;
97 } ev_qualifier_ids;
98 struct intlist *tid_list;
99 struct intlist *pid_list;
100 struct {
101 size_t nr;
102 pid_t *entries;
103 } filter_pids;
104 double duration_filter;
105 double runtime_ms;
106 struct {
107 u64 vfs_getname,
108 proc_getname;
109 } stats;
Arnaldo Carvalho de Meloc6d4a492016-04-14 18:29:08 -0300110 unsigned int max_stack;
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -0300111 bool not_ev_qualifier;
112 bool live;
113 bool full_time;
114 bool sched;
115 bool multiple_threads;
116 bool summary;
117 bool summary_only;
118 bool show_comm;
119 bool show_tool_stats;
120 bool trace_syscalls;
Arnaldo Carvalho de Melo44621812016-04-11 15:49:11 -0300121 bool kernel_syscallchains;
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -0300122 bool force;
123 bool vfs_getname;
124 int trace_pgfaults;
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -0300125 int open_id;
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -0300126};
Arnaldo Carvalho de Meloa1c25522015-06-11 22:47:54 -0300127
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300128struct tp_field {
129 int offset;
130 union {
131 u64 (*integer)(struct tp_field *field, struct perf_sample *sample);
132 void *(*pointer)(struct tp_field *field, struct perf_sample *sample);
133 };
134};
135
136#define TP_UINT_FIELD(bits) \
137static u64 tp_field__u##bits(struct tp_field *field, struct perf_sample *sample) \
138{ \
David Ahern55d43bca2015-02-19 15:00:22 -0500139 u##bits value; \
140 memcpy(&value, sample->raw_data + field->offset, sizeof(value)); \
141 return value; \
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300142}
143
144TP_UINT_FIELD(8);
145TP_UINT_FIELD(16);
146TP_UINT_FIELD(32);
147TP_UINT_FIELD(64);
148
149#define TP_UINT_FIELD__SWAPPED(bits) \
150static u64 tp_field__swapped_u##bits(struct tp_field *field, struct perf_sample *sample) \
151{ \
David Ahern55d43bca2015-02-19 15:00:22 -0500152 u##bits value; \
153 memcpy(&value, sample->raw_data + field->offset, sizeof(value)); \
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300154 return bswap_##bits(value);\
155}
156
157TP_UINT_FIELD__SWAPPED(16);
158TP_UINT_FIELD__SWAPPED(32);
159TP_UINT_FIELD__SWAPPED(64);
160
161static int tp_field__init_uint(struct tp_field *field,
162 struct format_field *format_field,
163 bool needs_swap)
164{
165 field->offset = format_field->offset;
166
167 switch (format_field->size) {
168 case 1:
169 field->integer = tp_field__u8;
170 break;
171 case 2:
172 field->integer = needs_swap ? tp_field__swapped_u16 : tp_field__u16;
173 break;
174 case 4:
175 field->integer = needs_swap ? tp_field__swapped_u32 : tp_field__u32;
176 break;
177 case 8:
178 field->integer = needs_swap ? tp_field__swapped_u64 : tp_field__u64;
179 break;
180 default:
181 return -1;
182 }
183
184 return 0;
185}
186
187static void *tp_field__ptr(struct tp_field *field, struct perf_sample *sample)
188{
189 return sample->raw_data + field->offset;
190}
191
192static int tp_field__init_ptr(struct tp_field *field, struct format_field *format_field)
193{
194 field->offset = format_field->offset;
195 field->pointer = tp_field__ptr;
196 return 0;
197}
198
199struct syscall_tp {
200 struct tp_field id;
201 union {
202 struct tp_field args, ret;
203 };
204};
205
206static int perf_evsel__init_tp_uint_field(struct perf_evsel *evsel,
207 struct tp_field *field,
208 const char *name)
209{
210 struct format_field *format_field = perf_evsel__field(evsel, name);
211
212 if (format_field == NULL)
213 return -1;
214
215 return tp_field__init_uint(field, format_field, evsel->needs_swap);
216}
217
218#define perf_evsel__init_sc_tp_uint_field(evsel, name) \
219 ({ struct syscall_tp *sc = evsel->priv;\
220 perf_evsel__init_tp_uint_field(evsel, &sc->name, #name); })
221
222static int perf_evsel__init_tp_ptr_field(struct perf_evsel *evsel,
223 struct tp_field *field,
224 const char *name)
225{
226 struct format_field *format_field = perf_evsel__field(evsel, name);
227
228 if (format_field == NULL)
229 return -1;
230
231 return tp_field__init_ptr(field, format_field);
232}
233
234#define perf_evsel__init_sc_tp_ptr_field(evsel, name) \
235 ({ struct syscall_tp *sc = evsel->priv;\
236 perf_evsel__init_tp_ptr_field(evsel, &sc->name, #name); })
237
238static void perf_evsel__delete_priv(struct perf_evsel *evsel)
239{
Arnaldo Carvalho de Melo04662522013-12-26 17:41:15 -0300240 zfree(&evsel->priv);
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300241 perf_evsel__delete(evsel);
242}
243
Namhyung Kim96695d42013-11-12 08:51:45 -0300244static int perf_evsel__init_syscall_tp(struct perf_evsel *evsel, void *handler)
245{
246 evsel->priv = malloc(sizeof(struct syscall_tp));
247 if (evsel->priv != NULL) {
248 if (perf_evsel__init_sc_tp_uint_field(evsel, id))
249 goto out_delete;
250
251 evsel->handler = handler;
252 return 0;
253 }
254
255 return -ENOMEM;
256
257out_delete:
Arnaldo Carvalho de Melo04662522013-12-26 17:41:15 -0300258 zfree(&evsel->priv);
Namhyung Kim96695d42013-11-12 08:51:45 -0300259 return -ENOENT;
260}
261
Arnaldo Carvalho de Meloef503832013-11-07 16:41:19 -0300262static struct perf_evsel *perf_evsel__syscall_newtp(const char *direction, void *handler)
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300263{
Arnaldo Carvalho de Meloef503832013-11-07 16:41:19 -0300264 struct perf_evsel *evsel = perf_evsel__newtp("raw_syscalls", direction);
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300265
David Ahern9aca7f12013-12-04 19:41:39 -0700266 /* older kernel (e.g., RHEL6) use syscalls:{enter,exit} */
Jiri Olsa8dd2a132015-09-07 10:38:06 +0200267 if (IS_ERR(evsel))
David Ahern9aca7f12013-12-04 19:41:39 -0700268 evsel = perf_evsel__newtp("syscalls", direction);
269
Jiri Olsa8dd2a132015-09-07 10:38:06 +0200270 if (IS_ERR(evsel))
271 return NULL;
272
273 if (perf_evsel__init_syscall_tp(evsel, handler))
274 goto out_delete;
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300275
276 return evsel;
277
278out_delete:
279 perf_evsel__delete_priv(evsel);
280 return NULL;
281}
282
283#define perf_evsel__sc_tp_uint(evsel, name, sample) \
284 ({ struct syscall_tp *fields = evsel->priv; \
285 fields->name.integer(&fields->name, sample); })
286
287#define perf_evsel__sc_tp_ptr(evsel, name, sample) \
288 ({ struct syscall_tp *fields = evsel->priv; \
289 fields->name.pointer(&fields->name, sample); })
290
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300291struct syscall_arg {
292 unsigned long val;
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300293 struct thread *thread;
294 struct trace *trace;
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300295 void *parm;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300296 u8 idx;
297 u8 mask;
298};
299
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300300struct strarray {
Arnaldo Carvalho de Melo03e3adc2013-10-08 16:00:21 -0300301 int offset;
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300302 int nr_entries;
303 const char **entries;
304};
305
306#define DEFINE_STRARRAY(array) struct strarray strarray__##array = { \
307 .nr_entries = ARRAY_SIZE(array), \
308 .entries = array, \
309}
310
Arnaldo Carvalho de Melo03e3adc2013-10-08 16:00:21 -0300311#define DEFINE_STRARRAY_OFFSET(array, off) struct strarray strarray__##array = { \
312 .offset = off, \
313 .nr_entries = ARRAY_SIZE(array), \
314 .entries = array, \
315}
316
Arnaldo Carvalho de Melo975b7c22013-10-08 17:17:43 -0300317static size_t __syscall_arg__scnprintf_strarray(char *bf, size_t size,
318 const char *intfmt,
319 struct syscall_arg *arg)
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300320{
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300321 struct strarray *sa = arg->parm;
Arnaldo Carvalho de Melo03e3adc2013-10-08 16:00:21 -0300322 int idx = arg->val - sa->offset;
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300323
324 if (idx < 0 || idx >= sa->nr_entries)
Arnaldo Carvalho de Melo975b7c22013-10-08 17:17:43 -0300325 return scnprintf(bf, size, intfmt, arg->val);
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300326
327 return scnprintf(bf, size, "%s", sa->entries[idx]);
328}
329
Arnaldo Carvalho de Melo975b7c22013-10-08 17:17:43 -0300330static size_t syscall_arg__scnprintf_strarray(char *bf, size_t size,
331 struct syscall_arg *arg)
332{
333 return __syscall_arg__scnprintf_strarray(bf, size, "%d", arg);
334}
335
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300336#define SCA_STRARRAY syscall_arg__scnprintf_strarray
337
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -0300338#if defined(__i386__) || defined(__x86_64__)
339/*
340 * FIXME: Make this available to all arches as soon as the ioctl beautifier
341 * gets rewritten to support all arches.
342 */
Arnaldo Carvalho de Melo78645cf2013-10-08 17:43:20 -0300343static size_t syscall_arg__scnprintf_strhexarray(char *bf, size_t size,
344 struct syscall_arg *arg)
345{
346 return __syscall_arg__scnprintf_strarray(bf, size, "%#x", arg);
347}
348
349#define SCA_STRHEXARRAY syscall_arg__scnprintf_strhexarray
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -0300350#endif /* defined(__i386__) || defined(__x86_64__) */
Arnaldo Carvalho de Melo78645cf2013-10-08 17:43:20 -0300351
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300352static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
353 struct syscall_arg *arg);
354
355#define SCA_FD syscall_arg__scnprintf_fd
356
357static size_t syscall_arg__scnprintf_fd_at(char *bf, size_t size,
358 struct syscall_arg *arg)
359{
360 int fd = arg->val;
361
362 if (fd == AT_FDCWD)
363 return scnprintf(bf, size, "CWD");
364
365 return syscall_arg__scnprintf_fd(bf, size, arg);
366}
367
368#define SCA_FDAT syscall_arg__scnprintf_fd_at
369
370static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
371 struct syscall_arg *arg);
372
373#define SCA_CLOSE_FD syscall_arg__scnprintf_close_fd
374
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -0300375static size_t syscall_arg__scnprintf_hex(char *bf, size_t size,
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300376 struct syscall_arg *arg)
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -0300377{
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300378 return scnprintf(bf, size, "%#lx", arg->val);
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -0300379}
380
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -0300381#define SCA_HEX syscall_arg__scnprintf_hex
382
Arnaldo Carvalho de Meloa1c25522015-06-11 22:47:54 -0300383static size_t syscall_arg__scnprintf_int(char *bf, size_t size,
384 struct syscall_arg *arg)
385{
386 return scnprintf(bf, size, "%d", arg->val);
387}
388
389#define SCA_INT syscall_arg__scnprintf_int
390
Arnaldo Carvalho de Melo5cea6ff2013-09-20 11:49:50 -0300391static size_t syscall_arg__scnprintf_flock(char *bf, size_t size,
392 struct syscall_arg *arg)
393{
394 int printed = 0, op = arg->val;
395
396 if (op == 0)
397 return scnprintf(bf, size, "NONE");
398#define P_CMD(cmd) \
399 if ((op & LOCK_##cmd) == LOCK_##cmd) { \
400 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #cmd); \
401 op &= ~LOCK_##cmd; \
402 }
403
404 P_CMD(SH);
405 P_CMD(EX);
406 P_CMD(NB);
407 P_CMD(UN);
408 P_CMD(MAND);
409 P_CMD(RW);
410 P_CMD(READ);
411 P_CMD(WRITE);
412#undef P_OP
413
414 if (op)
415 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", op);
416
417 return printed;
418}
419
420#define SCA_FLOCK syscall_arg__scnprintf_flock
421
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300422static 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 -0300423{
424 enum syscall_futex_args {
425 SCF_UADDR = (1 << 0),
426 SCF_OP = (1 << 1),
427 SCF_VAL = (1 << 2),
428 SCF_TIMEOUT = (1 << 3),
429 SCF_UADDR2 = (1 << 4),
430 SCF_VAL3 = (1 << 5),
431 };
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300432 int op = arg->val;
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -0300433 int cmd = op & FUTEX_CMD_MASK;
434 size_t printed = 0;
435
436 switch (cmd) {
437#define P_FUTEX_OP(n) case FUTEX_##n: printed = scnprintf(bf, size, #n);
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300438 P_FUTEX_OP(WAIT); arg->mask |= SCF_VAL3|SCF_UADDR2; break;
439 P_FUTEX_OP(WAKE); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
440 P_FUTEX_OP(FD); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
441 P_FUTEX_OP(REQUEUE); arg->mask |= SCF_VAL3|SCF_TIMEOUT; break;
442 P_FUTEX_OP(CMP_REQUEUE); arg->mask |= SCF_TIMEOUT; break;
443 P_FUTEX_OP(CMP_REQUEUE_PI); arg->mask |= SCF_TIMEOUT; break;
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -0300444 P_FUTEX_OP(WAKE_OP); break;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300445 P_FUTEX_OP(LOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
446 P_FUTEX_OP(UNLOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
447 P_FUTEX_OP(TRYLOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2; break;
448 P_FUTEX_OP(WAIT_BITSET); arg->mask |= SCF_UADDR2; break;
449 P_FUTEX_OP(WAKE_BITSET); arg->mask |= SCF_UADDR2; break;
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -0300450 P_FUTEX_OP(WAIT_REQUEUE_PI); break;
451 default: printed = scnprintf(bf, size, "%#x", cmd); break;
452 }
453
454 if (op & FUTEX_PRIVATE_FLAG)
455 printed += scnprintf(bf + printed, size - printed, "|PRIV");
456
457 if (op & FUTEX_CLOCK_REALTIME)
458 printed += scnprintf(bf + printed, size - printed, "|CLKRT");
459
460 return printed;
461}
462
Arnaldo Carvalho de Meloefe6b882013-09-03 16:15:12 -0300463#define SCA_FUTEX_OP syscall_arg__scnprintf_futex_op
464
Arnaldo Carvalho de Melo729a7842015-10-29 11:48:18 -0300465static const char *bpf_cmd[] = {
466 "MAP_CREATE", "MAP_LOOKUP_ELEM", "MAP_UPDATE_ELEM", "MAP_DELETE_ELEM",
467 "MAP_GET_NEXT_KEY", "PROG_LOAD",
468};
469static DEFINE_STRARRAY(bpf_cmd);
470
Arnaldo Carvalho de Melo03e3adc2013-10-08 16:00:21 -0300471static const char *epoll_ctl_ops[] = { "ADD", "DEL", "MOD", };
472static DEFINE_STRARRAY_OFFSET(epoll_ctl_ops, 1);
Arnaldo Carvalho de Meloeac032c2013-09-20 11:27:32 -0300473
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300474static const char *itimers[] = { "REAL", "VIRTUAL", "PROF", };
475static DEFINE_STRARRAY(itimers);
476
Arnaldo Carvalho de Melob62bee12015-08-11 11:05:36 -0300477static const char *keyctl_options[] = {
478 "GET_KEYRING_ID", "JOIN_SESSION_KEYRING", "UPDATE", "REVOKE", "CHOWN",
479 "SETPERM", "DESCRIBE", "CLEAR", "LINK", "UNLINK", "SEARCH", "READ",
480 "INSTANTIATE", "NEGATE", "SET_REQKEY_KEYRING", "SET_TIMEOUT",
481 "ASSUME_AUTHORITY", "GET_SECURITY", "SESSION_TO_PARENT", "REJECT",
482 "INSTANTIATE_IOV", "INVALIDATE", "GET_PERSISTENT",
483};
484static DEFINE_STRARRAY(keyctl_options);
485
Arnaldo Carvalho de Meloefe6b882013-09-03 16:15:12 -0300486static const char *whences[] = { "SET", "CUR", "END",
487#ifdef SEEK_DATA
488"DATA",
489#endif
490#ifdef SEEK_HOLE
491"HOLE",
492#endif
493};
494static DEFINE_STRARRAY(whences);
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -0300495
Arnaldo Carvalho de Melo80f587d2013-09-03 16:28:58 -0300496static const char *fcntl_cmds[] = {
497 "DUPFD", "GETFD", "SETFD", "GETFL", "SETFL", "GETLK", "SETLK",
498 "SETLKW", "SETOWN", "GETOWN", "SETSIG", "GETSIG", "F_GETLK64",
499 "F_SETLK64", "F_SETLKW64", "F_SETOWN_EX", "F_GETOWN_EX",
500 "F_GETOWNER_UIDS",
501};
502static DEFINE_STRARRAY(fcntl_cmds);
503
Arnaldo Carvalho de Meloc045bf02013-09-04 11:52:33 -0300504static const char *rlimit_resources[] = {
505 "CPU", "FSIZE", "DATA", "STACK", "CORE", "RSS", "NPROC", "NOFILE",
506 "MEMLOCK", "AS", "LOCKS", "SIGPENDING", "MSGQUEUE", "NICE", "RTPRIO",
507 "RTTIME",
508};
509static DEFINE_STRARRAY(rlimit_resources);
510
Arnaldo Carvalho de Meloeb5b1b12013-09-03 16:37:46 -0300511static const char *sighow[] = { "BLOCK", "UNBLOCK", "SETMASK", };
512static DEFINE_STRARRAY(sighow);
513
David Ahern4f8c1b72013-09-22 19:45:00 -0600514static const char *clockid[] = {
515 "REALTIME", "MONOTONIC", "PROCESS_CPUTIME_ID", "THREAD_CPUTIME_ID",
Arnaldo Carvalho de Melo28ebb872015-08-11 10:38:38 -0300516 "MONOTONIC_RAW", "REALTIME_COARSE", "MONOTONIC_COARSE", "BOOTTIME",
517 "REALTIME_ALARM", "BOOTTIME_ALARM", "SGI_CYCLE", "TAI"
David Ahern4f8c1b72013-09-22 19:45:00 -0600518};
519static DEFINE_STRARRAY(clockid);
520
Arnaldo Carvalho de Meloe10bce82013-09-04 10:27:41 -0300521static const char *socket_families[] = {
522 "UNSPEC", "LOCAL", "INET", "AX25", "IPX", "APPLETALK", "NETROM",
523 "BRIDGE", "ATMPVC", "X25", "INET6", "ROSE", "DECnet", "NETBEUI",
524 "SECURITY", "KEY", "NETLINK", "PACKET", "ASH", "ECONET", "ATMSVC",
525 "RDS", "SNA", "IRDA", "PPPOX", "WANPIPE", "LLC", "IB", "CAN", "TIPC",
526 "BLUETOOTH", "IUCV", "RXRPC", "ISDN", "PHONET", "IEEE802154", "CAIF",
527 "ALG", "NFC", "VSOCK",
528};
529static DEFINE_STRARRAY(socket_families);
530
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -0300531#ifndef MSG_PROBE
532#define MSG_PROBE 0x10
533#endif
David Ahernb6e8f8f2013-09-22 19:44:56 -0600534#ifndef MSG_WAITFORONE
535#define MSG_WAITFORONE 0x10000
536#endif
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -0300537#ifndef MSG_SENDPAGE_NOTLAST
538#define MSG_SENDPAGE_NOTLAST 0x20000
539#endif
540#ifndef MSG_FASTOPEN
541#define MSG_FASTOPEN 0x20000000
542#endif
543
544static size_t syscall_arg__scnprintf_msg_flags(char *bf, size_t size,
545 struct syscall_arg *arg)
546{
547 int printed = 0, flags = arg->val;
548
549 if (flags == 0)
550 return scnprintf(bf, size, "NONE");
551#define P_MSG_FLAG(n) \
552 if (flags & MSG_##n) { \
553 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
554 flags &= ~MSG_##n; \
555 }
556
557 P_MSG_FLAG(OOB);
558 P_MSG_FLAG(PEEK);
559 P_MSG_FLAG(DONTROUTE);
560 P_MSG_FLAG(TRYHARD);
561 P_MSG_FLAG(CTRUNC);
562 P_MSG_FLAG(PROBE);
563 P_MSG_FLAG(TRUNC);
564 P_MSG_FLAG(DONTWAIT);
565 P_MSG_FLAG(EOR);
566 P_MSG_FLAG(WAITALL);
567 P_MSG_FLAG(FIN);
568 P_MSG_FLAG(SYN);
569 P_MSG_FLAG(CONFIRM);
570 P_MSG_FLAG(RST);
571 P_MSG_FLAG(ERRQUEUE);
572 P_MSG_FLAG(NOSIGNAL);
573 P_MSG_FLAG(MORE);
574 P_MSG_FLAG(WAITFORONE);
575 P_MSG_FLAG(SENDPAGE_NOTLAST);
576 P_MSG_FLAG(FASTOPEN);
577 P_MSG_FLAG(CMSG_CLOEXEC);
578#undef P_MSG_FLAG
579
580 if (flags)
581 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
582
583 return printed;
584}
585
586#define SCA_MSG_FLAGS syscall_arg__scnprintf_msg_flags
587
Arnaldo Carvalho de Melo51108992013-09-04 11:42:27 -0300588static size_t syscall_arg__scnprintf_access_mode(char *bf, size_t size,
589 struct syscall_arg *arg)
590{
591 size_t printed = 0;
592 int mode = arg->val;
593
594 if (mode == F_OK) /* 0 */
595 return scnprintf(bf, size, "F");
596#define P_MODE(n) \
597 if (mode & n##_OK) { \
598 printed += scnprintf(bf + printed, size - printed, "%s", #n); \
599 mode &= ~n##_OK; \
600 }
601
602 P_MODE(R);
603 P_MODE(W);
604 P_MODE(X);
605#undef P_MODE
606
607 if (mode)
608 printed += scnprintf(bf + printed, size - printed, "|%#x", mode);
609
610 return printed;
611}
612
613#define SCA_ACCMODE syscall_arg__scnprintf_access_mode
614
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -0300615static size_t syscall_arg__scnprintf_filename(char *bf, size_t size,
616 struct syscall_arg *arg);
617
618#define SCA_FILENAME syscall_arg__scnprintf_filename
619
Arnaldo Carvalho de Melobe65a892013-09-02 16:22:31 -0300620static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300621 struct syscall_arg *arg)
Arnaldo Carvalho de Melobe65a892013-09-02 16:22:31 -0300622{
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300623 int printed = 0, flags = arg->val;
Arnaldo Carvalho de Melobe65a892013-09-02 16:22:31 -0300624
625 if (!(flags & O_CREAT))
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300626 arg->mask |= 1 << (arg->idx + 1); /* Mask the mode parm */
Arnaldo Carvalho de Melobe65a892013-09-02 16:22:31 -0300627
628 if (flags == 0)
629 return scnprintf(bf, size, "RDONLY");
630#define P_FLAG(n) \
631 if (flags & O_##n) { \
632 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
633 flags &= ~O_##n; \
634 }
635
636 P_FLAG(APPEND);
637 P_FLAG(ASYNC);
638 P_FLAG(CLOEXEC);
639 P_FLAG(CREAT);
640 P_FLAG(DIRECT);
641 P_FLAG(DIRECTORY);
642 P_FLAG(EXCL);
643 P_FLAG(LARGEFILE);
644 P_FLAG(NOATIME);
645 P_FLAG(NOCTTY);
646#ifdef O_NONBLOCK
647 P_FLAG(NONBLOCK);
648#elif O_NDELAY
649 P_FLAG(NDELAY);
650#endif
651#ifdef O_PATH
652 P_FLAG(PATH);
653#endif
654 P_FLAG(RDWR);
655#ifdef O_DSYNC
656 if ((flags & O_SYNC) == O_SYNC)
657 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", "SYNC");
658 else {
659 P_FLAG(DSYNC);
660 }
661#else
662 P_FLAG(SYNC);
663#endif
664 P_FLAG(TRUNC);
665 P_FLAG(WRONLY);
666#undef P_FLAG
667
668 if (flags)
669 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
670
671 return printed;
672}
673
674#define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags
675
Arnaldo Carvalho de Meloa1c25522015-06-11 22:47:54 -0300676static size_t syscall_arg__scnprintf_perf_flags(char *bf, size_t size,
677 struct syscall_arg *arg)
678{
679 int printed = 0, flags = arg->val;
680
681 if (flags == 0)
682 return 0;
683
684#define P_FLAG(n) \
685 if (flags & PERF_FLAG_##n) { \
686 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
687 flags &= ~PERF_FLAG_##n; \
688 }
689
690 P_FLAG(FD_NO_GROUP);
691 P_FLAG(FD_OUTPUT);
692 P_FLAG(PID_CGROUP);
693 P_FLAG(FD_CLOEXEC);
694#undef P_FLAG
695
696 if (flags)
697 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
698
699 return printed;
700}
701
702#define SCA_PERF_FLAGS syscall_arg__scnprintf_perf_flags
703
Arnaldo Carvalho de Melo46cce192013-09-23 12:52:04 -0300704static size_t syscall_arg__scnprintf_pipe_flags(char *bf, size_t size,
705 struct syscall_arg *arg)
706{
707 int printed = 0, flags = arg->val;
708
709#define P_FLAG(n) \
710 if (flags & O_##n) { \
711 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
712 flags &= ~O_##n; \
713 }
714
715 P_FLAG(CLOEXEC);
716 P_FLAG(NONBLOCK);
717#undef P_FLAG
718
719 if (flags)
720 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
721
722 return printed;
723}
724
725#define SCA_PIPE_FLAGS syscall_arg__scnprintf_pipe_flags
726
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -0300727static size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscall_arg *arg)
728{
729 int sig = arg->val;
730
731 switch (sig) {
732#define P_SIGNUM(n) case SIG##n: return scnprintf(bf, size, #n)
733 P_SIGNUM(HUP);
734 P_SIGNUM(INT);
735 P_SIGNUM(QUIT);
736 P_SIGNUM(ILL);
737 P_SIGNUM(TRAP);
738 P_SIGNUM(ABRT);
739 P_SIGNUM(BUS);
740 P_SIGNUM(FPE);
741 P_SIGNUM(KILL);
742 P_SIGNUM(USR1);
743 P_SIGNUM(SEGV);
744 P_SIGNUM(USR2);
745 P_SIGNUM(PIPE);
746 P_SIGNUM(ALRM);
747 P_SIGNUM(TERM);
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -0300748 P_SIGNUM(CHLD);
749 P_SIGNUM(CONT);
750 P_SIGNUM(STOP);
751 P_SIGNUM(TSTP);
752 P_SIGNUM(TTIN);
753 P_SIGNUM(TTOU);
754 P_SIGNUM(URG);
755 P_SIGNUM(XCPU);
756 P_SIGNUM(XFSZ);
757 P_SIGNUM(VTALRM);
758 P_SIGNUM(PROF);
759 P_SIGNUM(WINCH);
760 P_SIGNUM(IO);
761 P_SIGNUM(PWR);
762 P_SIGNUM(SYS);
Ben Hutchings02c5bb42014-02-06 01:00:41 +0000763#ifdef SIGEMT
764 P_SIGNUM(EMT);
765#endif
766#ifdef SIGSTKFLT
767 P_SIGNUM(STKFLT);
768#endif
769#ifdef SIGSWI
770 P_SIGNUM(SWI);
771#endif
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -0300772 default: break;
773 }
774
775 return scnprintf(bf, size, "%#x", sig);
776}
777
778#define SCA_SIGNUM syscall_arg__scnprintf_signum
779
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -0300780#if defined(__i386__) || defined(__x86_64__)
781/*
782 * FIXME: Make this available to all arches.
783 */
Arnaldo Carvalho de Melo78645cf2013-10-08 17:43:20 -0300784#define TCGETS 0x5401
785
786static const char *tioctls[] = {
787 "TCGETS", "TCSETS", "TCSETSW", "TCSETSF", "TCGETA", "TCSETA", "TCSETAW",
788 "TCSETAF", "TCSBRK", "TCXONC", "TCFLSH", "TIOCEXCL", "TIOCNXCL",
789 "TIOCSCTTY", "TIOCGPGRP", "TIOCSPGRP", "TIOCOUTQ", "TIOCSTI",
790 "TIOCGWINSZ", "TIOCSWINSZ", "TIOCMGET", "TIOCMBIS", "TIOCMBIC",
791 "TIOCMSET", "TIOCGSOFTCAR", "TIOCSSOFTCAR", "FIONREAD", "TIOCLINUX",
792 "TIOCCONS", "TIOCGSERIAL", "TIOCSSERIAL", "TIOCPKT", "FIONBIO",
793 "TIOCNOTTY", "TIOCSETD", "TIOCGETD", "TCSBRKP", [0x27] = "TIOCSBRK",
794 "TIOCCBRK", "TIOCGSID", "TCGETS2", "TCSETS2", "TCSETSW2", "TCSETSF2",
795 "TIOCGRS485", "TIOCSRS485", "TIOCGPTN", "TIOCSPTLCK",
796 "TIOCGDEV||TCGETX", "TCSETX", "TCSETXF", "TCSETXW", "TIOCSIG",
797 "TIOCVHANGUP", "TIOCGPKT", "TIOCGPTLCK", "TIOCGEXCL",
798 [0x50] = "FIONCLEX", "FIOCLEX", "FIOASYNC", "TIOCSERCONFIG",
799 "TIOCSERGWILD", "TIOCSERSWILD", "TIOCGLCKTRMIOS", "TIOCSLCKTRMIOS",
800 "TIOCSERGSTRUCT", "TIOCSERGETLSR", "TIOCSERGETMULTI", "TIOCSERSETMULTI",
801 "TIOCMIWAIT", "TIOCGICOUNT", [0x60] = "FIOQSIZE",
802};
803
804static DEFINE_STRARRAY_OFFSET(tioctls, 0x5401);
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -0300805#endif /* defined(__i386__) || defined(__x86_64__) */
Arnaldo Carvalho de Melo78645cf2013-10-08 17:43:20 -0300806
Arnaldo Carvalho de Melo6fb35b92016-04-13 11:50:23 -0300807#ifndef SECCOMP_SET_MODE_STRICT
808#define SECCOMP_SET_MODE_STRICT 0
809#endif
810#ifndef SECCOMP_SET_MODE_FILTER
811#define SECCOMP_SET_MODE_FILTER 1
812#endif
813
Arnaldo Carvalho de Melo997bba82016-03-30 19:43:32 -0300814static size_t syscall_arg__scnprintf_seccomp_op(char *bf, size_t size, struct syscall_arg *arg)
815{
816 int op = arg->val;
817 size_t printed = 0;
818
819 switch (op) {
820#define P_SECCOMP_SET_MODE_OP(n) case SECCOMP_SET_MODE_##n: printed = scnprintf(bf, size, #n); break
821 P_SECCOMP_SET_MODE_OP(STRICT);
822 P_SECCOMP_SET_MODE_OP(FILTER);
823#undef P_SECCOMP_SET_MODE_OP
824 default: printed = scnprintf(bf, size, "%#x", op); break;
825 }
826
827 return printed;
828}
829
830#define SCA_SECCOMP_OP syscall_arg__scnprintf_seccomp_op
831
Arnaldo Carvalho de Melo6fb35b92016-04-13 11:50:23 -0300832#ifndef SECCOMP_FILTER_FLAG_TSYNC
833#define SECCOMP_FILTER_FLAG_TSYNC 1
834#endif
835
Arnaldo Carvalho de Melo997bba82016-03-30 19:43:32 -0300836static size_t syscall_arg__scnprintf_seccomp_flags(char *bf, size_t size,
837 struct syscall_arg *arg)
838{
839 int printed = 0, flags = arg->val;
840
841#define P_FLAG(n) \
842 if (flags & SECCOMP_FILTER_FLAG_##n) { \
843 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
844 flags &= ~SECCOMP_FILTER_FLAG_##n; \
845 }
846
847 P_FLAG(TSYNC);
848#undef P_FLAG
849
850 if (flags)
851 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
852
853 return printed;
854}
855
856#define SCA_SECCOMP_FLAGS syscall_arg__scnprintf_seccomp_flags
857
Arnaldo Carvalho de Meloa355a612016-04-13 11:55:18 -0300858#ifndef GRND_NONBLOCK
859#define GRND_NONBLOCK 0x0001
860#endif
861#ifndef GRND_RANDOM
862#define GRND_RANDOM 0x0002
863#endif
864
Arnaldo Carvalho de Melo39878d42016-03-30 20:02:15 -0300865static size_t syscall_arg__scnprintf_getrandom_flags(char *bf, size_t size,
866 struct syscall_arg *arg)
867{
868 int printed = 0, flags = arg->val;
869
870#define P_FLAG(n) \
871 if (flags & GRND_##n) { \
872 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
873 flags &= ~GRND_##n; \
874 }
875
876 P_FLAG(RANDOM);
877 P_FLAG(NONBLOCK);
878#undef P_FLAG
879
880 if (flags)
881 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
882
883 return printed;
884}
885
886#define SCA_GETRANDOM_FLAGS syscall_arg__scnprintf_getrandom_flags
887
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300888#define STRARRAY(arg, name, array) \
889 .arg_scnprintf = { [arg] = SCA_STRARRAY, }, \
890 .arg_parm = { [arg] = &strarray__##array, }
891
Arnaldo Carvalho de Meloea8dc3c2016-04-13 12:10:19 -0300892#include "trace/beauty/eventfd.c"
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -0300893#include "trace/beauty/pid.c"
Arnaldo Carvalho de Melodf4cb162016-04-13 12:05:44 -0300894#include "trace/beauty/mmap.c"
Arnaldo Carvalho de Meloba2f22c2016-04-07 12:05:51 -0300895#include "trace/beauty/mode_t.c"
Arnaldo Carvalho de Meloa3bca912016-04-06 12:51:33 -0300896#include "trace/beauty/sched_policy.c"
Arnaldo Carvalho de Melobbf86c42016-04-14 13:53:10 -0300897#include "trace/beauty/socket_type.c"
Arnaldo Carvalho de Melo7206b902016-04-06 14:11:36 -0300898#include "trace/beauty/waitid_options.c"
Arnaldo Carvalho de Meloa3bca912016-04-06 12:51:33 -0300899
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300900static struct syscall_fmt {
901 const char *name;
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -0300902 const char *alias;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300903 size_t (*arg_scnprintf[6])(char *bf, size_t size, struct syscall_arg *arg);
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300904 void *arg_parm[6];
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300905 bool errmsg;
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -0300906 bool errpid;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300907 bool timeout;
Arnaldo Carvalho de Melo04b34722013-08-26 11:36:30 -0300908 bool hexret;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300909} syscall_fmts[] = {
Arnaldo Carvalho de Melo51108992013-09-04 11:42:27 -0300910 { .name = "access", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300911 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */
912 [1] = SCA_ACCMODE, /* mode */ }, },
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -0300913 { .name = "arch_prctl", .errmsg = true, .alias = "prctl", },
Arnaldo Carvalho de Melo729a7842015-10-29 11:48:18 -0300914 { .name = "bpf", .errmsg = true, STRARRAY(0, cmd, bpf_cmd), },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -0300915 { .name = "brk", .hexret = true,
916 .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300917 { .name = "chdir", .errmsg = true,
918 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
919 { .name = "chmod", .errmsg = true,
920 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
921 { .name = "chroot", .errmsg = true,
922 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
David Ahern4f8c1b72013-09-22 19:45:00 -0600923 { .name = "clock_gettime", .errmsg = true, STRARRAY(0, clk_id, clockid), },
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -0300924 { .name = "clone", .errpid = true, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300925 { .name = "close", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300926 .arg_scnprintf = { [0] = SCA_CLOSE_FD, /* fd */ }, },
Arnaldo Carvalho de Meloa14bb862013-07-30 16:38:23 -0300927 { .name = "connect", .errmsg = true, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300928 { .name = "creat", .errmsg = true,
929 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300930 { .name = "dup", .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 = "dup2", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300933 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300934 { .name = "dup3", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300935 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300936 { .name = "epoll_ctl", .errmsg = true, STRARRAY(1, op, epoll_ctl_ops), },
Arnaldo Carvalho de Melo49af9e92013-09-12 12:18:56 -0300937 { .name = "eventfd2", .errmsg = true,
938 .arg_scnprintf = { [1] = SCA_EFD_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300939 { .name = "faccessat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300940 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
941 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300942 { .name = "fadvise64", .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 = "fallocate", .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 = "fchdir", .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 = "fchmod", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300949 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300950 { .name = "fchmodat", .errmsg = true,
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -0300951 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */
952 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300953 { .name = "fchown", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300954 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300955 { .name = "fchownat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300956 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */
957 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300958 { .name = "fcntl", .errmsg = true,
959 .arg_scnprintf = { [0] = SCA_FD, /* fd */
960 [1] = SCA_STRARRAY, /* cmd */ },
961 .arg_parm = { [1] = &strarray__fcntl_cmds, /* cmd */ }, },
962 { .name = "fdatasync", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300963 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo5cea6ff2013-09-20 11:49:50 -0300964 { .name = "flock", .errmsg = true,
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300965 .arg_scnprintf = { [0] = SCA_FD, /* fd */
966 [1] = SCA_FLOCK, /* cmd */ }, },
967 { .name = "fsetxattr", .errmsg = true,
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 = "fstat", .errmsg = true, .alias = "newfstat",
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300970 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300971 { .name = "fstatat", .errmsg = true, .alias = "newfstatat",
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300972 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
973 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300974 { .name = "fstatfs", .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 = "fsync", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300977 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300978 { .name = "ftruncate", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300979 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -0300980 { .name = "futex", .errmsg = true,
981 .arg_scnprintf = { [1] = SCA_FUTEX_OP, /* op */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300982 { .name = "futimesat", .errmsg = true,
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -0300983 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */
984 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300985 { .name = "getdents", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300986 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300987 { .name = "getdents64", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300988 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300989 { .name = "getitimer", .errmsg = true, STRARRAY(0, which, itimers), },
Arnaldo Carvalho de Meloc65f1072016-04-06 14:55:18 -0300990 { .name = "getpid", .errpid = true, },
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -0300991 { .name = "getpgid", .errpid = true, },
Arnaldo Carvalho de Meloc65f1072016-04-06 14:55:18 -0300992 { .name = "getppid", .errpid = true, },
Arnaldo Carvalho de Melo39878d42016-03-30 20:02:15 -0300993 { .name = "getrandom", .errmsg = true,
994 .arg_scnprintf = { [2] = SCA_GETRANDOM_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300995 { .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300996 { .name = "getxattr", .errmsg = true,
997 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
998 { .name = "inotify_add_watch", .errmsg = true,
999 .arg_scnprintf = { [1] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -03001000 { .name = "ioctl", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001001 .arg_scnprintf = { [0] = SCA_FD, /* fd */
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -03001002#if defined(__i386__) || defined(__x86_64__)
1003/*
1004 * FIXME: Make this available to all arches.
1005 */
Arnaldo Carvalho de Melo78645cf2013-10-08 17:43:20 -03001006 [1] = SCA_STRHEXARRAY, /* cmd */
1007 [2] = SCA_HEX, /* arg */ },
1008 .arg_parm = { [1] = &strarray__tioctls, /* cmd */ }, },
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -03001009#else
1010 [2] = SCA_HEX, /* arg */ }, },
1011#endif
Arnaldo Carvalho de Melob62bee12015-08-11 11:05:36 -03001012 { .name = "keyctl", .errmsg = true, STRARRAY(0, option, keyctl_options), },
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -03001013 { .name = "kill", .errmsg = true,
1014 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001015 { .name = "lchown", .errmsg = true,
1016 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
1017 { .name = "lgetxattr", .errmsg = true,
1018 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001019 { .name = "linkat", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001020 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001021 { .name = "listxattr", .errmsg = true,
1022 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -03001023 { .name = "llistxattr", .errmsg = true,
1024 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
1025 { .name = "lremovexattr", .errmsg = true,
1026 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001027 { .name = "lseek", .errmsg = true,
1028 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1029 [2] = SCA_STRARRAY, /* whence */ },
1030 .arg_parm = { [2] = &strarray__whences, /* whence */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001031 { .name = "lsetxattr", .errmsg = true,
1032 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -03001033 { .name = "lstat", .errmsg = true, .alias = "newlstat",
1034 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001035 { .name = "lsxattr", .errmsg = true,
1036 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo9e9716d2013-08-23 10:06:41 -03001037 { .name = "madvise", .errmsg = true,
1038 .arg_scnprintf = { [0] = SCA_HEX, /* start */
1039 [2] = SCA_MADV_BHV, /* behavior */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001040 { .name = "mkdir", .errmsg = true,
1041 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001042 { .name = "mkdirat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001043 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */
1044 [1] = SCA_FILENAME, /* pathname */ }, },
1045 { .name = "mknod", .errmsg = true,
1046 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001047 { .name = "mknodat", .errmsg = true,
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -03001048 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */
1049 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo3d903aa2013-09-24 00:09:38 -03001050 { .name = "mlock", .errmsg = true,
1051 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
1052 { .name = "mlockall", .errmsg = true,
1053 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -03001054 { .name = "mmap", .hexret = true,
Arnaldo Carvalho de Meloae685382013-08-20 17:44:42 -03001055 .arg_scnprintf = { [0] = SCA_HEX, /* addr */
Arnaldo Carvalho de Melo941557e2013-08-23 10:48:33 -03001056 [2] = SCA_MMAP_PROT, /* prot */
Namhyung Kim73faab32013-11-12 15:24:59 +09001057 [3] = SCA_MMAP_FLAGS, /* flags */
1058 [4] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -03001059 { .name = "mprotect", .errmsg = true,
Arnaldo Carvalho de Meloae685382013-08-20 17:44:42 -03001060 .arg_scnprintf = { [0] = SCA_HEX, /* start */
1061 [2] = SCA_MMAP_PROT, /* prot */ }, },
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -03001062 { .name = "mq_unlink", .errmsg = true,
1063 .arg_scnprintf = { [0] = SCA_FILENAME, /* u_name */ }, },
Arnaldo Carvalho de Meloae685382013-08-20 17:44:42 -03001064 { .name = "mremap", .hexret = true,
1065 .arg_scnprintf = { [0] = SCA_HEX, /* addr */
Alex Snast86998dd2014-08-13 18:42:40 +03001066 [3] = SCA_MREMAP_FLAGS, /* flags */
Arnaldo Carvalho de Meloae685382013-08-20 17:44:42 -03001067 [4] = SCA_HEX, /* new_addr */ }, },
Arnaldo Carvalho de Melo3d903aa2013-09-24 00:09:38 -03001068 { .name = "munlock", .errmsg = true,
1069 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -03001070 { .name = "munmap", .errmsg = true,
1071 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001072 { .name = "name_to_handle_at", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001073 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001074 { .name = "newfstatat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001075 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
1076 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melobe65a892013-09-02 16:22:31 -03001077 { .name = "open", .errmsg = true,
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001078 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */
1079 [1] = SCA_OPEN_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo31cd3852013-09-02 16:40:40 -03001080 { .name = "open_by_handle_at", .errmsg = true,
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001081 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
1082 [2] = SCA_OPEN_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo31cd3852013-09-02 16:40:40 -03001083 { .name = "openat", .errmsg = true,
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001084 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001085 [1] = SCA_FILENAME, /* filename */
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001086 [2] = SCA_OPEN_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Meloa1c25522015-06-11 22:47:54 -03001087 { .name = "perf_event_open", .errmsg = true,
1088 .arg_scnprintf = { [1] = SCA_INT, /* pid */
1089 [2] = SCA_INT, /* cpu */
1090 [3] = SCA_FD, /* group_fd */
1091 [4] = SCA_PERF_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo46cce192013-09-23 12:52:04 -03001092 { .name = "pipe2", .errmsg = true,
1093 .arg_scnprintf = { [1] = SCA_PIPE_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -03001094 { .name = "poll", .errmsg = true, .timeout = true, },
1095 { .name = "ppoll", .errmsg = true, .timeout = true, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001096 { .name = "pread", .errmsg = true, .alias = "pread64",
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001097 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001098 { .name = "preadv", .errmsg = true, .alias = "pread",
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001099 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -03001100 { .name = "prlimit64", .errmsg = true, STRARRAY(1, resource, rlimit_resources), },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001101 { .name = "pwrite", .errmsg = true, .alias = "pwrite64",
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 = "pwritev", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001104 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001105 { .name = "read", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001106 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001107 { .name = "readlink", .errmsg = true,
1108 .arg_scnprintf = { [0] = SCA_FILENAME, /* path */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001109 { .name = "readlinkat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001110 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
1111 [1] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001112 { .name = "readv", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001113 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -03001114 { .name = "recvfrom", .errmsg = true,
Arnaldo Carvalho de Melo8d8c66a2015-08-11 10:57:02 -03001115 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1116 [3] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -03001117 { .name = "recvmmsg", .errmsg = true,
Arnaldo Carvalho de Melo8d8c66a2015-08-11 10:57:02 -03001118 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1119 [3] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -03001120 { .name = "recvmsg", .errmsg = true,
Arnaldo Carvalho de Melo8d8c66a2015-08-11 10:57:02 -03001121 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1122 [2] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001123 { .name = "removexattr", .errmsg = true,
1124 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001125 { .name = "renameat", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001126 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001127 { .name = "rmdir", .errmsg = true,
1128 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -03001129 { .name = "rt_sigaction", .errmsg = true,
1130 .arg_scnprintf = { [0] = SCA_SIGNUM, /* sig */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -03001131 { .name = "rt_sigprocmask", .errmsg = true, STRARRAY(0, how, sighow), },
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -03001132 { .name = "rt_sigqueueinfo", .errmsg = true,
1133 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
1134 { .name = "rt_tgsigqueueinfo", .errmsg = true,
1135 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
Arnaldo Carvalho de Meloa3bca912016-04-06 12:51:33 -03001136 { .name = "sched_setscheduler", .errmsg = true,
1137 .arg_scnprintf = { [1] = SCA_SCHED_POLICY, /* policy */ }, },
Arnaldo Carvalho de Melo997bba82016-03-30 19:43:32 -03001138 { .name = "seccomp", .errmsg = true,
1139 .arg_scnprintf = { [0] = SCA_SECCOMP_OP, /* op */
1140 [1] = SCA_SECCOMP_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -03001141 { .name = "select", .errmsg = true, .timeout = true, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -03001142 { .name = "sendmmsg", .errmsg = true,
Arnaldo Carvalho de Melo8d8c66a2015-08-11 10:57:02 -03001143 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1144 [3] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -03001145 { .name = "sendmsg", .errmsg = true,
Arnaldo Carvalho de Melo8d8c66a2015-08-11 10:57:02 -03001146 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1147 [2] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -03001148 { .name = "sendto", .errmsg = true,
Arnaldo Carvalho de Melo8d8c66a2015-08-11 10:57:02 -03001149 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1150 [3] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Meloc65f1072016-04-06 14:55:18 -03001151 { .name = "set_tid_address", .errpid = true, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -03001152 { .name = "setitimer", .errmsg = true, STRARRAY(0, which, itimers), },
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -03001153 { .name = "setpgid", .errmsg = true, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -03001154 { .name = "setrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001155 { .name = "setxattr", .errmsg = true,
1156 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001157 { .name = "shutdown", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001158 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Meloe10bce82013-09-04 10:27:41 -03001159 { .name = "socket", .errmsg = true,
Arnaldo Carvalho de Meloa28b24b2013-09-04 11:00:44 -03001160 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
1161 [1] = SCA_SK_TYPE, /* type */ },
Arnaldo Carvalho de Meloe10bce82013-09-04 10:27:41 -03001162 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, },
Arnaldo Carvalho de Melo07120aa2013-09-20 12:24:20 -03001163 { .name = "socketpair", .errmsg = true,
1164 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
1165 [1] = SCA_SK_TYPE, /* type */ },
1166 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, },
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -03001167 { .name = "stat", .errmsg = true, .alias = "newstat",
1168 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001169 { .name = "statfs", .errmsg = true,
1170 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
1171 { .name = "swapoff", .errmsg = true,
1172 .arg_scnprintf = { [0] = SCA_FILENAME, /* specialfile */ }, },
1173 { .name = "swapon", .errmsg = true,
1174 .arg_scnprintf = { [0] = SCA_FILENAME, /* specialfile */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001175 { .name = "symlinkat", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001176 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -03001177 { .name = "tgkill", .errmsg = true,
1178 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
1179 { .name = "tkill", .errmsg = true,
1180 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001181 { .name = "truncate", .errmsg = true,
1182 .arg_scnprintf = { [0] = SCA_FILENAME, /* path */ }, },
Arnaldo Carvalho de Meloe5959682013-08-26 12:21:41 -03001183 { .name = "uname", .errmsg = true, .alias = "newuname", },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001184 { .name = "unlinkat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001185 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
1186 [1] = SCA_FILENAME, /* pathname */ }, },
1187 { .name = "utime", .errmsg = true,
1188 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001189 { .name = "utimensat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001190 .arg_scnprintf = { [0] = SCA_FDAT, /* dirfd */
1191 [1] = SCA_FILENAME, /* filename */ }, },
1192 { .name = "utimes", .errmsg = true,
1193 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -03001194 { .name = "vmsplice", .errmsg = true,
1195 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -03001196 { .name = "wait4", .errpid = true,
Arnaldo Carvalho de Melo7206b902016-04-06 14:11:36 -03001197 .arg_scnprintf = { [2] = SCA_WAITID_OPTIONS, /* options */ }, },
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -03001198 { .name = "waitid", .errpid = true,
Arnaldo Carvalho de Melo7206b902016-04-06 14:11:36 -03001199 .arg_scnprintf = { [3] = SCA_WAITID_OPTIONS, /* options */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001200 { .name = "write", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001201 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001202 { .name = "writev", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001203 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001204};
1205
1206static int syscall_fmt__cmp(const void *name, const void *fmtp)
1207{
1208 const struct syscall_fmt *fmt = fmtp;
1209 return strcmp(name, fmt->name);
1210}
1211
1212static struct syscall_fmt *syscall_fmt__find(const char *name)
1213{
1214 const int nmemb = ARRAY_SIZE(syscall_fmts);
1215 return bsearch(name, syscall_fmts, nmemb, sizeof(struct syscall_fmt), syscall_fmt__cmp);
1216}
1217
1218struct syscall {
1219 struct event_format *tp_format;
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001220 int nr_args;
1221 struct format_field *args;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001222 const char *name;
Arnaldo Carvalho de Melo5089f202014-06-17 14:29:24 -03001223 bool is_exit;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001224 struct syscall_fmt *fmt;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001225 size_t (**arg_scnprintf)(char *bf, size_t size, struct syscall_arg *arg);
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -03001226 void **arg_parm;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001227};
1228
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001229static size_t fprintf_duration(unsigned long t, FILE *fp)
1230{
1231 double duration = (double)t / NSEC_PER_MSEC;
1232 size_t printed = fprintf(fp, "(");
1233
1234 if (duration >= 1.0)
1235 printed += color_fprintf(fp, PERF_COLOR_RED, "%6.3f ms", duration);
1236 else if (duration >= 0.01)
1237 printed += color_fprintf(fp, PERF_COLOR_YELLOW, "%6.3f ms", duration);
1238 else
1239 printed += color_fprintf(fp, PERF_COLOR_NORMAL, "%6.3f ms", duration);
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001240 return printed + fprintf(fp, "): ");
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001241}
1242
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001243/**
1244 * filename.ptr: The filename char pointer that will be vfs_getname'd
1245 * filename.entry_str_pos: Where to insert the string translated from
1246 * filename.ptr by the vfs_getname tracepoint/kprobe.
1247 */
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001248struct thread_trace {
1249 u64 entry_time;
1250 u64 exit_time;
1251 bool entry_pending;
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03001252 unsigned long nr_events;
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04001253 unsigned long pfmaj, pfmin;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001254 char *entry_str;
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001255 double runtime_ms;
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001256 struct {
1257 unsigned long ptr;
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03001258 short int entry_str_pos;
1259 bool pending_open;
1260 unsigned int namelen;
1261 char *name;
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001262 } filename;
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001263 struct {
1264 int max;
1265 char **table;
1266 } paths;
David Ahernbf2575c2013-10-08 21:26:53 -06001267
1268 struct intlist *syscall_stats;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001269};
1270
1271static struct thread_trace *thread_trace__new(void)
1272{
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001273 struct thread_trace *ttrace = zalloc(sizeof(struct thread_trace));
1274
1275 if (ttrace)
1276 ttrace->paths.max = -1;
1277
David Ahernbf2575c2013-10-08 21:26:53 -06001278 ttrace->syscall_stats = intlist__new(NULL);
1279
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001280 return ttrace;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001281}
1282
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001283static struct thread_trace *thread__trace(struct thread *thread, FILE *fp)
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001284{
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03001285 struct thread_trace *ttrace;
1286
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001287 if (thread == NULL)
1288 goto fail;
1289
Namhyung Kim89dceb22014-10-06 09:46:03 +09001290 if (thread__priv(thread) == NULL)
1291 thread__set_priv(thread, thread_trace__new());
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001292
Namhyung Kim89dceb22014-10-06 09:46:03 +09001293 if (thread__priv(thread) == NULL)
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001294 goto fail;
1295
Namhyung Kim89dceb22014-10-06 09:46:03 +09001296 ttrace = thread__priv(thread);
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03001297 ++ttrace->nr_events;
1298
1299 return ttrace;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001300fail:
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001301 color_fprintf(fp, PERF_COLOR_RED,
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001302 "WARNING: not enough memory, dropping samples!\n");
1303 return NULL;
1304}
1305
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04001306#define TRACE_PFMAJ (1 << 0)
1307#define TRACE_PFMIN (1 << 1)
1308
Arnaldo Carvalho de Meloe4d44e82015-08-04 22:17:29 -03001309static const size_t trace__entry_str_size = 2048;
1310
Arnaldo Carvalho de Melo97119f32013-09-27 17:34:10 -03001311static int trace__set_fd_pathname(struct thread *thread, int fd, const char *pathname)
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001312{
Namhyung Kim89dceb22014-10-06 09:46:03 +09001313 struct thread_trace *ttrace = thread__priv(thread);
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001314
1315 if (fd > ttrace->paths.max) {
1316 char **npath = realloc(ttrace->paths.table, (fd + 1) * sizeof(char *));
1317
1318 if (npath == NULL)
1319 return -1;
1320
1321 if (ttrace->paths.max != -1) {
1322 memset(npath + ttrace->paths.max + 1, 0,
1323 (fd - ttrace->paths.max) * sizeof(char *));
1324 } else {
1325 memset(npath, 0, (fd + 1) * sizeof(char *));
1326 }
1327
1328 ttrace->paths.table = npath;
1329 ttrace->paths.max = fd;
1330 }
1331
1332 ttrace->paths.table[fd] = strdup(pathname);
1333
1334 return ttrace->paths.table[fd] != NULL ? 0 : -1;
1335}
1336
Arnaldo Carvalho de Melo97119f32013-09-27 17:34:10 -03001337static int thread__read_fd_path(struct thread *thread, int fd)
1338{
1339 char linkname[PATH_MAX], pathname[PATH_MAX];
1340 struct stat st;
1341 int ret;
1342
1343 if (thread->pid_ == thread->tid) {
1344 scnprintf(linkname, sizeof(linkname),
1345 "/proc/%d/fd/%d", thread->pid_, fd);
1346 } else {
1347 scnprintf(linkname, sizeof(linkname),
1348 "/proc/%d/task/%d/fd/%d", thread->pid_, thread->tid, fd);
1349 }
1350
1351 if (lstat(linkname, &st) < 0 || st.st_size + 1 > (off_t)sizeof(pathname))
1352 return -1;
1353
1354 ret = readlink(linkname, pathname, sizeof(pathname));
1355
1356 if (ret < 0 || ret > st.st_size)
1357 return -1;
1358
1359 pathname[ret] = '\0';
1360 return trace__set_fd_pathname(thread, fd, pathname);
1361}
1362
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001363static const char *thread__fd_path(struct thread *thread, int fd,
1364 struct trace *trace)
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001365{
Namhyung Kim89dceb22014-10-06 09:46:03 +09001366 struct thread_trace *ttrace = thread__priv(thread);
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001367
1368 if (ttrace == NULL)
1369 return NULL;
1370
1371 if (fd < 0)
1372 return NULL;
1373
Arnaldo Carvalho de Melocdcd1e62014-06-10 16:00:18 -03001374 if ((fd > ttrace->paths.max || ttrace->paths.table[fd] == NULL)) {
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001375 if (!trace->live)
1376 return NULL;
1377 ++trace->stats.proc_getname;
Arnaldo Carvalho de Melocdcd1e62014-06-10 16:00:18 -03001378 if (thread__read_fd_path(thread, fd))
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001379 return NULL;
1380 }
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001381
1382 return ttrace->paths.table[fd];
1383}
1384
1385static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
1386 struct syscall_arg *arg)
1387{
1388 int fd = arg->val;
1389 size_t printed = scnprintf(bf, size, "%d", fd);
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001390 const char *path = thread__fd_path(arg->thread, fd, arg->trace);
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001391
1392 if (path)
1393 printed += scnprintf(bf + printed, size - printed, "<%s>", path);
1394
1395 return printed;
1396}
1397
1398static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
1399 struct syscall_arg *arg)
1400{
1401 int fd = arg->val;
1402 size_t printed = syscall_arg__scnprintf_fd(bf, size, arg);
Namhyung Kim89dceb22014-10-06 09:46:03 +09001403 struct thread_trace *ttrace = thread__priv(arg->thread);
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001404
Arnaldo Carvalho de Melo04662522013-12-26 17:41:15 -03001405 if (ttrace && fd >= 0 && fd <= ttrace->paths.max)
1406 zfree(&ttrace->paths.table[fd]);
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001407
1408 return printed;
1409}
1410
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001411static void thread__set_filename_pos(struct thread *thread, const char *bf,
1412 unsigned long ptr)
1413{
1414 struct thread_trace *ttrace = thread__priv(thread);
1415
1416 ttrace->filename.ptr = ptr;
1417 ttrace->filename.entry_str_pos = bf - ttrace->entry_str;
1418}
1419
1420static size_t syscall_arg__scnprintf_filename(char *bf, size_t size,
1421 struct syscall_arg *arg)
1422{
1423 unsigned long ptr = arg->val;
1424
1425 if (!arg->trace->vfs_getname)
1426 return scnprintf(bf, size, "%#x", ptr);
1427
1428 thread__set_filename_pos(arg->thread, bf, ptr);
1429 return 0;
1430}
1431
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001432static bool trace__filter_duration(struct trace *trace, double t)
1433{
1434 return t < (trace->duration_filter * NSEC_PER_MSEC);
1435}
1436
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001437static size_t trace__fprintf_tstamp(struct trace *trace, u64 tstamp, FILE *fp)
1438{
1439 double ts = (double)(tstamp - trace->base_time) / NSEC_PER_MSEC;
1440
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001441 return fprintf(fp, "%10.3f ", ts);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001442}
1443
Namhyung Kimf15eb532012-10-05 14:02:16 +09001444static bool done = false;
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03001445static bool interrupted = false;
Namhyung Kimf15eb532012-10-05 14:02:16 +09001446
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03001447static void sig_handler(int sig)
Namhyung Kimf15eb532012-10-05 14:02:16 +09001448{
1449 done = true;
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03001450 interrupted = sig == SIGINT;
Namhyung Kimf15eb532012-10-05 14:02:16 +09001451}
1452
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001453static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thread,
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001454 u64 duration, u64 tstamp, FILE *fp)
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001455{
1456 size_t printed = trace__fprintf_tstamp(trace, tstamp, fp);
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001457 printed += fprintf_duration(duration, fp);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001458
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -03001459 if (trace->multiple_threads) {
1460 if (trace->show_comm)
Frederic Weisbecker1902efe2013-09-11 16:56:44 +02001461 printed += fprintf(fp, "%.14s/", thread__comm_str(thread));
Adrian Hunter38051232013-07-04 16:20:31 +03001462 printed += fprintf(fp, "%d ", thread->tid);
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -03001463 }
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001464
1465 return printed;
1466}
1467
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001468static int trace__process_event(struct trace *trace, struct machine *machine,
Frederic Weisbecker162f0be2013-09-11 16:18:24 +02001469 union perf_event *event, struct perf_sample *sample)
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001470{
1471 int ret = 0;
1472
1473 switch (event->header.type) {
1474 case PERF_RECORD_LOST:
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001475 color_fprintf(trace->output, PERF_COLOR_RED,
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001476 "LOST %" PRIu64 " events!\n", event->lost.lost);
Frederic Weisbecker162f0be2013-09-11 16:18:24 +02001477 ret = machine__process_lost_event(machine, event, sample);
Arnaldo Carvalho de Melo3ed5ca22016-03-30 16:51:17 -03001478 break;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001479 default:
Frederic Weisbecker162f0be2013-09-11 16:18:24 +02001480 ret = machine__process_event(machine, event, sample);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001481 break;
1482 }
1483
1484 return ret;
1485}
1486
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001487static int trace__tool_process(struct perf_tool *tool,
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001488 union perf_event *event,
Frederic Weisbecker162f0be2013-09-11 16:18:24 +02001489 struct perf_sample *sample,
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001490 struct machine *machine)
1491{
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001492 struct trace *trace = container_of(tool, struct trace, tool);
Frederic Weisbecker162f0be2013-09-11 16:18:24 +02001493 return trace__process_event(trace, machine, event, sample);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001494}
1495
1496static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
1497{
Namhyung Kim0a7e6d12014-08-12 15:40:45 +09001498 int err = symbol__init(NULL);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001499
1500 if (err)
1501 return err;
1502
David Ahern8fb598e2013-09-28 13:13:00 -06001503 trace->host = machine__new_host();
1504 if (trace->host == NULL)
1505 return -ENOMEM;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001506
Arnaldo Carvalho de Melo959c2192015-07-24 12:13:05 -03001507 if (trace_event__register_resolver(trace->host, machine__resolve_kernel_addr) < 0)
Arnaldo Carvalho de Melo706c3da2015-07-22 16:16:16 -03001508 return -errno;
1509
Arnaldo Carvalho de Meloa33fbd52013-11-11 11:36:12 -03001510 err = __machine__synthesize_threads(trace->host, &trace->tool, &trace->opts.target,
Kan Liang9d9cad72015-06-17 09:51:11 -04001511 evlist->threads, trace__tool_process, false,
1512 trace->opts.proc_map_timeout);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001513 if (err)
1514 symbol__exit();
1515
1516 return err;
1517}
1518
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001519static int syscall__set_arg_fmts(struct syscall *sc)
1520{
1521 struct format_field *field;
1522 int idx = 0;
1523
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001524 sc->arg_scnprintf = calloc(sc->nr_args, sizeof(void *));
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001525 if (sc->arg_scnprintf == NULL)
1526 return -1;
1527
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -03001528 if (sc->fmt)
1529 sc->arg_parm = sc->fmt->arg_parm;
1530
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001531 for (field = sc->args; field; field = field->next) {
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -03001532 if (sc->fmt && sc->fmt->arg_scnprintf[idx])
1533 sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx];
1534 else if (field->flags & FIELD_IS_POINTER)
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001535 sc->arg_scnprintf[idx] = syscall_arg__scnprintf_hex;
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -03001536 else if (strcmp(field->type, "pid_t") == 0)
1537 sc->arg_scnprintf[idx] = SCA_PID;
Arnaldo Carvalho de Meloba2f22c2016-04-07 12:05:51 -03001538 else if (strcmp(field->type, "umode_t") == 0)
1539 sc->arg_scnprintf[idx] = SCA_MODE_T;
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001540 ++idx;
1541 }
1542
1543 return 0;
1544}
1545
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001546static int trace__read_syscall_info(struct trace *trace, int id)
1547{
1548 char tp_name[128];
1549 struct syscall *sc;
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03001550 const char *name = syscalltbl__name(trace->sctbl, id);
Arnaldo Carvalho de Melo3a531262012-10-20 12:39:03 -03001551
1552 if (name == NULL)
1553 return -1;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001554
1555 if (id > trace->syscalls.max) {
1556 struct syscall *nsyscalls = realloc(trace->syscalls.table, (id + 1) * sizeof(*sc));
1557
1558 if (nsyscalls == NULL)
1559 return -1;
1560
1561 if (trace->syscalls.max != -1) {
1562 memset(nsyscalls + trace->syscalls.max + 1, 0,
1563 (id - trace->syscalls.max) * sizeof(*sc));
1564 } else {
1565 memset(nsyscalls, 0, (id + 1) * sizeof(*sc));
1566 }
1567
1568 trace->syscalls.table = nsyscalls;
1569 trace->syscalls.max = id;
1570 }
1571
1572 sc = trace->syscalls.table + id;
Arnaldo Carvalho de Melo3a531262012-10-20 12:39:03 -03001573 sc->name = name;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001574
Arnaldo Carvalho de Melo3a531262012-10-20 12:39:03 -03001575 sc->fmt = syscall_fmt__find(sc->name);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001576
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -03001577 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name);
Jiri Olsa97978b32013-12-03 14:09:24 +01001578 sc->tp_format = trace_event__tp_format("syscalls", tp_name);
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -03001579
Jiri Olsa8dd2a132015-09-07 10:38:06 +02001580 if (IS_ERR(sc->tp_format) && sc->fmt && sc->fmt->alias) {
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -03001581 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->fmt->alias);
Jiri Olsa97978b32013-12-03 14:09:24 +01001582 sc->tp_format = trace_event__tp_format("syscalls", tp_name);
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -03001583 }
1584
Jiri Olsa8dd2a132015-09-07 10:38:06 +02001585 if (IS_ERR(sc->tp_format))
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001586 return -1;
1587
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001588 sc->args = sc->tp_format->format.fields;
1589 sc->nr_args = sc->tp_format->format.nr_fields;
Taeung Songc42de702016-02-26 22:14:25 +09001590 /*
1591 * We need to check and discard the first variable '__syscall_nr'
1592 * or 'nr' that mean the syscall number. It is needless here.
1593 * So drop '__syscall_nr' or 'nr' field but does not exist on older kernels.
1594 */
1595 if (sc->args && (!strcmp(sc->args->name, "__syscall_nr") || !strcmp(sc->args->name, "nr"))) {
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001596 sc->args = sc->args->next;
1597 --sc->nr_args;
1598 }
1599
Arnaldo Carvalho de Melo5089f202014-06-17 14:29:24 -03001600 sc->is_exit = !strcmp(name, "exit_group") || !strcmp(name, "exit");
1601
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001602 return syscall__set_arg_fmts(sc);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001603}
1604
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001605static int trace__validate_ev_qualifier(struct trace *trace)
1606{
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001607 int err = 0, i;
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001608 struct str_node *pos;
1609
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001610 trace->ev_qualifier_ids.nr = strlist__nr_entries(trace->ev_qualifier);
1611 trace->ev_qualifier_ids.entries = malloc(trace->ev_qualifier_ids.nr *
1612 sizeof(trace->ev_qualifier_ids.entries[0]));
1613
1614 if (trace->ev_qualifier_ids.entries == NULL) {
1615 fputs("Error:\tNot enough memory for allocating events qualifier ids\n",
1616 trace->output);
1617 err = -EINVAL;
1618 goto out;
1619 }
1620
1621 i = 0;
1622
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001623 strlist__for_each(pos, trace->ev_qualifier) {
1624 const char *sc = pos->s;
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03001625 int id = syscalltbl__id(trace->sctbl, sc);
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001626
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001627 if (id < 0) {
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001628 if (err == 0) {
1629 fputs("Error:\tInvalid syscall ", trace->output);
1630 err = -EINVAL;
1631 } else {
1632 fputs(", ", trace->output);
1633 }
1634
1635 fputs(sc, trace->output);
1636 }
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001637
1638 trace->ev_qualifier_ids.entries[i++] = id;
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001639 }
1640
1641 if (err < 0) {
1642 fputs("\nHint:\ttry 'perf list syscalls:sys_enter_*'"
1643 "\nHint:\tand: 'man syscalls'\n", trace->output);
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001644 zfree(&trace->ev_qualifier_ids.entries);
1645 trace->ev_qualifier_ids.nr = 0;
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001646 }
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001647out:
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001648 return err;
1649}
1650
David Ahern55d43bca2015-02-19 15:00:22 -05001651/*
1652 * args is to be interpreted as a series of longs but we need to handle
1653 * 8-byte unaligned accesses. args points to raw_data within the event
1654 * and raw_data is guaranteed to be 8-byte unaligned because it is
1655 * preceded by raw_size which is a u32. So we need to copy args to a temp
1656 * variable to read it. Most notably this avoids extended load instructions
1657 * on unaligned addresses
1658 */
1659
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001660static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
David Ahern55d43bca2015-02-19 15:00:22 -05001661 unsigned char *args, struct trace *trace,
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001662 struct thread *thread)
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001663{
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001664 size_t printed = 0;
David Ahern55d43bca2015-02-19 15:00:22 -05001665 unsigned char *p;
1666 unsigned long val;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001667
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001668 if (sc->args != NULL) {
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001669 struct format_field *field;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001670 u8 bit = 1;
1671 struct syscall_arg arg = {
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001672 .idx = 0,
1673 .mask = 0,
1674 .trace = trace,
1675 .thread = thread,
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001676 };
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001677
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001678 for (field = sc->args; field;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001679 field = field->next, ++arg.idx, bit <<= 1) {
1680 if (arg.mask & bit)
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -03001681 continue;
David Ahern55d43bca2015-02-19 15:00:22 -05001682
1683 /* special care for unaligned accesses */
1684 p = args + sizeof(unsigned long) * arg.idx;
1685 memcpy(&val, p, sizeof(val));
1686
Arnaldo Carvalho de Melo4aa58232013-09-20 12:19:41 -03001687 /*
1688 * Suppress this argument if its value is zero and
1689 * and we don't have a string associated in an
1690 * strarray for it.
1691 */
David Ahern55d43bca2015-02-19 15:00:22 -05001692 if (val == 0 &&
Arnaldo Carvalho de Melo4aa58232013-09-20 12:19:41 -03001693 !(sc->arg_scnprintf &&
1694 sc->arg_scnprintf[arg.idx] == SCA_STRARRAY &&
1695 sc->arg_parm[arg.idx]))
Arnaldo Carvalho de Melo22ae5cf12013-09-12 11:27:34 -03001696 continue;
1697
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001698 printed += scnprintf(bf + printed, size - printed,
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001699 "%s%s: ", printed ? ", " : "", field->name);
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001700 if (sc->arg_scnprintf && sc->arg_scnprintf[arg.idx]) {
David Ahern55d43bca2015-02-19 15:00:22 -05001701 arg.val = val;
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -03001702 if (sc->arg_parm)
1703 arg.parm = sc->arg_parm[arg.idx];
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001704 printed += sc->arg_scnprintf[arg.idx](bf + printed,
1705 size - printed, &arg);
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -03001706 } else {
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001707 printed += scnprintf(bf + printed, size - printed,
David Ahern55d43bca2015-02-19 15:00:22 -05001708 "%ld", val);
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -03001709 }
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001710 }
1711 } else {
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001712 int i = 0;
1713
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001714 while (i < 6) {
David Ahern55d43bca2015-02-19 15:00:22 -05001715 /* special care for unaligned accesses */
1716 p = args + sizeof(unsigned long) * i;
1717 memcpy(&val, p, sizeof(val));
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001718 printed += scnprintf(bf + printed, size - printed,
1719 "%sarg%d: %ld",
David Ahern55d43bca2015-02-19 15:00:22 -05001720 printed ? ", " : "", i, val);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001721 ++i;
1722 }
1723 }
1724
1725 return printed;
1726}
1727
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001728typedef int (*tracepoint_handler)(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04001729 union perf_event *event,
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001730 struct perf_sample *sample);
1731
1732static struct syscall *trace__syscall_info(struct trace *trace,
David Ahernbf2575c2013-10-08 21:26:53 -06001733 struct perf_evsel *evsel, int id)
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001734{
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001735
1736 if (id < 0) {
Arnaldo Carvalho de Meloadaa18b2013-08-22 17:55:25 -03001737
1738 /*
1739 * XXX: Noticed on x86_64, reproduced as far back as 3.0.36, haven't tried
1740 * before that, leaving at a higher verbosity level till that is
1741 * explained. Reproduced with plain ftrace with:
1742 *
1743 * echo 1 > /t/events/raw_syscalls/sys_exit/enable
1744 * grep "NR -1 " /t/trace_pipe
1745 *
1746 * After generating some load on the machine.
1747 */
1748 if (verbose > 1) {
1749 static u64 n;
1750 fprintf(trace->output, "Invalid syscall %d id, skipping (%s, %" PRIu64 ") ...\n",
1751 id, perf_evsel__name(evsel), ++n);
1752 }
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001753 return NULL;
1754 }
1755
1756 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL) &&
1757 trace__read_syscall_info(trace, id))
1758 goto out_cant_read;
1759
1760 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL))
1761 goto out_cant_read;
1762
1763 return &trace->syscalls.table[id];
1764
1765out_cant_read:
Arnaldo Carvalho de Melo7c304ee02013-08-22 16:49:54 -03001766 if (verbose) {
1767 fprintf(trace->output, "Problems reading syscall %d", id);
1768 if (id <= trace->syscalls.max && trace->syscalls.table[id].name != NULL)
1769 fprintf(trace->output, "(%s)", trace->syscalls.table[id].name);
1770 fputs(" information\n", trace->output);
1771 }
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001772 return NULL;
1773}
1774
David Ahernbf2575c2013-10-08 21:26:53 -06001775static void thread__update_stats(struct thread_trace *ttrace,
1776 int id, struct perf_sample *sample)
1777{
1778 struct int_node *inode;
1779 struct stats *stats;
1780 u64 duration = 0;
1781
1782 inode = intlist__findnew(ttrace->syscall_stats, id);
1783 if (inode == NULL)
1784 return;
1785
1786 stats = inode->priv;
1787 if (stats == NULL) {
1788 stats = malloc(sizeof(struct stats));
1789 if (stats == NULL)
1790 return;
1791 init_stats(stats);
1792 inode->priv = stats;
1793 }
1794
1795 if (ttrace->entry_time && sample->time > ttrace->entry_time)
1796 duration = sample->time - ttrace->entry_time;
1797
1798 update_stats(stats, duration);
1799}
1800
Arnaldo Carvalho de Meloe5966632015-02-13 13:22:21 -03001801static int trace__printf_interrupted_entry(struct trace *trace, struct perf_sample *sample)
1802{
1803 struct thread_trace *ttrace;
1804 u64 duration;
1805 size_t printed;
1806
1807 if (trace->current == NULL)
1808 return 0;
1809
1810 ttrace = thread__priv(trace->current);
1811
1812 if (!ttrace->entry_pending)
1813 return 0;
1814
1815 duration = sample->time - ttrace->entry_time;
1816
1817 printed = trace__fprintf_entry_head(trace, trace->current, duration, sample->time, trace->output);
1818 printed += fprintf(trace->output, "%-70s) ...\n", ttrace->entry_str);
1819 ttrace->entry_pending = false;
1820
1821 return printed;
1822}
1823
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001824static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04001825 union perf_event *event __maybe_unused,
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001826 struct perf_sample *sample)
1827{
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001828 char *msg;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001829 void *args;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001830 size_t printed = 0;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001831 struct thread *thread;
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001832 int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
David Ahernbf2575c2013-10-08 21:26:53 -06001833 struct syscall *sc = trace__syscall_info(trace, evsel, id);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001834 struct thread_trace *ttrace;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001835
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001836 if (sc == NULL)
1837 return -1;
1838
David Ahern8fb598e2013-09-28 13:13:00 -06001839 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001840 ttrace = thread__trace(thread, trace->output);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001841 if (ttrace == NULL)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001842 goto out_put;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001843
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -03001844 args = perf_evsel__sc_tp_ptr(evsel, args, sample);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001845
1846 if (ttrace->entry_str == NULL) {
Arnaldo Carvalho de Meloe4d44e82015-08-04 22:17:29 -03001847 ttrace->entry_str = malloc(trace__entry_str_size);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001848 if (!ttrace->entry_str)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001849 goto out_put;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001850 }
1851
David Ahern13f22a22015-03-19 12:23:03 -06001852 if (!trace->summary_only)
Arnaldo Carvalho de Melo6ebad5c2015-03-25 18:01:15 -03001853 trace__printf_interrupted_entry(trace, sample);
Arnaldo Carvalho de Meloe5966632015-02-13 13:22:21 -03001854
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001855 ttrace->entry_time = sample->time;
1856 msg = ttrace->entry_str;
Arnaldo Carvalho de Meloe4d44e82015-08-04 22:17:29 -03001857 printed += scnprintf(msg + printed, trace__entry_str_size - printed, "%s(", sc->name);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001858
Arnaldo Carvalho de Meloe4d44e82015-08-04 22:17:29 -03001859 printed += syscall__scnprintf_args(sc, msg + printed, trace__entry_str_size - printed,
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001860 args, trace, thread);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001861
Arnaldo Carvalho de Melo5089f202014-06-17 14:29:24 -03001862 if (sc->is_exit) {
David Ahernfd2eaba2013-11-12 09:31:15 -07001863 if (!trace->duration_filter && !trace->summary_only) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001864 trace__fprintf_entry_head(trace, thread, 1, sample->time, trace->output);
1865 fprintf(trace->output, "%-70s\n", ttrace->entry_str);
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001866 }
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03001867 } else {
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001868 ttrace->entry_pending = true;
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03001869 /* See trace__vfs_getname & trace__sys_exit */
1870 ttrace->filename.pending_open = false;
1871 }
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001872
Arnaldo Carvalho de Melof3b623b2015-03-02 22:21:35 -03001873 if (trace->current != thread) {
1874 thread__put(trace->current);
1875 trace->current = thread__get(thread);
1876 }
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001877 err = 0;
1878out_put:
1879 thread__put(thread);
1880 return err;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001881}
1882
Arnaldo Carvalho de Melo202ff962016-04-12 10:11:07 -03001883static int trace__fprintf_callchain(struct trace *trace, struct perf_evsel *evsel,
1884 struct perf_sample *sample)
1885{
1886 struct addr_location al;
1887 /* TODO: user-configurable print_opts */
Arnaldo Carvalho de Meloe20ab862016-04-12 15:16:15 -03001888 const unsigned int print_opts = EVSEL__PRINT_SYM |
1889 EVSEL__PRINT_DSO |
1890 EVSEL__PRINT_UNKNOWN_AS_ADDR;
Arnaldo Carvalho de Melo202ff962016-04-12 10:11:07 -03001891
1892 if (sample->callchain == NULL)
1893 return 0;
1894
Arnaldo Carvalho de Melo6f736732016-04-14 17:45:51 -03001895 if (machine__resolve(trace->host, &al, sample) < 0 ||
1896 thread__resolve_callchain(al.thread, &callchain_cursor, evsel,
Arnaldo Carvalho de Meloc6d4a492016-04-14 18:29:08 -03001897 sample, NULL, NULL, trace->max_stack)) {
Arnaldo Carvalho de Melo202ff962016-04-12 10:11:07 -03001898 pr_err("Problem processing %s callchain, skipping...\n",
1899 perf_evsel__name(evsel));
1900 return 0;
1901 }
1902
Arnaldo Carvalho de Melod327e602016-04-14 17:53:49 -03001903 return sample__fprintf_callchain(sample, 38, print_opts, &callchain_cursor, trace->output);
Arnaldo Carvalho de Melo202ff962016-04-12 10:11:07 -03001904}
1905
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001906static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04001907 union perf_event *event __maybe_unused,
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001908 struct perf_sample *sample)
1909{
Chang Hyun Park2c82c3a2014-09-26 21:54:01 +09001910 long ret;
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001911 u64 duration = 0;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001912 struct thread *thread;
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001913 int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
David Ahernbf2575c2013-10-08 21:26:53 -06001914 struct syscall *sc = trace__syscall_info(trace, evsel, id);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001915 struct thread_trace *ttrace;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001916
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001917 if (sc == NULL)
1918 return -1;
1919
David Ahern8fb598e2013-09-28 13:13:00 -06001920 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001921 ttrace = thread__trace(thread, trace->output);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001922 if (ttrace == NULL)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001923 goto out_put;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001924
David Ahernbf2575c2013-10-08 21:26:53 -06001925 if (trace->summary)
1926 thread__update_stats(ttrace, id, sample);
1927
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -03001928 ret = perf_evsel__sc_tp_uint(evsel, ret, sample);
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001929
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03001930 if (id == trace->open_id && ret >= 0 && ttrace->filename.pending_open) {
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03001931 trace__set_fd_pathname(thread, ret, ttrace->filename.name);
1932 ttrace->filename.pending_open = false;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001933 ++trace->stats.vfs_getname;
1934 }
1935
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001936 ttrace->exit_time = sample->time;
1937
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001938 if (ttrace->entry_time) {
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001939 duration = sample->time - ttrace->entry_time;
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001940 if (trace__filter_duration(trace, duration))
1941 goto out;
1942 } else if (trace->duration_filter)
1943 goto out;
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001944
David Ahernfd2eaba2013-11-12 09:31:15 -07001945 if (trace->summary_only)
1946 goto out;
1947
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001948 trace__fprintf_entry_head(trace, thread, duration, sample->time, trace->output);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001949
1950 if (ttrace->entry_pending) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001951 fprintf(trace->output, "%-70s", ttrace->entry_str);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001952 } else {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001953 fprintf(trace->output, " ... [");
1954 color_fprintf(trace->output, PERF_COLOR_YELLOW, "continued");
1955 fprintf(trace->output, "]: %s()", sc->name);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001956 }
1957
Arnaldo Carvalho de Meloda3c9a42013-08-26 11:28:34 -03001958 if (sc->fmt == NULL) {
1959signed_print:
Chang Hyun Park2c82c3a2014-09-26 21:54:01 +09001960 fprintf(trace->output, ") = %ld", ret);
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -03001961 } else if (ret < 0 && (sc->fmt->errmsg || sc->fmt->errpid)) {
Masami Hiramatsu942a91e2014-08-14 02:22:41 +00001962 char bf[STRERR_BUFSIZE];
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001963 const char *emsg = strerror_r(-ret, bf, sizeof(bf)),
1964 *e = audit_errno_to_name(-ret);
1965
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001966 fprintf(trace->output, ") = -1 %s %s", e, emsg);
Arnaldo Carvalho de Meloda3c9a42013-08-26 11:28:34 -03001967 } else if (ret == 0 && sc->fmt->timeout)
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001968 fprintf(trace->output, ") = 0 Timeout");
Arnaldo Carvalho de Melo04b34722013-08-26 11:36:30 -03001969 else if (sc->fmt->hexret)
Chang Hyun Park2c82c3a2014-09-26 21:54:01 +09001970 fprintf(trace->output, ") = %#lx", ret);
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -03001971 else if (sc->fmt->errpid) {
1972 struct thread *child = machine__find_thread(trace->host, ret, ret);
1973
1974 if (child != NULL) {
1975 fprintf(trace->output, ") = %ld", ret);
1976 if (child->comm_set)
1977 fprintf(trace->output, " (%s)", thread__comm_str(child));
1978 thread__put(child);
1979 }
1980 } else
Arnaldo Carvalho de Meloda3c9a42013-08-26 11:28:34 -03001981 goto signed_print;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001982
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001983 fputc('\n', trace->output);
Milian Wolff566a0882016-04-08 13:34:15 +02001984
Arnaldo Carvalho de Melo202ff962016-04-12 10:11:07 -03001985 trace__fprintf_callchain(trace, evsel, sample);
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001986out:
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001987 ttrace->entry_pending = false;
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001988 err = 0;
1989out_put:
1990 thread__put(thread);
1991 return err;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001992}
1993
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001994static int trace__vfs_getname(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04001995 union perf_event *event __maybe_unused,
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001996 struct perf_sample *sample)
1997{
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001998 struct thread *thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
1999 struct thread_trace *ttrace;
2000 size_t filename_len, entry_str_len, to_move;
2001 ssize_t remaining_space;
2002 char *pos;
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03002003 const char *filename = perf_evsel__rawptr(evsel, sample, "pathname");
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03002004
2005 if (!thread)
2006 goto out;
2007
2008 ttrace = thread__priv(thread);
2009 if (!ttrace)
2010 goto out;
2011
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03002012 filename_len = strlen(filename);
2013
2014 if (ttrace->filename.namelen < filename_len) {
2015 char *f = realloc(ttrace->filename.name, filename_len + 1);
2016
2017 if (f == NULL)
2018 goto out;
2019
2020 ttrace->filename.namelen = filename_len;
2021 ttrace->filename.name = f;
2022 }
2023
2024 strcpy(ttrace->filename.name, filename);
2025 ttrace->filename.pending_open = true;
2026
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03002027 if (!ttrace->filename.ptr)
2028 goto out;
2029
2030 entry_str_len = strlen(ttrace->entry_str);
2031 remaining_space = trace__entry_str_size - entry_str_len - 1; /* \0 */
2032 if (remaining_space <= 0)
2033 goto out;
2034
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03002035 if (filename_len > (size_t)remaining_space) {
2036 filename += filename_len - remaining_space;
2037 filename_len = remaining_space;
2038 }
2039
2040 to_move = entry_str_len - ttrace->filename.entry_str_pos + 1; /* \0 */
2041 pos = ttrace->entry_str + ttrace->filename.entry_str_pos;
2042 memmove(pos + filename_len, pos, to_move);
2043 memcpy(pos, filename, filename_len);
2044
2045 ttrace->filename.ptr = 0;
2046 ttrace->filename.entry_str_pos = 0;
2047out:
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002048 return 0;
2049}
2050
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002051static int trace__sched_stat_runtime(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04002052 union perf_event *event __maybe_unused,
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002053 struct perf_sample *sample)
2054{
2055 u64 runtime = perf_evsel__intval(evsel, sample, "runtime");
2056 double runtime_ms = (double)runtime / NSEC_PER_MSEC;
David Ahern8fb598e2013-09-28 13:13:00 -06002057 struct thread *thread = machine__findnew_thread(trace->host,
Adrian Hunter314add62013-08-27 11:23:03 +03002058 sample->pid,
2059 sample->tid);
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002060 struct thread_trace *ttrace = thread__trace(thread, trace->output);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002061
2062 if (ttrace == NULL)
2063 goto out_dump;
2064
2065 ttrace->runtime_ms += runtime_ms;
2066 trace->runtime_ms += runtime_ms;
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002067 thread__put(thread);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002068 return 0;
2069
2070out_dump:
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002071 fprintf(trace->output, "%s: comm=%s,pid=%u,runtime=%" PRIu64 ",vruntime=%" PRIu64 ")\n",
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002072 evsel->name,
2073 perf_evsel__strval(evsel, sample, "comm"),
2074 (pid_t)perf_evsel__intval(evsel, sample, "pid"),
2075 runtime,
2076 perf_evsel__intval(evsel, sample, "vruntime"));
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002077 thread__put(thread);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002078 return 0;
2079}
2080
Wang Nan1d6c9402016-02-26 09:31:55 +00002081static void bpf_output__printer(enum binary_printer_ops op,
2082 unsigned int val, void *extra)
2083{
2084 FILE *output = extra;
2085 unsigned char ch = (unsigned char)val;
2086
2087 switch (op) {
2088 case BINARY_PRINT_CHAR_DATA:
2089 fprintf(output, "%c", isprint(ch) ? ch : '.');
2090 break;
2091 case BINARY_PRINT_DATA_BEGIN:
2092 case BINARY_PRINT_LINE_BEGIN:
2093 case BINARY_PRINT_ADDR:
2094 case BINARY_PRINT_NUM_DATA:
2095 case BINARY_PRINT_NUM_PAD:
2096 case BINARY_PRINT_SEP:
2097 case BINARY_PRINT_CHAR_PAD:
2098 case BINARY_PRINT_LINE_END:
2099 case BINARY_PRINT_DATA_END:
2100 default:
2101 break;
2102 }
2103}
2104
2105static void bpf_output__fprintf(struct trace *trace,
2106 struct perf_sample *sample)
2107{
2108 print_binary(sample->raw_data, sample->raw_size, 8,
2109 bpf_output__printer, trace->output);
2110}
2111
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002112static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
2113 union perf_event *event __maybe_unused,
2114 struct perf_sample *sample)
2115{
2116 trace__printf_interrupted_entry(trace, sample);
2117 trace__fprintf_tstamp(trace, sample->time, trace->output);
Arnaldo Carvalho de Melo08089212015-02-19 21:51:50 -08002118
2119 if (trace->trace_syscalls)
2120 fprintf(trace->output, "( ): ");
2121
2122 fprintf(trace->output, "%s:", evsel->name);
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002123
Wang Nan1d6c9402016-02-26 09:31:55 +00002124 if (perf_evsel__is_bpf_output(evsel)) {
2125 bpf_output__fprintf(trace, sample);
2126 } else if (evsel->tp_format) {
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002127 event_format__fprintf(evsel->tp_format, sample->cpu,
2128 sample->raw_data, sample->raw_size,
2129 trace->output);
2130 }
2131
2132 fprintf(trace->output, ")\n");
Arnaldo Carvalho de Melo202ff962016-04-12 10:11:07 -03002133
2134 trace__fprintf_callchain(trace, evsel, sample);
2135
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002136 return 0;
2137}
2138
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002139static void print_location(FILE *f, struct perf_sample *sample,
2140 struct addr_location *al,
2141 bool print_dso, bool print_sym)
2142{
2143
2144 if ((verbose || print_dso) && al->map)
2145 fprintf(f, "%s@", al->map->dso->long_name);
2146
2147 if ((verbose || print_sym) && al->sym)
Arnaldo Carvalho de Melo4414a3c2014-07-08 15:39:21 -03002148 fprintf(f, "%s+0x%" PRIx64, al->sym->name,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002149 al->addr - al->sym->start);
2150 else if (al->map)
Arnaldo Carvalho de Melo4414a3c2014-07-08 15:39:21 -03002151 fprintf(f, "0x%" PRIx64, al->addr);
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002152 else
Arnaldo Carvalho de Melo4414a3c2014-07-08 15:39:21 -03002153 fprintf(f, "0x%" PRIx64, sample->addr);
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002154}
2155
2156static int trace__pgfault(struct trace *trace,
2157 struct perf_evsel *evsel,
Arnaldo Carvalho de Melo473398a2016-03-22 18:23:43 -03002158 union perf_event *event __maybe_unused,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002159 struct perf_sample *sample)
2160{
2161 struct thread *thread;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002162 struct addr_location al;
2163 char map_type = 'd';
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04002164 struct thread_trace *ttrace;
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002165 int err = -1;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002166
2167 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04002168 ttrace = thread__trace(thread, trace->output);
2169 if (ttrace == NULL)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002170 goto out_put;
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04002171
2172 if (evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ)
2173 ttrace->pfmaj++;
2174 else
2175 ttrace->pfmin++;
2176
2177 if (trace->summary_only)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002178 goto out;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002179
Arnaldo Carvalho de Melo473398a2016-03-22 18:23:43 -03002180 thread__find_addr_location(thread, sample->cpumode, MAP__FUNCTION,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002181 sample->ip, &al);
2182
2183 trace__fprintf_entry_head(trace, thread, 0, sample->time, trace->output);
2184
2185 fprintf(trace->output, "%sfault [",
2186 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ?
2187 "maj" : "min");
2188
2189 print_location(trace->output, sample, &al, false, true);
2190
2191 fprintf(trace->output, "] => ");
2192
Arnaldo Carvalho de Melo473398a2016-03-22 18:23:43 -03002193 thread__find_addr_location(thread, sample->cpumode, MAP__VARIABLE,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002194 sample->addr, &al);
2195
2196 if (!al.map) {
Arnaldo Carvalho de Melo473398a2016-03-22 18:23:43 -03002197 thread__find_addr_location(thread, sample->cpumode,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002198 MAP__FUNCTION, sample->addr, &al);
2199
2200 if (al.map)
2201 map_type = 'x';
2202 else
2203 map_type = '?';
2204 }
2205
2206 print_location(trace->output, sample, &al, true, false);
2207
2208 fprintf(trace->output, " (%c%c)\n", map_type, al.level);
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002209out:
2210 err = 0;
2211out_put:
2212 thread__put(thread);
2213 return err;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002214}
2215
David Ahernbdc89662013-08-28 22:29:53 -06002216static bool skip_sample(struct trace *trace, struct perf_sample *sample)
2217{
2218 if ((trace->pid_list && intlist__find(trace->pid_list, sample->pid)) ||
2219 (trace->tid_list && intlist__find(trace->tid_list, sample->tid)))
2220 return false;
2221
2222 if (trace->pid_list || trace->tid_list)
2223 return true;
2224
2225 return false;
2226}
2227
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03002228static void trace__set_base_time(struct trace *trace,
Arnaldo Carvalho de Melo8a07a802016-03-31 15:19:39 -03002229 struct perf_evsel *evsel,
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03002230 struct perf_sample *sample)
2231{
Arnaldo Carvalho de Melo8a07a802016-03-31 15:19:39 -03002232 /*
2233 * BPF events were not setting PERF_SAMPLE_TIME, so be more robust
2234 * and don't use sample->time unconditionally, we may end up having
2235 * some other event in the future without PERF_SAMPLE_TIME for good
2236 * reason, i.e. we may not be interested in its timestamps, just in
2237 * it taking place, picking some piece of information when it
2238 * appears in our event stream (vfs_getname comes to mind).
2239 */
2240 if (trace->base_time == 0 && !trace->full_time &&
2241 (evsel->attr.sample_type & PERF_SAMPLE_TIME))
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03002242 trace->base_time = sample->time;
2243}
2244
David Ahern6810fc92013-08-28 22:29:52 -06002245static int trace__process_sample(struct perf_tool *tool,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04002246 union perf_event *event,
David Ahern6810fc92013-08-28 22:29:52 -06002247 struct perf_sample *sample,
2248 struct perf_evsel *evsel,
2249 struct machine *machine __maybe_unused)
2250{
2251 struct trace *trace = container_of(tool, struct trace, tool);
2252 int err = 0;
2253
Arnaldo Carvalho de Melo744a9712013-11-06 10:17:38 -03002254 tracepoint_handler handler = evsel->handler;
David Ahern6810fc92013-08-28 22:29:52 -06002255
David Ahernbdc89662013-08-28 22:29:53 -06002256 if (skip_sample(trace, sample))
2257 return 0;
2258
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03002259 trace__set_base_time(trace, evsel, sample);
David Ahern6810fc92013-08-28 22:29:52 -06002260
David Ahern31605652013-12-04 19:41:41 -07002261 if (handler) {
2262 ++trace->nr_events;
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04002263 handler(trace, evsel, event, sample);
David Ahern31605652013-12-04 19:41:41 -07002264 }
David Ahern6810fc92013-08-28 22:29:52 -06002265
2266 return err;
2267}
2268
David Ahernbdc89662013-08-28 22:29:53 -06002269static int parse_target_str(struct trace *trace)
2270{
2271 if (trace->opts.target.pid) {
2272 trace->pid_list = intlist__new(trace->opts.target.pid);
2273 if (trace->pid_list == NULL) {
2274 pr_err("Error parsing process id string\n");
2275 return -EINVAL;
2276 }
2277 }
2278
2279 if (trace->opts.target.tid) {
2280 trace->tid_list = intlist__new(trace->opts.target.tid);
2281 if (trace->tid_list == NULL) {
2282 pr_err("Error parsing thread id string\n");
2283 return -EINVAL;
2284 }
2285 }
2286
2287 return 0;
2288}
2289
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002290static int trace__record(struct trace *trace, int argc, const char **argv)
David Ahern5e2485b2013-09-28 13:13:01 -06002291{
2292 unsigned int rec_argc, i, j;
2293 const char **rec_argv;
2294 const char * const record_args[] = {
2295 "record",
2296 "-R",
2297 "-m", "1024",
2298 "-c", "1",
David Ahern5e2485b2013-09-28 13:13:01 -06002299 };
2300
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002301 const char * const sc_args[] = { "-e", };
2302 unsigned int sc_args_nr = ARRAY_SIZE(sc_args);
2303 const char * const majpf_args[] = { "-e", "major-faults" };
2304 unsigned int majpf_args_nr = ARRAY_SIZE(majpf_args);
2305 const char * const minpf_args[] = { "-e", "minor-faults" };
2306 unsigned int minpf_args_nr = ARRAY_SIZE(minpf_args);
2307
David Ahern9aca7f12013-12-04 19:41:39 -07002308 /* +1 is for the event string below */
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002309 rec_argc = ARRAY_SIZE(record_args) + sc_args_nr + 1 +
2310 majpf_args_nr + minpf_args_nr + argc;
David Ahern5e2485b2013-09-28 13:13:01 -06002311 rec_argv = calloc(rec_argc + 1, sizeof(char *));
2312
2313 if (rec_argv == NULL)
2314 return -ENOMEM;
2315
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002316 j = 0;
David Ahern5e2485b2013-09-28 13:13:01 -06002317 for (i = 0; i < ARRAY_SIZE(record_args); i++)
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002318 rec_argv[j++] = record_args[i];
2319
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002320 if (trace->trace_syscalls) {
2321 for (i = 0; i < sc_args_nr; i++)
2322 rec_argv[j++] = sc_args[i];
David Ahern5e2485b2013-09-28 13:13:01 -06002323
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002324 /* event string may be different for older kernels - e.g., RHEL6 */
2325 if (is_valid_tracepoint("raw_syscalls:sys_enter"))
2326 rec_argv[j++] = "raw_syscalls:sys_enter,raw_syscalls:sys_exit";
2327 else if (is_valid_tracepoint("syscalls:sys_enter"))
2328 rec_argv[j++] = "syscalls:sys_enter,syscalls:sys_exit";
2329 else {
2330 pr_err("Neither raw_syscalls nor syscalls events exist.\n");
2331 return -1;
2332 }
David Ahern9aca7f12013-12-04 19:41:39 -07002333 }
David Ahern9aca7f12013-12-04 19:41:39 -07002334
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002335 if (trace->trace_pgfaults & TRACE_PFMAJ)
2336 for (i = 0; i < majpf_args_nr; i++)
2337 rec_argv[j++] = majpf_args[i];
David Ahern5e2485b2013-09-28 13:13:01 -06002338
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002339 if (trace->trace_pgfaults & TRACE_PFMIN)
2340 for (i = 0; i < minpf_args_nr; i++)
2341 rec_argv[j++] = minpf_args[i];
2342
2343 for (i = 0; i < (unsigned int)argc; i++)
2344 rec_argv[j++] = argv[i];
2345
2346 return cmd_record(j, rec_argv, NULL);
David Ahern5e2485b2013-09-28 13:13:01 -06002347}
2348
David Ahernbf2575c2013-10-08 21:26:53 -06002349static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp);
2350
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002351static bool perf_evlist__add_vfs_getname(struct perf_evlist *evlist)
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002352{
Arnaldo Carvalho de Meloef503832013-11-07 16:41:19 -03002353 struct perf_evsel *evsel = perf_evsel__newtp("probe", "vfs_getname");
Jiri Olsa8dd2a132015-09-07 10:38:06 +02002354
2355 if (IS_ERR(evsel))
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002356 return false;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002357
2358 if (perf_evsel__field(evsel, "pathname") == NULL) {
2359 perf_evsel__delete(evsel);
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002360 return false;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002361 }
2362
Arnaldo Carvalho de Melo744a9712013-11-06 10:17:38 -03002363 evsel->handler = trace__vfs_getname;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002364 perf_evlist__add(evlist, evsel);
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002365 return true;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002366}
2367
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002368static int perf_evlist__add_pgfault(struct perf_evlist *evlist,
2369 u64 config)
2370{
2371 struct perf_evsel *evsel;
2372 struct perf_event_attr attr = {
2373 .type = PERF_TYPE_SOFTWARE,
2374 .mmap_data = 1,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002375 };
2376
2377 attr.config = config;
Arnaldo Carvalho de Melo05247982014-07-23 18:15:09 -03002378 attr.sample_period = 1;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002379
2380 event_attr_init(&attr);
2381
2382 evsel = perf_evsel__new(&attr);
2383 if (!evsel)
2384 return -ENOMEM;
2385
2386 evsel->handler = trace__pgfault;
2387 perf_evlist__add(evlist, evsel);
2388
2389 return 0;
2390}
2391
Arnaldo Carvalho de Meloddbb1b12015-02-21 12:10:29 -08002392static void trace__handle_event(struct trace *trace, union perf_event *event, struct perf_sample *sample)
2393{
2394 const u32 type = event->header.type;
2395 struct perf_evsel *evsel;
2396
Arnaldo Carvalho de Meloddbb1b12015-02-21 12:10:29 -08002397 if (type != PERF_RECORD_SAMPLE) {
2398 trace__process_event(trace, trace->host, event, sample);
2399 return;
2400 }
2401
2402 evsel = perf_evlist__id2evsel(trace->evlist, sample->id);
2403 if (evsel == NULL) {
2404 fprintf(trace->output, "Unknown tp ID %" PRIu64 ", skipping...\n", sample->id);
2405 return;
2406 }
2407
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03002408 trace__set_base_time(trace, evsel, sample);
2409
Arnaldo Carvalho de Meloddbb1b12015-02-21 12:10:29 -08002410 if (evsel->attr.type == PERF_TYPE_TRACEPOINT &&
2411 sample->raw_data == NULL) {
2412 fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n",
2413 perf_evsel__name(evsel), sample->tid,
2414 sample->cpu, sample->raw_size);
2415 } else {
2416 tracepoint_handler handler = evsel->handler;
2417 handler(trace, evsel, event, sample);
2418 }
2419}
2420
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03002421static int trace__add_syscall_newtp(struct trace *trace)
2422{
2423 int ret = -1;
2424 struct perf_evlist *evlist = trace->evlist;
2425 struct perf_evsel *sys_enter, *sys_exit;
2426
2427 sys_enter = perf_evsel__syscall_newtp("sys_enter", trace__sys_enter);
2428 if (sys_enter == NULL)
2429 goto out;
2430
2431 if (perf_evsel__init_sc_tp_ptr_field(sys_enter, args))
2432 goto out_delete_sys_enter;
2433
2434 sys_exit = perf_evsel__syscall_newtp("sys_exit", trace__sys_exit);
2435 if (sys_exit == NULL)
2436 goto out_delete_sys_enter;
2437
2438 if (perf_evsel__init_sc_tp_uint_field(sys_exit, ret))
2439 goto out_delete_sys_exit;
2440
2441 perf_evlist__add(evlist, sys_enter);
2442 perf_evlist__add(evlist, sys_exit);
2443
Arnaldo Carvalho de Melo44621812016-04-11 15:49:11 -03002444 if (trace->opts.callgraph_set && !trace->kernel_syscallchains) {
2445 /*
2446 * We're interested only in the user space callchain
2447 * leading to the syscall, allow overriding that for
2448 * debugging reasons using --kernel_syscall_callchains
2449 */
2450 sys_exit->attr.exclude_callchain_kernel = 1;
2451 }
2452
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03002453 trace->syscalls.events.sys_enter = sys_enter;
2454 trace->syscalls.events.sys_exit = sys_exit;
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03002455
2456 ret = 0;
2457out:
2458 return ret;
2459
2460out_delete_sys_exit:
2461 perf_evsel__delete_priv(sys_exit);
2462out_delete_sys_enter:
2463 perf_evsel__delete_priv(sys_enter);
2464 goto out;
2465}
2466
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002467static int trace__set_ev_qualifier_filter(struct trace *trace)
2468{
2469 int err = -1;
2470 char *filter = asprintf_expr_inout_ints("id", !trace->not_ev_qualifier,
2471 trace->ev_qualifier_ids.nr,
2472 trace->ev_qualifier_ids.entries);
2473
2474 if (filter == NULL)
2475 goto out_enomem;
2476
2477 if (!perf_evsel__append_filter(trace->syscalls.events.sys_enter, "&&", filter))
2478 err = perf_evsel__append_filter(trace->syscalls.events.sys_exit, "&&", filter);
2479
2480 free(filter);
2481out:
2482 return err;
2483out_enomem:
2484 errno = ENOMEM;
2485 goto out;
2486}
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03002487
Namhyung Kimf15eb532012-10-05 14:02:16 +09002488static int trace__run(struct trace *trace, int argc, const char **argv)
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002489{
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002490 struct perf_evlist *evlist = trace->evlist;
Arnaldo Carvalho de Melo94ad89b2015-07-03 17:42:03 -03002491 struct perf_evsel *evsel;
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03002492 int err = -1, i;
2493 unsigned long before;
Namhyung Kimf15eb532012-10-05 14:02:16 +09002494 const bool forks = argc > 0;
Arnaldo Carvalho de Melo46fb3c22014-09-22 14:39:48 -03002495 bool draining = false;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002496
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03002497 trace->live = true;
2498
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03002499 if (trace->trace_syscalls && trace__add_syscall_newtp(trace))
Arnaldo Carvalho de Melo801c67b2015-01-22 10:52:55 -03002500 goto out_error_raw_syscalls;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002501
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002502 if (trace->trace_syscalls)
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002503 trace->vfs_getname = perf_evlist__add_vfs_getname(evlist);
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002504
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002505 if ((trace->trace_pgfaults & TRACE_PFMAJ) &&
Arnaldo Carvalho de Meloe2726d92015-01-22 10:34:22 -03002506 perf_evlist__add_pgfault(evlist, PERF_COUNT_SW_PAGE_FAULTS_MAJ)) {
Arnaldo Carvalho de Melo5ed08da2015-01-22 11:08:04 -03002507 goto out_error_mem;
Arnaldo Carvalho de Meloe2726d92015-01-22 10:34:22 -03002508 }
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002509
2510 if ((trace->trace_pgfaults & TRACE_PFMIN) &&
2511 perf_evlist__add_pgfault(evlist, PERF_COUNT_SW_PAGE_FAULTS_MIN))
Arnaldo Carvalho de Melo5ed08da2015-01-22 11:08:04 -03002512 goto out_error_mem;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002513
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002514 if (trace->sched &&
Arnaldo Carvalho de Melo2cc990b2015-01-22 11:13:43 -03002515 perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime",
2516 trace__sched_stat_runtime))
2517 goto out_error_sched_stat_runtime;
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002518
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002519 err = perf_evlist__create_maps(evlist, &trace->opts.target);
2520 if (err < 0) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002521 fprintf(trace->output, "Problems parsing the target to trace, check your options!\n");
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002522 goto out_delete_evlist;
2523 }
2524
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03002525 err = trace__symbols_init(trace, evlist);
2526 if (err < 0) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002527 fprintf(trace->output, "Problems initializing symbol libraries!\n");
Arnaldo Carvalho de Melo03ad9742014-01-03 15:56:06 -03002528 goto out_delete_evlist;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03002529 }
2530
Arnaldo Carvalho de Melofde54b72016-04-11 18:42:37 -03002531 perf_evlist__config(evlist, &trace->opts, NULL);
2532
2533 if (trace->opts.callgraph_set && trace->syscalls.events.sys_exit) {
2534 perf_evsel__config_callchain(trace->syscalls.events.sys_exit,
2535 &trace->opts, &callchain_param);
2536 /*
2537 * Now we have evsels with different sample_ids, use
2538 * PERF_SAMPLE_IDENTIFIER to map from sample to evsel
2539 * from a fixed position in each ring buffer record.
2540 *
2541 * As of this the changeset introducing this comment, this
2542 * isn't strictly needed, as the fields that can come before
2543 * PERF_SAMPLE_ID are all used, but we'll probably disable
2544 * some of those for things like copying the payload of
2545 * pointer syscall arguments, and for vfs_getname we don't
2546 * need PERF_SAMPLE_ADDR and PERF_SAMPLE_IP, so do this
2547 * here as a warning we need to use PERF_SAMPLE_IDENTIFIER.
2548 */
2549 perf_evlist__set_sample_bit(evlist, IDENTIFIER);
2550 perf_evlist__reset_sample_bit(evlist, ID);
2551 }
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002552
Namhyung Kimf15eb532012-10-05 14:02:16 +09002553 signal(SIGCHLD, sig_handler);
2554 signal(SIGINT, sig_handler);
2555
2556 if (forks) {
Namhyung Kim6ef73ec2013-03-11 16:43:15 +09002557 err = perf_evlist__prepare_workload(evlist, &trace->opts.target,
Arnaldo Carvalho de Melo735f7e02014-01-03 14:56:49 -03002558 argv, false, NULL);
Namhyung Kimf15eb532012-10-05 14:02:16 +09002559 if (err < 0) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002560 fprintf(trace->output, "Couldn't run the workload!\n");
Arnaldo Carvalho de Melo03ad9742014-01-03 15:56:06 -03002561 goto out_delete_evlist;
Namhyung Kimf15eb532012-10-05 14:02:16 +09002562 }
2563 }
2564
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002565 err = perf_evlist__open(evlist);
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002566 if (err < 0)
2567 goto out_error_open;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002568
Wang Nanba504232016-02-26 09:31:54 +00002569 err = bpf__apply_obj_config();
2570 if (err) {
2571 char errbuf[BUFSIZ];
2572
2573 bpf__strerror_apply_obj_config(err, errbuf, sizeof(errbuf));
2574 pr_err("ERROR: Apply config to BPF failed: %s\n",
2575 errbuf);
2576 goto out_error_open;
2577 }
2578
Arnaldo Carvalho de Melo241b0572015-02-21 10:15:21 -08002579 /*
2580 * Better not use !target__has_task() here because we need to cover the
2581 * case where no threads were specified in the command line, but a
2582 * workload was, and in that case we will fill in the thread_map when
2583 * we fork the workload in perf_evlist__prepare_workload.
2584 */
Arnaldo Carvalho de Melof078c382015-02-21 11:36:52 -08002585 if (trace->filter_pids.nr > 0)
2586 err = perf_evlist__set_filter_pids(evlist, trace->filter_pids.nr, trace->filter_pids.entries);
Jiri Olsae13798c2015-06-23 00:36:02 +02002587 else if (thread_map__pid(evlist->threads, 0) == -1)
Arnaldo Carvalho de Melof078c382015-02-21 11:36:52 -08002588 err = perf_evlist__set_filter_pid(evlist, getpid());
2589
Arnaldo Carvalho de Melo94ad89b2015-07-03 17:42:03 -03002590 if (err < 0)
2591 goto out_error_mem;
2592
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002593 if (trace->ev_qualifier_ids.nr > 0) {
2594 err = trace__set_ev_qualifier_filter(trace);
2595 if (err < 0)
2596 goto out_errno;
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002597
Arnaldo Carvalho de Melo2e5e5f82015-08-03 17:12:29 -03002598 pr_debug("event qualifier tracepoint filter: %s\n",
2599 trace->syscalls.events.sys_exit->filter);
2600 }
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002601
Arnaldo Carvalho de Melo94ad89b2015-07-03 17:42:03 -03002602 err = perf_evlist__apply_filters(evlist, &evsel);
2603 if (err < 0)
2604 goto out_error_apply_filters;
Arnaldo Carvalho de Melo241b0572015-02-21 10:15:21 -08002605
Jiri Olsaf8850372013-11-28 17:57:22 +01002606 err = perf_evlist__mmap(evlist, trace->opts.mmap_pages, false);
Arnaldo Carvalho de Meloe09b18d2014-12-11 18:04:10 -03002607 if (err < 0)
2608 goto out_error_mmap;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002609
Arnaldo Carvalho de Melocb24d012015-04-22 10:04:23 -03002610 if (!target__none(&trace->opts.target))
2611 perf_evlist__enable(evlist);
2612
Namhyung Kimf15eb532012-10-05 14:02:16 +09002613 if (forks)
2614 perf_evlist__start_workload(evlist);
2615
Jiri Olsae13798c2015-06-23 00:36:02 +02002616 trace->multiple_threads = thread_map__pid(evlist->threads, 0) == -1 ||
Arnaldo Carvalho de Melo42052be2015-02-13 12:32:45 -03002617 evlist->threads->nr > 1 ||
2618 perf_evlist__first(evlist)->attr.inherit;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002619again:
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03002620 before = trace->nr_events;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002621
2622 for (i = 0; i < evlist->nr_mmaps; i++) {
2623 union perf_event *event;
2624
2625 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002626 struct perf_sample sample;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002627
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03002628 ++trace->nr_events;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002629
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002630 err = perf_evlist__parse_sample(evlist, event, &sample);
2631 if (err) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002632 fprintf(trace->output, "Can't parse sample, err = %d, skipping...\n", err);
Zhouyi Zhou8e50d382013-10-24 15:43:33 +08002633 goto next_event;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002634 }
2635
Arnaldo Carvalho de Meloddbb1b12015-02-21 12:10:29 -08002636 trace__handle_event(trace, event, &sample);
Zhouyi Zhou8e50d382013-10-24 15:43:33 +08002637next_event:
2638 perf_evlist__mmap_consume(evlist, i);
Arnaldo Carvalho de Melo20c5f102013-09-03 11:55:07 -03002639
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002640 if (interrupted)
2641 goto out_disable;
Arnaldo Carvalho de Melo02ac5422015-04-22 11:11:57 -03002642
2643 if (done && !draining) {
2644 perf_evlist__disable(evlist);
2645 draining = true;
2646 }
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002647 }
2648 }
2649
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03002650 if (trace->nr_events == before) {
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002651 int timeout = done ? 100 : -1;
Namhyung Kimf15eb532012-10-05 14:02:16 +09002652
Arnaldo Carvalho de Melo46fb3c22014-09-22 14:39:48 -03002653 if (!draining && perf_evlist__poll(evlist, timeout) > 0) {
2654 if (perf_evlist__filter_pollfd(evlist, POLLERR | POLLHUP) == 0)
2655 draining = true;
2656
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002657 goto again;
Arnaldo Carvalho de Melo46fb3c22014-09-22 14:39:48 -03002658 }
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002659 } else {
2660 goto again;
Namhyung Kimf15eb532012-10-05 14:02:16 +09002661 }
2662
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002663out_disable:
Arnaldo Carvalho de Melof3b623b2015-03-02 22:21:35 -03002664 thread__zput(trace->current);
2665
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002666 perf_evlist__disable(evlist);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002667
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002668 if (!err) {
2669 if (trace->summary)
2670 trace__fprintf_thread_summary(trace, trace->output);
2671
2672 if (trace->show_tool_stats) {
2673 fprintf(trace->output, "Stats:\n "
2674 " vfs_getname : %" PRIu64 "\n"
2675 " proc_getname: %" PRIu64 "\n",
2676 trace->stats.vfs_getname,
2677 trace->stats.proc_getname);
2678 }
2679 }
David Ahernbf2575c2013-10-08 21:26:53 -06002680
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002681out_delete_evlist:
2682 perf_evlist__delete(evlist);
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002683 trace->evlist = NULL;
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03002684 trace->live = false;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002685 return err;
Arnaldo Carvalho de Melo6ef068c2013-10-17 12:07:58 -03002686{
2687 char errbuf[BUFSIZ];
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002688
Arnaldo Carvalho de Melo2cc990b2015-01-22 11:13:43 -03002689out_error_sched_stat_runtime:
Jiri Olsa988bdb32015-09-02 09:56:35 +02002690 tracing_path__strerror_open_tp(errno, errbuf, sizeof(errbuf), "sched", "sched_stat_runtime");
Arnaldo Carvalho de Melo2cc990b2015-01-22 11:13:43 -03002691 goto out_error;
2692
Arnaldo Carvalho de Melo801c67b2015-01-22 10:52:55 -03002693out_error_raw_syscalls:
Jiri Olsa988bdb32015-09-02 09:56:35 +02002694 tracing_path__strerror_open_tp(errno, errbuf, sizeof(errbuf), "raw_syscalls", "sys_(enter|exit)");
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002695 goto out_error;
2696
Arnaldo Carvalho de Meloe09b18d2014-12-11 18:04:10 -03002697out_error_mmap:
2698 perf_evlist__strerror_mmap(evlist, errno, errbuf, sizeof(errbuf));
2699 goto out_error;
2700
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002701out_error_open:
2702 perf_evlist__strerror_open(evlist, errno, errbuf, sizeof(errbuf));
2703
2704out_error:
Arnaldo Carvalho de Melo6ef068c2013-10-17 12:07:58 -03002705 fprintf(trace->output, "%s\n", errbuf);
Ramkumar Ramachandra87f91862013-10-04 10:47:31 +05302706 goto out_delete_evlist;
Arnaldo Carvalho de Melo94ad89b2015-07-03 17:42:03 -03002707
2708out_error_apply_filters:
2709 fprintf(trace->output,
2710 "Failed to set filter \"%s\" on event %s with %d (%s)\n",
2711 evsel->filter, perf_evsel__name(evsel), errno,
2712 strerror_r(errno, errbuf, sizeof(errbuf)));
2713 goto out_delete_evlist;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002714}
Arnaldo Carvalho de Melo5ed08da2015-01-22 11:08:04 -03002715out_error_mem:
2716 fprintf(trace->output, "Not enough memory to run!\n");
2717 goto out_delete_evlist;
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002718
2719out_errno:
2720 fprintf(trace->output, "errno=%d,%s\n", errno, strerror(errno));
2721 goto out_delete_evlist;
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002722}
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002723
David Ahern6810fc92013-08-28 22:29:52 -06002724static int trace__replay(struct trace *trace)
2725{
2726 const struct perf_evsel_str_handler handlers[] = {
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002727 { "probe:vfs_getname", trace__vfs_getname, },
David Ahern6810fc92013-08-28 22:29:52 -06002728 };
Jiri Olsaf5fc14122013-10-15 16:27:32 +02002729 struct perf_data_file file = {
2730 .path = input_name,
2731 .mode = PERF_DATA_MODE_READ,
Yunlong Songe366a6d2015-04-02 21:47:18 +08002732 .force = trace->force,
Jiri Olsaf5fc14122013-10-15 16:27:32 +02002733 };
David Ahern6810fc92013-08-28 22:29:52 -06002734 struct perf_session *session;
Namhyung Kim003824e2013-11-12 15:25:00 +09002735 struct perf_evsel *evsel;
David Ahern6810fc92013-08-28 22:29:52 -06002736 int err = -1;
2737
2738 trace->tool.sample = trace__process_sample;
2739 trace->tool.mmap = perf_event__process_mmap;
David Ahern384c6712013-09-22 19:44:58 -06002740 trace->tool.mmap2 = perf_event__process_mmap2;
David Ahern6810fc92013-08-28 22:29:52 -06002741 trace->tool.comm = perf_event__process_comm;
2742 trace->tool.exit = perf_event__process_exit;
2743 trace->tool.fork = perf_event__process_fork;
2744 trace->tool.attr = perf_event__process_attr;
2745 trace->tool.tracing_data = perf_event__process_tracing_data;
2746 trace->tool.build_id = perf_event__process_build_id;
2747
Jiri Olsa0a8cb852014-07-06 14:18:21 +02002748 trace->tool.ordered_events = true;
David Ahern6810fc92013-08-28 22:29:52 -06002749 trace->tool.ordering_requires_timestamps = true;
2750
2751 /* add tid to output */
2752 trace->multiple_threads = true;
2753
Jiri Olsaf5fc14122013-10-15 16:27:32 +02002754 session = perf_session__new(&file, false, &trace->tool);
David Ahern6810fc92013-08-28 22:29:52 -06002755 if (session == NULL)
Taeung Song52e028342014-09-24 10:33:37 +09002756 return -1;
David Ahern6810fc92013-08-28 22:29:52 -06002757
Namhyung Kim0a7e6d12014-08-12 15:40:45 +09002758 if (symbol__init(&session->header.env) < 0)
Namhyung Kimcb2ffae2014-08-12 15:40:44 +09002759 goto out;
2760
David Ahern8fb598e2013-09-28 13:13:00 -06002761 trace->host = &session->machines.host;
2762
David Ahern6810fc92013-08-28 22:29:52 -06002763 err = perf_session__set_tracepoints_handlers(session, handlers);
2764 if (err)
2765 goto out;
2766
Namhyung Kim003824e2013-11-12 15:25:00 +09002767 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2768 "raw_syscalls:sys_enter");
David Ahern9aca7f12013-12-04 19:41:39 -07002769 /* older kernels have syscalls tp versus raw_syscalls */
2770 if (evsel == NULL)
2771 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2772 "syscalls:sys_enter");
David Ahern6810fc92013-08-28 22:29:52 -06002773
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002774 if (evsel &&
2775 (perf_evsel__init_syscall_tp(evsel, trace__sys_enter) < 0 ||
2776 perf_evsel__init_sc_tp_ptr_field(evsel, args))) {
Namhyung Kim003824e2013-11-12 15:25:00 +09002777 pr_err("Error during initialize raw_syscalls:sys_enter event\n");
2778 goto out;
2779 }
2780
2781 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2782 "raw_syscalls:sys_exit");
David Ahern9aca7f12013-12-04 19:41:39 -07002783 if (evsel == NULL)
2784 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2785 "syscalls:sys_exit");
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002786 if (evsel &&
2787 (perf_evsel__init_syscall_tp(evsel, trace__sys_exit) < 0 ||
2788 perf_evsel__init_sc_tp_uint_field(evsel, ret))) {
Namhyung Kim003824e2013-11-12 15:25:00 +09002789 pr_err("Error during initialize raw_syscalls:sys_exit event\n");
David Ahern6810fc92013-08-28 22:29:52 -06002790 goto out;
2791 }
2792
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002793 evlist__for_each(session->evlist, evsel) {
2794 if (evsel->attr.type == PERF_TYPE_SOFTWARE &&
2795 (evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ||
2796 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MIN ||
2797 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS))
2798 evsel->handler = trace__pgfault;
2799 }
2800
David Ahernbdc89662013-08-28 22:29:53 -06002801 err = parse_target_str(trace);
2802 if (err != 0)
2803 goto out;
2804
David Ahern6810fc92013-08-28 22:29:52 -06002805 setup_pager();
2806
Arnaldo Carvalho de Melob7b61cb2015-03-03 11:58:45 -03002807 err = perf_session__process_events(session);
David Ahern6810fc92013-08-28 22:29:52 -06002808 if (err)
2809 pr_err("Failed to process events, error %d", err);
2810
David Ahernbf2575c2013-10-08 21:26:53 -06002811 else if (trace->summary)
2812 trace__fprintf_thread_summary(trace, trace->output);
2813
David Ahern6810fc92013-08-28 22:29:52 -06002814out:
2815 perf_session__delete(session);
2816
2817 return err;
2818}
2819
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002820static size_t trace__fprintf_threads_header(FILE *fp)
2821{
2822 size_t printed;
2823
Pekka Enberg99ff7152013-11-12 16:42:14 +02002824 printed = fprintf(fp, "\n Summary of events:\n\n");
David Ahernbf2575c2013-10-08 21:26:53 -06002825
2826 return printed;
2827}
2828
2829static size_t thread__dump_stats(struct thread_trace *ttrace,
2830 struct trace *trace, FILE *fp)
2831{
2832 struct stats *stats;
2833 size_t printed = 0;
2834 struct syscall *sc;
2835 struct int_node *inode = intlist__first(ttrace->syscall_stats);
2836
2837 if (inode == NULL)
2838 return 0;
2839
2840 printed += fprintf(fp, "\n");
2841
Milian Wolff834fd462015-08-06 11:24:29 +02002842 printed += fprintf(fp, " syscall calls total min avg max stddev\n");
2843 printed += fprintf(fp, " (msec) (msec) (msec) (msec) (%%)\n");
2844 printed += fprintf(fp, " --------------- -------- --------- --------- --------- --------- ------\n");
Pekka Enberg99ff7152013-11-12 16:42:14 +02002845
David Ahernbf2575c2013-10-08 21:26:53 -06002846 /* each int_node is a syscall */
2847 while (inode) {
2848 stats = inode->priv;
2849 if (stats) {
2850 double min = (double)(stats->min) / NSEC_PER_MSEC;
2851 double max = (double)(stats->max) / NSEC_PER_MSEC;
2852 double avg = avg_stats(stats);
2853 double pct;
2854 u64 n = (u64) stats->n;
2855
2856 pct = avg ? 100.0 * stddev_stats(stats)/avg : 0.0;
2857 avg /= NSEC_PER_MSEC;
2858
2859 sc = &trace->syscalls.table[inode->i];
Pekka Enberg99ff7152013-11-12 16:42:14 +02002860 printed += fprintf(fp, " %-15s", sc->name);
Milian Wolff834fd462015-08-06 11:24:29 +02002861 printed += fprintf(fp, " %8" PRIu64 " %9.3f %9.3f %9.3f",
2862 n, avg * n, min, avg);
Pekka Enberg27a778b2013-11-13 14:21:48 +02002863 printed += fprintf(fp, " %9.3f %9.2f%%\n", max, pct);
David Ahernbf2575c2013-10-08 21:26:53 -06002864 }
2865
2866 inode = intlist__next(inode);
2867 }
2868
2869 printed += fprintf(fp, "\n\n");
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002870
2871 return printed;
2872}
2873
David Ahern896cbb52013-09-28 13:12:59 -06002874/* struct used to pass data to per-thread function */
2875struct summary_data {
2876 FILE *fp;
2877 struct trace *trace;
2878 size_t printed;
2879};
2880
2881static int trace__fprintf_one_thread(struct thread *thread, void *priv)
2882{
2883 struct summary_data *data = priv;
2884 FILE *fp = data->fp;
2885 size_t printed = data->printed;
2886 struct trace *trace = data->trace;
Namhyung Kim89dceb22014-10-06 09:46:03 +09002887 struct thread_trace *ttrace = thread__priv(thread);
David Ahern896cbb52013-09-28 13:12:59 -06002888 double ratio;
2889
2890 if (ttrace == NULL)
2891 return 0;
2892
2893 ratio = (double)ttrace->nr_events / trace->nr_events * 100.0;
2894
Pekka Enberg15e65c62013-11-14 18:43:30 +02002895 printed += fprintf(fp, " %s (%d), ", thread__comm_str(thread), thread->tid);
Pekka Enberg99ff7152013-11-12 16:42:14 +02002896 printed += fprintf(fp, "%lu events, ", ttrace->nr_events);
Pekka Enberg15e65c62013-11-14 18:43:30 +02002897 printed += fprintf(fp, "%.1f%%", ratio);
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04002898 if (ttrace->pfmaj)
2899 printed += fprintf(fp, ", %lu majfaults", ttrace->pfmaj);
2900 if (ttrace->pfmin)
2901 printed += fprintf(fp, ", %lu minfaults", ttrace->pfmin);
Pekka Enberg99ff7152013-11-12 16:42:14 +02002902 printed += fprintf(fp, ", %.3f msec\n", ttrace->runtime_ms);
David Ahernbf2575c2013-10-08 21:26:53 -06002903 printed += thread__dump_stats(ttrace, trace, fp);
David Ahern896cbb52013-09-28 13:12:59 -06002904
2905 data->printed += printed;
2906
2907 return 0;
2908}
2909
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002910static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp)
2911{
David Ahern896cbb52013-09-28 13:12:59 -06002912 struct summary_data data = {
2913 .fp = fp,
2914 .trace = trace
2915 };
2916 data.printed = trace__fprintf_threads_header(fp);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002917
David Ahern896cbb52013-09-28 13:12:59 -06002918 machine__for_each_thread(trace->host, trace__fprintf_one_thread, &data);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002919
David Ahern896cbb52013-09-28 13:12:59 -06002920 return data.printed;
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002921}
2922
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03002923static int trace__set_duration(const struct option *opt, const char *str,
2924 int unset __maybe_unused)
2925{
2926 struct trace *trace = opt->value;
2927
2928 trace->duration_filter = atof(str);
2929 return 0;
2930}
2931
Arnaldo Carvalho de Melof078c382015-02-21 11:36:52 -08002932static int trace__set_filter_pids(const struct option *opt, const char *str,
2933 int unset __maybe_unused)
2934{
2935 int ret = -1;
2936 size_t i;
2937 struct trace *trace = opt->value;
2938 /*
2939 * FIXME: introduce a intarray class, plain parse csv and create a
2940 * { int nr, int entries[] } struct...
2941 */
2942 struct intlist *list = intlist__new(str);
2943
2944 if (list == NULL)
2945 return -1;
2946
2947 i = trace->filter_pids.nr = intlist__nr_entries(list) + 1;
2948 trace->filter_pids.entries = calloc(i, sizeof(pid_t));
2949
2950 if (trace->filter_pids.entries == NULL)
2951 goto out;
2952
2953 trace->filter_pids.entries[0] = getpid();
2954
2955 for (i = 1; i < trace->filter_pids.nr; ++i)
2956 trace->filter_pids.entries[i] = intlist__entry(list, i - 1)->i;
2957
2958 intlist__delete(list);
2959 ret = 0;
2960out:
2961 return ret;
2962}
2963
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002964static int trace__open_output(struct trace *trace, const char *filename)
2965{
2966 struct stat st;
2967
2968 if (!stat(filename, &st) && st.st_size) {
2969 char oldname[PATH_MAX];
2970
2971 scnprintf(oldname, sizeof(oldname), "%s.old", filename);
2972 unlink(oldname);
2973 rename(filename, oldname);
2974 }
2975
2976 trace->output = fopen(filename, "w");
2977
2978 return trace->output == NULL ? -errno : 0;
2979}
2980
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002981static int parse_pagefaults(const struct option *opt, const char *str,
2982 int unset __maybe_unused)
2983{
2984 int *trace_pgfaults = opt->value;
2985
2986 if (strcmp(str, "all") == 0)
2987 *trace_pgfaults |= TRACE_PFMAJ | TRACE_PFMIN;
2988 else if (strcmp(str, "maj") == 0)
2989 *trace_pgfaults |= TRACE_PFMAJ;
2990 else if (strcmp(str, "min") == 0)
2991 *trace_pgfaults |= TRACE_PFMIN;
2992 else
2993 return -1;
2994
2995 return 0;
2996}
2997
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002998static void evlist__set_evsel_handler(struct perf_evlist *evlist, void *handler)
2999{
3000 struct perf_evsel *evsel;
3001
3002 evlist__for_each(evlist, evsel)
3003 evsel->handler = handler;
3004}
3005
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003006int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
3007{
Yunlong Song6fdd9cb2015-03-18 21:35:57 +08003008 const char *trace_usage[] = {
Namhyung Kimf15eb532012-10-05 14:02:16 +09003009 "perf trace [<options>] [<command>]",
3010 "perf trace [<options>] -- <command> [<options>]",
David Ahern5e2485b2013-09-28 13:13:01 -06003011 "perf trace record [<options>] [<command>]",
3012 "perf trace record [<options>] -- <command> [<options>]",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003013 NULL
3014 };
3015 struct trace trace = {
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003016 .syscalls = {
3017 . max = -1,
3018 },
3019 .opts = {
3020 .target = {
3021 .uid = UINT_MAX,
3022 .uses_mmap = true,
3023 },
3024 .user_freq = UINT_MAX,
3025 .user_interval = ULLONG_MAX,
Arnaldo Carvalho de Melo509051e2014-01-14 17:52:14 -03003026 .no_buffering = true,
Arnaldo Carvalho de Melo38d54472014-12-12 17:28:32 -03003027 .mmap_pages = UINT_MAX,
Kan Liang9d9cad72015-06-17 09:51:11 -04003028 .proc_map_timeout = 500,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003029 },
Milian Wolff007d66a2015-08-05 16:52:23 -03003030 .output = stderr,
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -03003031 .show_comm = true,
Stanislav Fomicheve281a962014-06-26 20:14:28 +04003032 .trace_syscalls = true,
Arnaldo Carvalho de Melo44621812016-04-11 15:49:11 -03003033 .kernel_syscallchains = false,
Arnaldo Carvalho de Meloc6d4a492016-04-14 18:29:08 -03003034 .max_stack = PERF_MAX_STACK_DEPTH,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003035 };
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003036 const char *output_name = NULL;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03003037 const char *ev_qualifier_str = NULL;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003038 const struct option trace_options[] = {
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003039 OPT_CALLBACK(0, "event", &trace.evlist, "event",
3040 "event selector. use 'perf list' to list available events",
3041 parse_events_option),
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -03003042 OPT_BOOLEAN(0, "comm", &trace.show_comm,
3043 "show the thread COMM next to its id"),
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03003044 OPT_BOOLEAN(0, "tool_stats", &trace.show_tool_stats, "show tool stats"),
Arnaldo Carvalho de Melod303e852015-04-23 12:02:07 -03003045 OPT_STRING('e', "expr", &ev_qualifier_str, "expr", "list of syscalls to trace"),
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003046 OPT_STRING('o', "output", &output_name, "file", "output file name"),
David Ahern6810fc92013-08-28 22:29:52 -06003047 OPT_STRING('i', "input", &input_name, "file", "Analyze events in file"),
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003048 OPT_STRING('p', "pid", &trace.opts.target.pid, "pid",
3049 "trace events on existing process id"),
David Ahernac9be8e2013-08-20 11:15:45 -06003050 OPT_STRING('t', "tid", &trace.opts.target.tid, "tid",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003051 "trace events on existing thread id"),
Arnaldo Carvalho de Melofa0e4ff2015-04-23 11:59:20 -03003052 OPT_CALLBACK(0, "filter-pids", &trace, "CSV list of pids",
3053 "pids to filter (by the kernel)", trace__set_filter_pids),
David Ahernac9be8e2013-08-20 11:15:45 -06003054 OPT_BOOLEAN('a', "all-cpus", &trace.opts.target.system_wide,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003055 "system-wide collection from all CPUs"),
David Ahernac9be8e2013-08-20 11:15:45 -06003056 OPT_STRING('C', "cpu", &trace.opts.target.cpu_list, "cpu",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003057 "list of cpus to monitor"),
David Ahern6810fc92013-08-28 22:29:52 -06003058 OPT_BOOLEAN(0, "no-inherit", &trace.opts.no_inherit,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003059 "child tasks do not inherit counters"),
Jiri Olsa994a1f72013-09-01 12:36:12 +02003060 OPT_CALLBACK('m', "mmap-pages", &trace.opts.mmap_pages, "pages",
3061 "number of mmap data pages",
3062 perf_evlist__parse_mmap_pages),
David Ahernac9be8e2013-08-20 11:15:45 -06003063 OPT_STRING('u', "uid", &trace.opts.target.uid_str, "user",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003064 "user to profile"),
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03003065 OPT_CALLBACK(0, "duration", &trace, "float",
3066 "show only events with duration > N.M ms",
3067 trace__set_duration),
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03003068 OPT_BOOLEAN(0, "sched", &trace.sched, "show blocking scheduler events"),
Arnaldo Carvalho de Melo7c304ee02013-08-22 16:49:54 -03003069 OPT_INCR('v', "verbose", &verbose, "be more verbose"),
David Ahern4bb09192013-09-04 12:37:43 -06003070 OPT_BOOLEAN('T', "time", &trace.full_time,
3071 "Show full timestamp, not time relative to first start"),
David Ahernfd2eaba2013-11-12 09:31:15 -07003072 OPT_BOOLEAN('s', "summary", &trace.summary_only,
3073 "Show only syscall summary with statistics"),
3074 OPT_BOOLEAN('S', "with-summary", &trace.summary,
3075 "Show all syscalls and summary with statistics"),
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04003076 OPT_CALLBACK_DEFAULT('F', "pf", &trace.trace_pgfaults, "all|maj|min",
3077 "Trace pagefaults", parse_pagefaults, "maj"),
Stanislav Fomicheve281a962014-06-26 20:14:28 +04003078 OPT_BOOLEAN(0, "syscalls", &trace.trace_syscalls, "Trace syscalls"),
Yunlong Songe366a6d2015-04-02 21:47:18 +08003079 OPT_BOOLEAN('f', "force", &trace.force, "don't complain, do it"),
Milian Wolff566a0882016-04-08 13:34:15 +02003080 OPT_CALLBACK(0, "call-graph", &trace.opts,
3081 "record_mode[,record_size]", record_callchain_help,
3082 &record_parse_callchain_opt),
Arnaldo Carvalho de Melo44621812016-04-11 15:49:11 -03003083 OPT_BOOLEAN(0, "kernel-syscall-graph", &trace.kernel_syscallchains,
3084 "Show the kernel callchains on the syscall exit path"),
Arnaldo Carvalho de Meloc6d4a492016-04-14 18:29:08 -03003085 OPT_UINTEGER(0, "max-stack", &trace.max_stack,
3086 "Set the maximum stack depth when parsing the callchain, "
3087 "anything beyond the specified depth will be ignored. "
3088 "Default: " __stringify(PERF_MAX_STACK_DEPTH)),
Kan Liang9d9cad72015-06-17 09:51:11 -04003089 OPT_UINTEGER(0, "proc-map-timeout", &trace.opts.proc_map_timeout,
3090 "per thread proc mmap processing timeout in ms"),
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003091 OPT_END()
3092 };
Yunlong Song6fdd9cb2015-03-18 21:35:57 +08003093 const char * const trace_subcommands[] = { "record", NULL };
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003094 int err;
Namhyung Kim32caf0d2012-10-05 14:02:13 +09003095 char bf[BUFSIZ];
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003096
Arnaldo Carvalho de Melo4d08cb82015-02-24 15:35:55 -03003097 signal(SIGSEGV, sighandler_dump_stack);
3098 signal(SIGFPE, sighandler_dump_stack);
3099
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003100 trace.evlist = perf_evlist__new();
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03003101 trace.sctbl = syscalltbl__new();
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003102
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03003103 if (trace.evlist == NULL || trace.sctbl == NULL) {
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003104 pr_err("Not enough memory to run!\n");
He Kuangff8f6952015-05-11 12:28:36 +00003105 err = -ENOMEM;
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003106 goto out;
3107 }
3108
Yunlong Song6fdd9cb2015-03-18 21:35:57 +08003109 argc = parse_options_subcommand(argc, argv, trace_options, trace_subcommands,
3110 trace_usage, PARSE_OPT_STOP_AT_NON_OPTION);
David Ahernfd2eaba2013-11-12 09:31:15 -07003111
Wang Nand7888572016-04-08 15:07:24 +00003112 err = bpf__setup_stdout(trace.evlist);
3113 if (err) {
3114 bpf__strerror_setup_stdout(trace.evlist, err, bf, sizeof(bf));
3115 pr_err("ERROR: Setup BPF stdout failed: %s\n", bf);
3116 goto out;
3117 }
3118
Arnaldo Carvalho de Melo59247e32016-04-12 16:05:02 -03003119 err = -1;
3120
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04003121 if (trace.trace_pgfaults) {
3122 trace.opts.sample_address = true;
3123 trace.opts.sample_time = true;
3124 }
3125
Milian Wolff566a0882016-04-08 13:34:15 +02003126 if (trace.opts.callgraph_set)
3127 symbol_conf.use_callchain = true;
3128
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003129 if (trace.evlist->nr_entries > 0)
3130 evlist__set_evsel_handler(trace.evlist, trace__event_handler);
3131
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04003132 if ((argc >= 1) && (strcmp(argv[0], "record") == 0))
3133 return trace__record(&trace, argc-1, &argv[1]);
3134
3135 /* summary_only implies summary option, but don't overwrite summary if set */
3136 if (trace.summary_only)
3137 trace.summary = trace.summary_only;
3138
Arnaldo Carvalho de Melo726f3232015-02-06 10:16:45 +01003139 if (!trace.trace_syscalls && !trace.trace_pgfaults &&
3140 trace.evlist->nr_entries == 0 /* Was --events used? */) {
Stanislav Fomicheve281a962014-06-26 20:14:28 +04003141 pr_err("Please specify something to trace.\n");
3142 return -1;
3143 }
3144
Arnaldo Carvalho de Melo59247e32016-04-12 16:05:02 -03003145 if (!trace.trace_syscalls && ev_qualifier_str) {
3146 pr_err("The -e option can't be used with --no-syscalls.\n");
3147 goto out;
3148 }
3149
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003150 if (output_name != NULL) {
3151 err = trace__open_output(&trace, output_name);
3152 if (err < 0) {
3153 perror("failed to create output file");
3154 goto out;
3155 }
3156 }
3157
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03003158 trace.open_id = syscalltbl__id(trace.sctbl, "open");
3159
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03003160 if (ev_qualifier_str != NULL) {
Arnaldo Carvalho de Melob059efd2013-08-21 12:56:21 -03003161 const char *s = ev_qualifier_str;
Arnaldo Carvalho de Melo005438a82015-07-20 12:02:09 -03003162 struct strlist_config slist_config = {
3163 .dirname = system_path(STRACE_GROUPS_DIR),
3164 };
Arnaldo Carvalho de Melob059efd2013-08-21 12:56:21 -03003165
3166 trace.not_ev_qualifier = *s == '!';
3167 if (trace.not_ev_qualifier)
3168 ++s;
Arnaldo Carvalho de Melo005438a82015-07-20 12:02:09 -03003169 trace.ev_qualifier = strlist__new(s, &slist_config);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03003170 if (trace.ev_qualifier == NULL) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003171 fputs("Not enough memory to parse event qualifier",
3172 trace.output);
3173 err = -ENOMEM;
3174 goto out_close;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03003175 }
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03003176
3177 err = trace__validate_ev_qualifier(&trace);
3178 if (err)
3179 goto out_close;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03003180 }
3181
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003182 err = target__validate(&trace.opts.target);
Namhyung Kim32caf0d2012-10-05 14:02:13 +09003183 if (err) {
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003184 target__strerror(&trace.opts.target, err, bf, sizeof(bf));
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003185 fprintf(trace.output, "%s", bf);
3186 goto out_close;
Namhyung Kim32caf0d2012-10-05 14:02:13 +09003187 }
3188
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003189 err = target__parse_uid(&trace.opts.target);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003190 if (err) {
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003191 target__strerror(&trace.opts.target, err, bf, sizeof(bf));
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003192 fprintf(trace.output, "%s", bf);
3193 goto out_close;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003194 }
3195
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003196 if (!argc && target__none(&trace.opts.target))
Namhyung Kimee761202012-10-05 14:02:14 +09003197 trace.opts.target.system_wide = true;
3198
David Ahern6810fc92013-08-28 22:29:52 -06003199 if (input_name)
3200 err = trace__replay(&trace);
3201 else
3202 err = trace__run(&trace, argc, argv);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03003203
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003204out_close:
3205 if (output_name != NULL)
3206 fclose(trace.output);
3207out:
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03003208 return err;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003209}