blob: 8e090a785c5e5191473206ac12a334cad66e9c4a [file] [log] [blame]
Arnaldo Carvalho de Meloa598bb52015-08-28 12:02:37 -03001/*
2 * builtin-trace.c
3 *
4 * Builtin 'trace' command:
5 *
6 * Display a continuously updated trace of any workload, CPU, specific PID,
7 * system wide, etc. Default format is loosely strace like, but any other
8 * event may be specified using --event.
9 *
10 * Copyright (C) 2012, 2013, 2014, 2015 Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
11 *
12 * Initially based on the 'trace' prototype by Thomas Gleixner:
13 *
14 * http://lwn.net/Articles/415728/ ("Announcing a new utility: 'trace'")
15 *
16 * Released under the GPL v2. (and only v2, not any later version)
17 */
18
Robert Richter4e319022013-06-11 17:29:18 +020019#include <traceevent/event-parse.h>
Jiri Olsa988bdb32015-09-02 09:56:35 +020020#include <api/fs/tracing_path.h>
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -030021#include "builtin.h"
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -030022#include "util/color.h"
Arnaldo Carvalho de Melo7c304ee02013-08-22 16:49:54 -030023#include "util/debug.h"
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -030024#include "util/evlist.h"
Josh Poimboeuf4b6ab942015-12-15 09:39:39 -060025#include <subcmd/exec-cmd.h>
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -030026#include "util/machine.h"
David Ahern6810fc92013-08-28 22:29:52 -060027#include "util/session.h"
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -030028#include "util/thread.h"
Josh Poimboeuf4b6ab942015-12-15 09:39:39 -060029#include <subcmd/parse-options.h>
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -030030#include "util/strlist.h"
David Ahernbdc89662013-08-28 22:29:53 -060031#include "util/intlist.h"
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -030032#include "util/thread_map.h"
David Ahernbf2575c2013-10-08 21:26:53 -060033#include "util/stat.h"
Jiri Olsa97978b32013-12-03 14:09:24 +010034#include "trace-event.h"
David Ahern9aca7f12013-12-04 19:41:39 -070035#include "util/parse-events.h"
Wang Nanba504232016-02-26 09:31:54 +000036#include "util/bpf-loader.h"
Milian Wolff566a0882016-04-08 13:34:15 +020037#include "callchain.h"
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -030038#include "syscalltbl.h"
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -030039
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -030040#include <libaudit.h> /* FIXME: Still needed for audit_errno_to_name */
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -030041#include <stdlib.h>
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -030042#include <linux/futex.h>
Jiri Olsa8dd2a132015-09-07 10:38:06 +020043#include <linux/err.h>
Arnaldo Carvalho de Melo997bba82016-03-30 19:43:32 -030044#include <linux/seccomp.h>
45#include <linux/filter.h>
46#include <linux/audit.h>
47#include <sys/ptrace.h>
Arnaldo Carvalho de Melo39878d42016-03-30 20:02:15 -030048#include <linux/random.h>
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -030049
Arnaldo Carvalho de Meloc188e7a2015-05-14 17:39:03 -030050#ifndef O_CLOEXEC
51# define O_CLOEXEC 02000000
52#endif
53
54#ifndef SOCK_DCCP
55# define SOCK_DCCP 6
56#endif
57
58#ifndef SOCK_CLOEXEC
59# define SOCK_CLOEXEC 02000000
60#endif
61
62#ifndef SOCK_NONBLOCK
63# define SOCK_NONBLOCK 00004000
64#endif
65
66#ifndef MSG_CMSG_CLOEXEC
67# define MSG_CMSG_CLOEXEC 0x40000000
68#endif
69
Arnaldo Carvalho de Meloa1c25522015-06-11 22:47:54 -030070#ifndef PERF_FLAG_FD_NO_GROUP
71# define PERF_FLAG_FD_NO_GROUP (1UL << 0)
72#endif
73
74#ifndef PERF_FLAG_FD_OUTPUT
75# define PERF_FLAG_FD_OUTPUT (1UL << 1)
76#endif
77
78#ifndef PERF_FLAG_PID_CGROUP
79# define PERF_FLAG_PID_CGROUP (1UL << 2) /* pid=cgroup id, per-cpu mode only */
80#endif
81
82#ifndef PERF_FLAG_FD_CLOEXEC
83# define PERF_FLAG_FD_CLOEXEC (1UL << 3) /* O_CLOEXEC */
84#endif
85
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -030086struct trace {
87 struct perf_tool tool;
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -030088 struct syscalltbl *sctbl;
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -030089 struct {
90 int max;
91 struct syscall *table;
92 struct {
93 struct perf_evsel *sys_enter,
94 *sys_exit;
95 } events;
96 } syscalls;
97 struct record_opts opts;
98 struct perf_evlist *evlist;
99 struct machine *host;
100 struct thread *current;
101 u64 base_time;
102 FILE *output;
103 unsigned long nr_events;
104 struct strlist *ev_qualifier;
105 struct {
106 size_t nr;
107 int *entries;
108 } ev_qualifier_ids;
109 struct intlist *tid_list;
110 struct intlist *pid_list;
111 struct {
112 size_t nr;
113 pid_t *entries;
114 } filter_pids;
115 double duration_filter;
116 double runtime_ms;
117 struct {
118 u64 vfs_getname,
119 proc_getname;
120 } stats;
121 bool not_ev_qualifier;
122 bool live;
123 bool full_time;
124 bool sched;
125 bool multiple_threads;
126 bool summary;
127 bool summary_only;
128 bool show_comm;
129 bool show_tool_stats;
130 bool trace_syscalls;
Arnaldo Carvalho de Melo44621812016-04-11 15:49:11 -0300131 bool kernel_syscallchains;
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -0300132 bool force;
133 bool vfs_getname;
134 int trace_pgfaults;
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -0300135 int open_id;
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -0300136};
Arnaldo Carvalho de Meloa1c25522015-06-11 22:47:54 -0300137
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300138struct tp_field {
139 int offset;
140 union {
141 u64 (*integer)(struct tp_field *field, struct perf_sample *sample);
142 void *(*pointer)(struct tp_field *field, struct perf_sample *sample);
143 };
144};
145
146#define TP_UINT_FIELD(bits) \
147static u64 tp_field__u##bits(struct tp_field *field, struct perf_sample *sample) \
148{ \
David Ahern55d43bc2015-02-19 15:00:22 -0500149 u##bits value; \
150 memcpy(&value, sample->raw_data + field->offset, sizeof(value)); \
151 return value; \
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300152}
153
154TP_UINT_FIELD(8);
155TP_UINT_FIELD(16);
156TP_UINT_FIELD(32);
157TP_UINT_FIELD(64);
158
159#define TP_UINT_FIELD__SWAPPED(bits) \
160static u64 tp_field__swapped_u##bits(struct tp_field *field, struct perf_sample *sample) \
161{ \
David Ahern55d43bc2015-02-19 15:00:22 -0500162 u##bits value; \
163 memcpy(&value, sample->raw_data + field->offset, sizeof(value)); \
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300164 return bswap_##bits(value);\
165}
166
167TP_UINT_FIELD__SWAPPED(16);
168TP_UINT_FIELD__SWAPPED(32);
169TP_UINT_FIELD__SWAPPED(64);
170
171static int tp_field__init_uint(struct tp_field *field,
172 struct format_field *format_field,
173 bool needs_swap)
174{
175 field->offset = format_field->offset;
176
177 switch (format_field->size) {
178 case 1:
179 field->integer = tp_field__u8;
180 break;
181 case 2:
182 field->integer = needs_swap ? tp_field__swapped_u16 : tp_field__u16;
183 break;
184 case 4:
185 field->integer = needs_swap ? tp_field__swapped_u32 : tp_field__u32;
186 break;
187 case 8:
188 field->integer = needs_swap ? tp_field__swapped_u64 : tp_field__u64;
189 break;
190 default:
191 return -1;
192 }
193
194 return 0;
195}
196
197static void *tp_field__ptr(struct tp_field *field, struct perf_sample *sample)
198{
199 return sample->raw_data + field->offset;
200}
201
202static int tp_field__init_ptr(struct tp_field *field, struct format_field *format_field)
203{
204 field->offset = format_field->offset;
205 field->pointer = tp_field__ptr;
206 return 0;
207}
208
209struct syscall_tp {
210 struct tp_field id;
211 union {
212 struct tp_field args, ret;
213 };
214};
215
216static int perf_evsel__init_tp_uint_field(struct perf_evsel *evsel,
217 struct tp_field *field,
218 const char *name)
219{
220 struct format_field *format_field = perf_evsel__field(evsel, name);
221
222 if (format_field == NULL)
223 return -1;
224
225 return tp_field__init_uint(field, format_field, evsel->needs_swap);
226}
227
228#define perf_evsel__init_sc_tp_uint_field(evsel, name) \
229 ({ struct syscall_tp *sc = evsel->priv;\
230 perf_evsel__init_tp_uint_field(evsel, &sc->name, #name); })
231
232static int perf_evsel__init_tp_ptr_field(struct perf_evsel *evsel,
233 struct tp_field *field,
234 const char *name)
235{
236 struct format_field *format_field = perf_evsel__field(evsel, name);
237
238 if (format_field == NULL)
239 return -1;
240
241 return tp_field__init_ptr(field, format_field);
242}
243
244#define perf_evsel__init_sc_tp_ptr_field(evsel, name) \
245 ({ struct syscall_tp *sc = evsel->priv;\
246 perf_evsel__init_tp_ptr_field(evsel, &sc->name, #name); })
247
248static void perf_evsel__delete_priv(struct perf_evsel *evsel)
249{
Arnaldo Carvalho de Melo04662522013-12-26 17:41:15 -0300250 zfree(&evsel->priv);
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300251 perf_evsel__delete(evsel);
252}
253
Namhyung Kim96695d42013-11-12 08:51:45 -0300254static int perf_evsel__init_syscall_tp(struct perf_evsel *evsel, void *handler)
255{
256 evsel->priv = malloc(sizeof(struct syscall_tp));
257 if (evsel->priv != NULL) {
258 if (perf_evsel__init_sc_tp_uint_field(evsel, id))
259 goto out_delete;
260
261 evsel->handler = handler;
262 return 0;
263 }
264
265 return -ENOMEM;
266
267out_delete:
Arnaldo Carvalho de Melo04662522013-12-26 17:41:15 -0300268 zfree(&evsel->priv);
Namhyung Kim96695d42013-11-12 08:51:45 -0300269 return -ENOENT;
270}
271
Arnaldo Carvalho de Meloef503832013-11-07 16:41:19 -0300272static struct perf_evsel *perf_evsel__syscall_newtp(const char *direction, void *handler)
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300273{
Arnaldo Carvalho de Meloef503832013-11-07 16:41:19 -0300274 struct perf_evsel *evsel = perf_evsel__newtp("raw_syscalls", direction);
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300275
David Ahern9aca7f12013-12-04 19:41:39 -0700276 /* older kernel (e.g., RHEL6) use syscalls:{enter,exit} */
Jiri Olsa8dd2a132015-09-07 10:38:06 +0200277 if (IS_ERR(evsel))
David Ahern9aca7f12013-12-04 19:41:39 -0700278 evsel = perf_evsel__newtp("syscalls", direction);
279
Jiri Olsa8dd2a132015-09-07 10:38:06 +0200280 if (IS_ERR(evsel))
281 return NULL;
282
283 if (perf_evsel__init_syscall_tp(evsel, handler))
284 goto out_delete;
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300285
286 return evsel;
287
288out_delete:
289 perf_evsel__delete_priv(evsel);
290 return NULL;
291}
292
293#define perf_evsel__sc_tp_uint(evsel, name, sample) \
294 ({ struct syscall_tp *fields = evsel->priv; \
295 fields->name.integer(&fields->name, sample); })
296
297#define perf_evsel__sc_tp_ptr(evsel, name, sample) \
298 ({ struct syscall_tp *fields = evsel->priv; \
299 fields->name.pointer(&fields->name, sample); })
300
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300301struct syscall_arg {
302 unsigned long val;
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300303 struct thread *thread;
304 struct trace *trace;
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300305 void *parm;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300306 u8 idx;
307 u8 mask;
308};
309
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300310struct strarray {
Arnaldo Carvalho de Melo03e3adc2013-10-08 16:00:21 -0300311 int offset;
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300312 int nr_entries;
313 const char **entries;
314};
315
316#define DEFINE_STRARRAY(array) struct strarray strarray__##array = { \
317 .nr_entries = ARRAY_SIZE(array), \
318 .entries = array, \
319}
320
Arnaldo Carvalho de Melo03e3adc2013-10-08 16:00:21 -0300321#define DEFINE_STRARRAY_OFFSET(array, off) struct strarray strarray__##array = { \
322 .offset = off, \
323 .nr_entries = ARRAY_SIZE(array), \
324 .entries = array, \
325}
326
Arnaldo Carvalho de Melo975b7c22013-10-08 17:17:43 -0300327static size_t __syscall_arg__scnprintf_strarray(char *bf, size_t size,
328 const char *intfmt,
329 struct syscall_arg *arg)
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300330{
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300331 struct strarray *sa = arg->parm;
Arnaldo Carvalho de Melo03e3adc2013-10-08 16:00:21 -0300332 int idx = arg->val - sa->offset;
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300333
334 if (idx < 0 || idx >= sa->nr_entries)
Arnaldo Carvalho de Melo975b7c22013-10-08 17:17:43 -0300335 return scnprintf(bf, size, intfmt, arg->val);
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300336
337 return scnprintf(bf, size, "%s", sa->entries[idx]);
338}
339
Arnaldo Carvalho de Melo975b7c22013-10-08 17:17:43 -0300340static size_t syscall_arg__scnprintf_strarray(char *bf, size_t size,
341 struct syscall_arg *arg)
342{
343 return __syscall_arg__scnprintf_strarray(bf, size, "%d", arg);
344}
345
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300346#define SCA_STRARRAY syscall_arg__scnprintf_strarray
347
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -0300348#if defined(__i386__) || defined(__x86_64__)
349/*
350 * FIXME: Make this available to all arches as soon as the ioctl beautifier
351 * gets rewritten to support all arches.
352 */
Arnaldo Carvalho de Melo78645cf2013-10-08 17:43:20 -0300353static size_t syscall_arg__scnprintf_strhexarray(char *bf, size_t size,
354 struct syscall_arg *arg)
355{
356 return __syscall_arg__scnprintf_strarray(bf, size, "%#x", arg);
357}
358
359#define SCA_STRHEXARRAY syscall_arg__scnprintf_strhexarray
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -0300360#endif /* defined(__i386__) || defined(__x86_64__) */
Arnaldo Carvalho de Melo78645cf2013-10-08 17:43:20 -0300361
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300362static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
363 struct syscall_arg *arg);
364
365#define SCA_FD syscall_arg__scnprintf_fd
366
367static size_t syscall_arg__scnprintf_fd_at(char *bf, size_t size,
368 struct syscall_arg *arg)
369{
370 int fd = arg->val;
371
372 if (fd == AT_FDCWD)
373 return scnprintf(bf, size, "CWD");
374
375 return syscall_arg__scnprintf_fd(bf, size, arg);
376}
377
378#define SCA_FDAT syscall_arg__scnprintf_fd_at
379
380static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
381 struct syscall_arg *arg);
382
383#define SCA_CLOSE_FD syscall_arg__scnprintf_close_fd
384
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -0300385static size_t syscall_arg__scnprintf_hex(char *bf, size_t size,
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300386 struct syscall_arg *arg)
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -0300387{
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300388 return scnprintf(bf, size, "%#lx", arg->val);
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -0300389}
390
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -0300391#define SCA_HEX syscall_arg__scnprintf_hex
392
Arnaldo Carvalho de Meloa1c25522015-06-11 22:47:54 -0300393static size_t syscall_arg__scnprintf_int(char *bf, size_t size,
394 struct syscall_arg *arg)
395{
396 return scnprintf(bf, size, "%d", arg->val);
397}
398
399#define SCA_INT syscall_arg__scnprintf_int
400
Arnaldo Carvalho de Melo5cea6ff2013-09-20 11:49:50 -0300401static size_t syscall_arg__scnprintf_flock(char *bf, size_t size,
402 struct syscall_arg *arg)
403{
404 int printed = 0, op = arg->val;
405
406 if (op == 0)
407 return scnprintf(bf, size, "NONE");
408#define P_CMD(cmd) \
409 if ((op & LOCK_##cmd) == LOCK_##cmd) { \
410 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #cmd); \
411 op &= ~LOCK_##cmd; \
412 }
413
414 P_CMD(SH);
415 P_CMD(EX);
416 P_CMD(NB);
417 P_CMD(UN);
418 P_CMD(MAND);
419 P_CMD(RW);
420 P_CMD(READ);
421 P_CMD(WRITE);
422#undef P_OP
423
424 if (op)
425 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", op);
426
427 return printed;
428}
429
430#define SCA_FLOCK syscall_arg__scnprintf_flock
431
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300432static 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 -0300433{
434 enum syscall_futex_args {
435 SCF_UADDR = (1 << 0),
436 SCF_OP = (1 << 1),
437 SCF_VAL = (1 << 2),
438 SCF_TIMEOUT = (1 << 3),
439 SCF_UADDR2 = (1 << 4),
440 SCF_VAL3 = (1 << 5),
441 };
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300442 int op = arg->val;
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -0300443 int cmd = op & FUTEX_CMD_MASK;
444 size_t printed = 0;
445
446 switch (cmd) {
447#define P_FUTEX_OP(n) case FUTEX_##n: printed = scnprintf(bf, size, #n);
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300448 P_FUTEX_OP(WAIT); arg->mask |= SCF_VAL3|SCF_UADDR2; break;
449 P_FUTEX_OP(WAKE); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
450 P_FUTEX_OP(FD); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
451 P_FUTEX_OP(REQUEUE); arg->mask |= SCF_VAL3|SCF_TIMEOUT; break;
452 P_FUTEX_OP(CMP_REQUEUE); arg->mask |= SCF_TIMEOUT; break;
453 P_FUTEX_OP(CMP_REQUEUE_PI); arg->mask |= SCF_TIMEOUT; break;
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -0300454 P_FUTEX_OP(WAKE_OP); break;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300455 P_FUTEX_OP(LOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
456 P_FUTEX_OP(UNLOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
457 P_FUTEX_OP(TRYLOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2; break;
458 P_FUTEX_OP(WAIT_BITSET); arg->mask |= SCF_UADDR2; break;
459 P_FUTEX_OP(WAKE_BITSET); arg->mask |= SCF_UADDR2; break;
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -0300460 P_FUTEX_OP(WAIT_REQUEUE_PI); break;
461 default: printed = scnprintf(bf, size, "%#x", cmd); break;
462 }
463
464 if (op & FUTEX_PRIVATE_FLAG)
465 printed += scnprintf(bf + printed, size - printed, "|PRIV");
466
467 if (op & FUTEX_CLOCK_REALTIME)
468 printed += scnprintf(bf + printed, size - printed, "|CLKRT");
469
470 return printed;
471}
472
Arnaldo Carvalho de Meloefe6b882013-09-03 16:15:12 -0300473#define SCA_FUTEX_OP syscall_arg__scnprintf_futex_op
474
Arnaldo Carvalho de Melo729a7842015-10-29 11:48:18 -0300475static const char *bpf_cmd[] = {
476 "MAP_CREATE", "MAP_LOOKUP_ELEM", "MAP_UPDATE_ELEM", "MAP_DELETE_ELEM",
477 "MAP_GET_NEXT_KEY", "PROG_LOAD",
478};
479static DEFINE_STRARRAY(bpf_cmd);
480
Arnaldo Carvalho de Melo03e3adc2013-10-08 16:00:21 -0300481static const char *epoll_ctl_ops[] = { "ADD", "DEL", "MOD", };
482static DEFINE_STRARRAY_OFFSET(epoll_ctl_ops, 1);
Arnaldo Carvalho de Meloeac032c2013-09-20 11:27:32 -0300483
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300484static const char *itimers[] = { "REAL", "VIRTUAL", "PROF", };
485static DEFINE_STRARRAY(itimers);
486
Arnaldo Carvalho de Melob62bee12015-08-11 11:05:36 -0300487static const char *keyctl_options[] = {
488 "GET_KEYRING_ID", "JOIN_SESSION_KEYRING", "UPDATE", "REVOKE", "CHOWN",
489 "SETPERM", "DESCRIBE", "CLEAR", "LINK", "UNLINK", "SEARCH", "READ",
490 "INSTANTIATE", "NEGATE", "SET_REQKEY_KEYRING", "SET_TIMEOUT",
491 "ASSUME_AUTHORITY", "GET_SECURITY", "SESSION_TO_PARENT", "REJECT",
492 "INSTANTIATE_IOV", "INVALIDATE", "GET_PERSISTENT",
493};
494static DEFINE_STRARRAY(keyctl_options);
495
Arnaldo Carvalho de Meloefe6b882013-09-03 16:15:12 -0300496static const char *whences[] = { "SET", "CUR", "END",
497#ifdef SEEK_DATA
498"DATA",
499#endif
500#ifdef SEEK_HOLE
501"HOLE",
502#endif
503};
504static DEFINE_STRARRAY(whences);
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -0300505
Arnaldo Carvalho de Melo80f587d2013-09-03 16:28:58 -0300506static const char *fcntl_cmds[] = {
507 "DUPFD", "GETFD", "SETFD", "GETFL", "SETFL", "GETLK", "SETLK",
508 "SETLKW", "SETOWN", "GETOWN", "SETSIG", "GETSIG", "F_GETLK64",
509 "F_SETLK64", "F_SETLKW64", "F_SETOWN_EX", "F_GETOWN_EX",
510 "F_GETOWNER_UIDS",
511};
512static DEFINE_STRARRAY(fcntl_cmds);
513
Arnaldo Carvalho de Meloc045bf02013-09-04 11:52:33 -0300514static const char *rlimit_resources[] = {
515 "CPU", "FSIZE", "DATA", "STACK", "CORE", "RSS", "NPROC", "NOFILE",
516 "MEMLOCK", "AS", "LOCKS", "SIGPENDING", "MSGQUEUE", "NICE", "RTPRIO",
517 "RTTIME",
518};
519static DEFINE_STRARRAY(rlimit_resources);
520
Arnaldo Carvalho de Meloeb5b1b12013-09-03 16:37:46 -0300521static const char *sighow[] = { "BLOCK", "UNBLOCK", "SETMASK", };
522static DEFINE_STRARRAY(sighow);
523
David Ahern4f8c1b72013-09-22 19:45:00 -0600524static const char *clockid[] = {
525 "REALTIME", "MONOTONIC", "PROCESS_CPUTIME_ID", "THREAD_CPUTIME_ID",
Arnaldo Carvalho de Melo28ebb872015-08-11 10:38:38 -0300526 "MONOTONIC_RAW", "REALTIME_COARSE", "MONOTONIC_COARSE", "BOOTTIME",
527 "REALTIME_ALARM", "BOOTTIME_ALARM", "SGI_CYCLE", "TAI"
David Ahern4f8c1b72013-09-22 19:45:00 -0600528};
529static DEFINE_STRARRAY(clockid);
530
Arnaldo Carvalho de Meloe10bce82013-09-04 10:27:41 -0300531static const char *socket_families[] = {
532 "UNSPEC", "LOCAL", "INET", "AX25", "IPX", "APPLETALK", "NETROM",
533 "BRIDGE", "ATMPVC", "X25", "INET6", "ROSE", "DECnet", "NETBEUI",
534 "SECURITY", "KEY", "NETLINK", "PACKET", "ASH", "ECONET", "ATMSVC",
535 "RDS", "SNA", "IRDA", "PPPOX", "WANPIPE", "LLC", "IB", "CAN", "TIPC",
536 "BLUETOOTH", "IUCV", "RXRPC", "ISDN", "PHONET", "IEEE802154", "CAIF",
537 "ALG", "NFC", "VSOCK",
538};
539static DEFINE_STRARRAY(socket_families);
540
Arnaldo Carvalho de Meloa28b24b2013-09-04 11:00:44 -0300541#ifndef SOCK_TYPE_MASK
542#define SOCK_TYPE_MASK 0xf
543#endif
544
545static size_t syscall_arg__scnprintf_socket_type(char *bf, size_t size,
546 struct syscall_arg *arg)
547{
548 size_t printed;
549 int type = arg->val,
550 flags = type & ~SOCK_TYPE_MASK;
551
552 type &= SOCK_TYPE_MASK;
553 /*
554 * Can't use a strarray, MIPS may override for ABI reasons.
555 */
556 switch (type) {
557#define P_SK_TYPE(n) case SOCK_##n: printed = scnprintf(bf, size, #n); break;
558 P_SK_TYPE(STREAM);
559 P_SK_TYPE(DGRAM);
560 P_SK_TYPE(RAW);
561 P_SK_TYPE(RDM);
562 P_SK_TYPE(SEQPACKET);
563 P_SK_TYPE(DCCP);
564 P_SK_TYPE(PACKET);
565#undef P_SK_TYPE
566 default:
567 printed = scnprintf(bf, size, "%#x", type);
568 }
569
570#define P_SK_FLAG(n) \
571 if (flags & SOCK_##n) { \
572 printed += scnprintf(bf + printed, size - printed, "|%s", #n); \
573 flags &= ~SOCK_##n; \
574 }
575
576 P_SK_FLAG(CLOEXEC);
577 P_SK_FLAG(NONBLOCK);
578#undef P_SK_FLAG
579
580 if (flags)
581 printed += scnprintf(bf + printed, size - printed, "|%#x", flags);
582
583 return printed;
584}
585
586#define SCA_SK_TYPE syscall_arg__scnprintf_socket_type
587
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -0300588#ifndef MSG_PROBE
589#define MSG_PROBE 0x10
590#endif
David Ahernb6e8f8f2013-09-22 19:44:56 -0600591#ifndef MSG_WAITFORONE
592#define MSG_WAITFORONE 0x10000
593#endif
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -0300594#ifndef MSG_SENDPAGE_NOTLAST
595#define MSG_SENDPAGE_NOTLAST 0x20000
596#endif
597#ifndef MSG_FASTOPEN
598#define MSG_FASTOPEN 0x20000000
599#endif
600
601static size_t syscall_arg__scnprintf_msg_flags(char *bf, size_t size,
602 struct syscall_arg *arg)
603{
604 int printed = 0, flags = arg->val;
605
606 if (flags == 0)
607 return scnprintf(bf, size, "NONE");
608#define P_MSG_FLAG(n) \
609 if (flags & MSG_##n) { \
610 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
611 flags &= ~MSG_##n; \
612 }
613
614 P_MSG_FLAG(OOB);
615 P_MSG_FLAG(PEEK);
616 P_MSG_FLAG(DONTROUTE);
617 P_MSG_FLAG(TRYHARD);
618 P_MSG_FLAG(CTRUNC);
619 P_MSG_FLAG(PROBE);
620 P_MSG_FLAG(TRUNC);
621 P_MSG_FLAG(DONTWAIT);
622 P_MSG_FLAG(EOR);
623 P_MSG_FLAG(WAITALL);
624 P_MSG_FLAG(FIN);
625 P_MSG_FLAG(SYN);
626 P_MSG_FLAG(CONFIRM);
627 P_MSG_FLAG(RST);
628 P_MSG_FLAG(ERRQUEUE);
629 P_MSG_FLAG(NOSIGNAL);
630 P_MSG_FLAG(MORE);
631 P_MSG_FLAG(WAITFORONE);
632 P_MSG_FLAG(SENDPAGE_NOTLAST);
633 P_MSG_FLAG(FASTOPEN);
634 P_MSG_FLAG(CMSG_CLOEXEC);
635#undef P_MSG_FLAG
636
637 if (flags)
638 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
639
640 return printed;
641}
642
643#define SCA_MSG_FLAGS syscall_arg__scnprintf_msg_flags
644
Arnaldo Carvalho de Melo51108992013-09-04 11:42:27 -0300645static size_t syscall_arg__scnprintf_access_mode(char *bf, size_t size,
646 struct syscall_arg *arg)
647{
648 size_t printed = 0;
649 int mode = arg->val;
650
651 if (mode == F_OK) /* 0 */
652 return scnprintf(bf, size, "F");
653#define P_MODE(n) \
654 if (mode & n##_OK) { \
655 printed += scnprintf(bf + printed, size - printed, "%s", #n); \
656 mode &= ~n##_OK; \
657 }
658
659 P_MODE(R);
660 P_MODE(W);
661 P_MODE(X);
662#undef P_MODE
663
664 if (mode)
665 printed += scnprintf(bf + printed, size - printed, "|%#x", mode);
666
667 return printed;
668}
669
670#define SCA_ACCMODE syscall_arg__scnprintf_access_mode
671
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -0300672static size_t syscall_arg__scnprintf_filename(char *bf, size_t size,
673 struct syscall_arg *arg);
674
675#define SCA_FILENAME syscall_arg__scnprintf_filename
676
Arnaldo Carvalho de Melobe65a892013-09-02 16:22:31 -0300677static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300678 struct syscall_arg *arg)
Arnaldo Carvalho de Melobe65a892013-09-02 16:22:31 -0300679{
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300680 int printed = 0, flags = arg->val;
Arnaldo Carvalho de Melobe65a892013-09-02 16:22:31 -0300681
682 if (!(flags & O_CREAT))
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300683 arg->mask |= 1 << (arg->idx + 1); /* Mask the mode parm */
Arnaldo Carvalho de Melobe65a892013-09-02 16:22:31 -0300684
685 if (flags == 0)
686 return scnprintf(bf, size, "RDONLY");
687#define P_FLAG(n) \
688 if (flags & O_##n) { \
689 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
690 flags &= ~O_##n; \
691 }
692
693 P_FLAG(APPEND);
694 P_FLAG(ASYNC);
695 P_FLAG(CLOEXEC);
696 P_FLAG(CREAT);
697 P_FLAG(DIRECT);
698 P_FLAG(DIRECTORY);
699 P_FLAG(EXCL);
700 P_FLAG(LARGEFILE);
701 P_FLAG(NOATIME);
702 P_FLAG(NOCTTY);
703#ifdef O_NONBLOCK
704 P_FLAG(NONBLOCK);
705#elif O_NDELAY
706 P_FLAG(NDELAY);
707#endif
708#ifdef O_PATH
709 P_FLAG(PATH);
710#endif
711 P_FLAG(RDWR);
712#ifdef O_DSYNC
713 if ((flags & O_SYNC) == O_SYNC)
714 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", "SYNC");
715 else {
716 P_FLAG(DSYNC);
717 }
718#else
719 P_FLAG(SYNC);
720#endif
721 P_FLAG(TRUNC);
722 P_FLAG(WRONLY);
723#undef P_FLAG
724
725 if (flags)
726 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
727
728 return printed;
729}
730
731#define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags
732
Arnaldo Carvalho de Meloa1c25522015-06-11 22:47:54 -0300733static size_t syscall_arg__scnprintf_perf_flags(char *bf, size_t size,
734 struct syscall_arg *arg)
735{
736 int printed = 0, flags = arg->val;
737
738 if (flags == 0)
739 return 0;
740
741#define P_FLAG(n) \
742 if (flags & PERF_FLAG_##n) { \
743 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
744 flags &= ~PERF_FLAG_##n; \
745 }
746
747 P_FLAG(FD_NO_GROUP);
748 P_FLAG(FD_OUTPUT);
749 P_FLAG(PID_CGROUP);
750 P_FLAG(FD_CLOEXEC);
751#undef P_FLAG
752
753 if (flags)
754 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
755
756 return printed;
757}
758
759#define SCA_PERF_FLAGS syscall_arg__scnprintf_perf_flags
760
Arnaldo Carvalho de Melo46cce192013-09-23 12:52:04 -0300761static size_t syscall_arg__scnprintf_pipe_flags(char *bf, size_t size,
762 struct syscall_arg *arg)
763{
764 int printed = 0, flags = arg->val;
765
766#define P_FLAG(n) \
767 if (flags & O_##n) { \
768 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
769 flags &= ~O_##n; \
770 }
771
772 P_FLAG(CLOEXEC);
773 P_FLAG(NONBLOCK);
774#undef P_FLAG
775
776 if (flags)
777 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
778
779 return printed;
780}
781
782#define SCA_PIPE_FLAGS syscall_arg__scnprintf_pipe_flags
783
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -0300784static size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscall_arg *arg)
785{
786 int sig = arg->val;
787
788 switch (sig) {
789#define P_SIGNUM(n) case SIG##n: return scnprintf(bf, size, #n)
790 P_SIGNUM(HUP);
791 P_SIGNUM(INT);
792 P_SIGNUM(QUIT);
793 P_SIGNUM(ILL);
794 P_SIGNUM(TRAP);
795 P_SIGNUM(ABRT);
796 P_SIGNUM(BUS);
797 P_SIGNUM(FPE);
798 P_SIGNUM(KILL);
799 P_SIGNUM(USR1);
800 P_SIGNUM(SEGV);
801 P_SIGNUM(USR2);
802 P_SIGNUM(PIPE);
803 P_SIGNUM(ALRM);
804 P_SIGNUM(TERM);
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -0300805 P_SIGNUM(CHLD);
806 P_SIGNUM(CONT);
807 P_SIGNUM(STOP);
808 P_SIGNUM(TSTP);
809 P_SIGNUM(TTIN);
810 P_SIGNUM(TTOU);
811 P_SIGNUM(URG);
812 P_SIGNUM(XCPU);
813 P_SIGNUM(XFSZ);
814 P_SIGNUM(VTALRM);
815 P_SIGNUM(PROF);
816 P_SIGNUM(WINCH);
817 P_SIGNUM(IO);
818 P_SIGNUM(PWR);
819 P_SIGNUM(SYS);
Ben Hutchings02c5bb42014-02-06 01:00:41 +0000820#ifdef SIGEMT
821 P_SIGNUM(EMT);
822#endif
823#ifdef SIGSTKFLT
824 P_SIGNUM(STKFLT);
825#endif
826#ifdef SIGSWI
827 P_SIGNUM(SWI);
828#endif
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -0300829 default: break;
830 }
831
832 return scnprintf(bf, size, "%#x", sig);
833}
834
835#define SCA_SIGNUM syscall_arg__scnprintf_signum
836
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -0300837#if defined(__i386__) || defined(__x86_64__)
838/*
839 * FIXME: Make this available to all arches.
840 */
Arnaldo Carvalho de Melo78645cf2013-10-08 17:43:20 -0300841#define TCGETS 0x5401
842
843static const char *tioctls[] = {
844 "TCGETS", "TCSETS", "TCSETSW", "TCSETSF", "TCGETA", "TCSETA", "TCSETAW",
845 "TCSETAF", "TCSBRK", "TCXONC", "TCFLSH", "TIOCEXCL", "TIOCNXCL",
846 "TIOCSCTTY", "TIOCGPGRP", "TIOCSPGRP", "TIOCOUTQ", "TIOCSTI",
847 "TIOCGWINSZ", "TIOCSWINSZ", "TIOCMGET", "TIOCMBIS", "TIOCMBIC",
848 "TIOCMSET", "TIOCGSOFTCAR", "TIOCSSOFTCAR", "FIONREAD", "TIOCLINUX",
849 "TIOCCONS", "TIOCGSERIAL", "TIOCSSERIAL", "TIOCPKT", "FIONBIO",
850 "TIOCNOTTY", "TIOCSETD", "TIOCGETD", "TCSBRKP", [0x27] = "TIOCSBRK",
851 "TIOCCBRK", "TIOCGSID", "TCGETS2", "TCSETS2", "TCSETSW2", "TCSETSF2",
852 "TIOCGRS485", "TIOCSRS485", "TIOCGPTN", "TIOCSPTLCK",
853 "TIOCGDEV||TCGETX", "TCSETX", "TCSETXF", "TCSETXW", "TIOCSIG",
854 "TIOCVHANGUP", "TIOCGPKT", "TIOCGPTLCK", "TIOCGEXCL",
855 [0x50] = "FIONCLEX", "FIOCLEX", "FIOASYNC", "TIOCSERCONFIG",
856 "TIOCSERGWILD", "TIOCSERSWILD", "TIOCGLCKTRMIOS", "TIOCSLCKTRMIOS",
857 "TIOCSERGSTRUCT", "TIOCSERGETLSR", "TIOCSERGETMULTI", "TIOCSERSETMULTI",
858 "TIOCMIWAIT", "TIOCGICOUNT", [0x60] = "FIOQSIZE",
859};
860
861static DEFINE_STRARRAY_OFFSET(tioctls, 0x5401);
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -0300862#endif /* defined(__i386__) || defined(__x86_64__) */
Arnaldo Carvalho de Melo78645cf2013-10-08 17:43:20 -0300863
Arnaldo Carvalho de Melo6fb35b92016-04-13 11:50:23 -0300864#ifndef SECCOMP_SET_MODE_STRICT
865#define SECCOMP_SET_MODE_STRICT 0
866#endif
867#ifndef SECCOMP_SET_MODE_FILTER
868#define SECCOMP_SET_MODE_FILTER 1
869#endif
870
Arnaldo Carvalho de Melo997bba82016-03-30 19:43:32 -0300871static size_t syscall_arg__scnprintf_seccomp_op(char *bf, size_t size, struct syscall_arg *arg)
872{
873 int op = arg->val;
874 size_t printed = 0;
875
876 switch (op) {
877#define P_SECCOMP_SET_MODE_OP(n) case SECCOMP_SET_MODE_##n: printed = scnprintf(bf, size, #n); break
878 P_SECCOMP_SET_MODE_OP(STRICT);
879 P_SECCOMP_SET_MODE_OP(FILTER);
880#undef P_SECCOMP_SET_MODE_OP
881 default: printed = scnprintf(bf, size, "%#x", op); break;
882 }
883
884 return printed;
885}
886
887#define SCA_SECCOMP_OP syscall_arg__scnprintf_seccomp_op
888
Arnaldo Carvalho de Melo6fb35b92016-04-13 11:50:23 -0300889#ifndef SECCOMP_FILTER_FLAG_TSYNC
890#define SECCOMP_FILTER_FLAG_TSYNC 1
891#endif
892
Arnaldo Carvalho de Melo997bba82016-03-30 19:43:32 -0300893static size_t syscall_arg__scnprintf_seccomp_flags(char *bf, size_t size,
894 struct syscall_arg *arg)
895{
896 int printed = 0, flags = arg->val;
897
898#define P_FLAG(n) \
899 if (flags & SECCOMP_FILTER_FLAG_##n) { \
900 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
901 flags &= ~SECCOMP_FILTER_FLAG_##n; \
902 }
903
904 P_FLAG(TSYNC);
905#undef P_FLAG
906
907 if (flags)
908 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
909
910 return printed;
911}
912
913#define SCA_SECCOMP_FLAGS syscall_arg__scnprintf_seccomp_flags
914
Arnaldo Carvalho de Meloa355a612016-04-13 11:55:18 -0300915#ifndef GRND_NONBLOCK
916#define GRND_NONBLOCK 0x0001
917#endif
918#ifndef GRND_RANDOM
919#define GRND_RANDOM 0x0002
920#endif
921
Arnaldo Carvalho de Melo39878d42016-03-30 20:02:15 -0300922static size_t syscall_arg__scnprintf_getrandom_flags(char *bf, size_t size,
923 struct syscall_arg *arg)
924{
925 int printed = 0, flags = arg->val;
926
927#define P_FLAG(n) \
928 if (flags & GRND_##n) { \
929 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
930 flags &= ~GRND_##n; \
931 }
932
933 P_FLAG(RANDOM);
934 P_FLAG(NONBLOCK);
935#undef P_FLAG
936
937 if (flags)
938 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
939
940 return printed;
941}
942
943#define SCA_GETRANDOM_FLAGS syscall_arg__scnprintf_getrandom_flags
944
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300945#define STRARRAY(arg, name, array) \
946 .arg_scnprintf = { [arg] = SCA_STRARRAY, }, \
947 .arg_parm = { [arg] = &strarray__##array, }
948
Arnaldo Carvalho de Meloea8dc3c2016-04-13 12:10:19 -0300949#include "trace/beauty/eventfd.c"
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -0300950#include "trace/beauty/pid.c"
Arnaldo Carvalho de Melodf4cb162016-04-13 12:05:44 -0300951#include "trace/beauty/mmap.c"
Arnaldo Carvalho de Meloba2f22c2016-04-07 12:05:51 -0300952#include "trace/beauty/mode_t.c"
Arnaldo Carvalho de Meloa3bca912016-04-06 12:51:33 -0300953#include "trace/beauty/sched_policy.c"
Arnaldo Carvalho de Melo7206b902016-04-06 14:11:36 -0300954#include "trace/beauty/waitid_options.c"
Arnaldo Carvalho de Meloa3bca912016-04-06 12:51:33 -0300955
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300956static struct syscall_fmt {
957 const char *name;
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -0300958 const char *alias;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300959 size_t (*arg_scnprintf[6])(char *bf, size_t size, struct syscall_arg *arg);
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300960 void *arg_parm[6];
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300961 bool errmsg;
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -0300962 bool errpid;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300963 bool timeout;
Arnaldo Carvalho de Melo04b34722013-08-26 11:36:30 -0300964 bool hexret;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300965} syscall_fmts[] = {
Arnaldo Carvalho de Melo51108992013-09-04 11:42:27 -0300966 { .name = "access", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300967 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */
968 [1] = SCA_ACCMODE, /* mode */ }, },
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -0300969 { .name = "arch_prctl", .errmsg = true, .alias = "prctl", },
Arnaldo Carvalho de Melo729a7842015-10-29 11:48:18 -0300970 { .name = "bpf", .errmsg = true, STRARRAY(0, cmd, bpf_cmd), },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -0300971 { .name = "brk", .hexret = true,
972 .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300973 { .name = "chdir", .errmsg = true,
974 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
975 { .name = "chmod", .errmsg = true,
976 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
977 { .name = "chroot", .errmsg = true,
978 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
David Ahern4f8c1b72013-09-22 19:45:00 -0600979 { .name = "clock_gettime", .errmsg = true, STRARRAY(0, clk_id, clockid), },
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -0300980 { .name = "clone", .errpid = true, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300981 { .name = "close", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300982 .arg_scnprintf = { [0] = SCA_CLOSE_FD, /* fd */ }, },
Arnaldo Carvalho de Meloa14bb862013-07-30 16:38:23 -0300983 { .name = "connect", .errmsg = true, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300984 { .name = "creat", .errmsg = true,
985 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300986 { .name = "dup", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300987 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300988 { .name = "dup2", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300989 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300990 { .name = "dup3", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300991 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300992 { .name = "epoll_ctl", .errmsg = true, STRARRAY(1, op, epoll_ctl_ops), },
Arnaldo Carvalho de Melo49af9e92013-09-12 12:18:56 -0300993 { .name = "eventfd2", .errmsg = true,
994 .arg_scnprintf = { [1] = SCA_EFD_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300995 { .name = "faccessat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300996 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
997 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300998 { .name = "fadvise64", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300999 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001000 { .name = "fallocate", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001001 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001002 { .name = "fchdir", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001003 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001004 { .name = "fchmod", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001005 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001006 { .name = "fchmodat", .errmsg = true,
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -03001007 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */
1008 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001009 { .name = "fchown", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001010 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001011 { .name = "fchownat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001012 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */
1013 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001014 { .name = "fcntl", .errmsg = true,
1015 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1016 [1] = SCA_STRARRAY, /* cmd */ },
1017 .arg_parm = { [1] = &strarray__fcntl_cmds, /* cmd */ }, },
1018 { .name = "fdatasync", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001019 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo5cea6ff2013-09-20 11:49:50 -03001020 { .name = "flock", .errmsg = true,
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001021 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1022 [1] = SCA_FLOCK, /* cmd */ }, },
1023 { .name = "fsetxattr", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001024 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001025 { .name = "fstat", .errmsg = true, .alias = "newfstat",
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001026 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001027 { .name = "fstatat", .errmsg = true, .alias = "newfstatat",
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001028 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
1029 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001030 { .name = "fstatfs", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001031 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001032 { .name = "fsync", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001033 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001034 { .name = "ftruncate", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001035 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -03001036 { .name = "futex", .errmsg = true,
1037 .arg_scnprintf = { [1] = SCA_FUTEX_OP, /* op */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001038 { .name = "futimesat", .errmsg = true,
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -03001039 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */
1040 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001041 { .name = "getdents", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001042 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001043 { .name = "getdents64", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001044 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -03001045 { .name = "getitimer", .errmsg = true, STRARRAY(0, which, itimers), },
Arnaldo Carvalho de Meloc65f1072016-04-06 14:55:18 -03001046 { .name = "getpid", .errpid = true, },
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -03001047 { .name = "getpgid", .errpid = true, },
Arnaldo Carvalho de Meloc65f1072016-04-06 14:55:18 -03001048 { .name = "getppid", .errpid = true, },
Arnaldo Carvalho de Melo39878d42016-03-30 20:02:15 -03001049 { .name = "getrandom", .errmsg = true,
1050 .arg_scnprintf = { [2] = SCA_GETRANDOM_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -03001051 { .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001052 { .name = "getxattr", .errmsg = true,
1053 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
1054 { .name = "inotify_add_watch", .errmsg = true,
1055 .arg_scnprintf = { [1] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -03001056 { .name = "ioctl", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001057 .arg_scnprintf = { [0] = SCA_FD, /* fd */
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -03001058#if defined(__i386__) || defined(__x86_64__)
1059/*
1060 * FIXME: Make this available to all arches.
1061 */
Arnaldo Carvalho de Melo78645cf2013-10-08 17:43:20 -03001062 [1] = SCA_STRHEXARRAY, /* cmd */
1063 [2] = SCA_HEX, /* arg */ },
1064 .arg_parm = { [1] = &strarray__tioctls, /* cmd */ }, },
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -03001065#else
1066 [2] = SCA_HEX, /* arg */ }, },
1067#endif
Arnaldo Carvalho de Melob62bee12015-08-11 11:05:36 -03001068 { .name = "keyctl", .errmsg = true, STRARRAY(0, option, keyctl_options), },
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -03001069 { .name = "kill", .errmsg = true,
1070 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001071 { .name = "lchown", .errmsg = true,
1072 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
1073 { .name = "lgetxattr", .errmsg = true,
1074 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001075 { .name = "linkat", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001076 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001077 { .name = "listxattr", .errmsg = true,
1078 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -03001079 { .name = "llistxattr", .errmsg = true,
1080 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
1081 { .name = "lremovexattr", .errmsg = true,
1082 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001083 { .name = "lseek", .errmsg = true,
1084 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1085 [2] = SCA_STRARRAY, /* whence */ },
1086 .arg_parm = { [2] = &strarray__whences, /* whence */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001087 { .name = "lsetxattr", .errmsg = true,
1088 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -03001089 { .name = "lstat", .errmsg = true, .alias = "newlstat",
1090 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001091 { .name = "lsxattr", .errmsg = true,
1092 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo9e9716d2013-08-23 10:06:41 -03001093 { .name = "madvise", .errmsg = true,
1094 .arg_scnprintf = { [0] = SCA_HEX, /* start */
1095 [2] = SCA_MADV_BHV, /* behavior */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001096 { .name = "mkdir", .errmsg = true,
1097 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001098 { .name = "mkdirat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001099 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */
1100 [1] = SCA_FILENAME, /* pathname */ }, },
1101 { .name = "mknod", .errmsg = true,
1102 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001103 { .name = "mknodat", .errmsg = true,
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -03001104 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */
1105 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo3d903aa2013-09-24 00:09:38 -03001106 { .name = "mlock", .errmsg = true,
1107 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
1108 { .name = "mlockall", .errmsg = true,
1109 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -03001110 { .name = "mmap", .hexret = true,
Arnaldo Carvalho de Meloae685382013-08-20 17:44:42 -03001111 .arg_scnprintf = { [0] = SCA_HEX, /* addr */
Arnaldo Carvalho de Melo941557e2013-08-23 10:48:33 -03001112 [2] = SCA_MMAP_PROT, /* prot */
Namhyung Kim73faab32013-11-12 15:24:59 +09001113 [3] = SCA_MMAP_FLAGS, /* flags */
1114 [4] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -03001115 { .name = "mprotect", .errmsg = true,
Arnaldo Carvalho de Meloae685382013-08-20 17:44:42 -03001116 .arg_scnprintf = { [0] = SCA_HEX, /* start */
1117 [2] = SCA_MMAP_PROT, /* prot */ }, },
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -03001118 { .name = "mq_unlink", .errmsg = true,
1119 .arg_scnprintf = { [0] = SCA_FILENAME, /* u_name */ }, },
Arnaldo Carvalho de Meloae685382013-08-20 17:44:42 -03001120 { .name = "mremap", .hexret = true,
1121 .arg_scnprintf = { [0] = SCA_HEX, /* addr */
Alex Snast86998dd2014-08-13 18:42:40 +03001122 [3] = SCA_MREMAP_FLAGS, /* flags */
Arnaldo Carvalho de Meloae685382013-08-20 17:44:42 -03001123 [4] = SCA_HEX, /* new_addr */ }, },
Arnaldo Carvalho de Melo3d903aa2013-09-24 00:09:38 -03001124 { .name = "munlock", .errmsg = true,
1125 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -03001126 { .name = "munmap", .errmsg = true,
1127 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001128 { .name = "name_to_handle_at", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001129 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001130 { .name = "newfstatat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001131 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
1132 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melobe65a892013-09-02 16:22:31 -03001133 { .name = "open", .errmsg = true,
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001134 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */
1135 [1] = SCA_OPEN_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo31cd3852013-09-02 16:40:40 -03001136 { .name = "open_by_handle_at", .errmsg = true,
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001137 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
1138 [2] = SCA_OPEN_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo31cd3852013-09-02 16:40:40 -03001139 { .name = "openat", .errmsg = true,
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001140 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001141 [1] = SCA_FILENAME, /* filename */
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001142 [2] = SCA_OPEN_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Meloa1c25522015-06-11 22:47:54 -03001143 { .name = "perf_event_open", .errmsg = true,
1144 .arg_scnprintf = { [1] = SCA_INT, /* pid */
1145 [2] = SCA_INT, /* cpu */
1146 [3] = SCA_FD, /* group_fd */
1147 [4] = SCA_PERF_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo46cce192013-09-23 12:52:04 -03001148 { .name = "pipe2", .errmsg = true,
1149 .arg_scnprintf = { [1] = SCA_PIPE_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -03001150 { .name = "poll", .errmsg = true, .timeout = true, },
1151 { .name = "ppoll", .errmsg = true, .timeout = true, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001152 { .name = "pread", .errmsg = true, .alias = "pread64",
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001153 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001154 { .name = "preadv", .errmsg = true, .alias = "pread",
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001155 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -03001156 { .name = "prlimit64", .errmsg = true, STRARRAY(1, resource, rlimit_resources), },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001157 { .name = "pwrite", .errmsg = true, .alias = "pwrite64",
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001158 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001159 { .name = "pwritev", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001160 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001161 { .name = "read", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001162 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001163 { .name = "readlink", .errmsg = true,
1164 .arg_scnprintf = { [0] = SCA_FILENAME, /* path */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001165 { .name = "readlinkat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001166 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
1167 [1] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001168 { .name = "readv", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001169 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -03001170 { .name = "recvfrom", .errmsg = true,
Arnaldo Carvalho de Melo8d8c66a2015-08-11 10:57:02 -03001171 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1172 [3] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -03001173 { .name = "recvmmsg", .errmsg = true,
Arnaldo Carvalho de Melo8d8c66a2015-08-11 10:57:02 -03001174 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1175 [3] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -03001176 { .name = "recvmsg", .errmsg = true,
Arnaldo Carvalho de Melo8d8c66a2015-08-11 10:57:02 -03001177 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1178 [2] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001179 { .name = "removexattr", .errmsg = true,
1180 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001181 { .name = "renameat", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001182 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001183 { .name = "rmdir", .errmsg = true,
1184 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -03001185 { .name = "rt_sigaction", .errmsg = true,
1186 .arg_scnprintf = { [0] = SCA_SIGNUM, /* sig */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -03001187 { .name = "rt_sigprocmask", .errmsg = true, STRARRAY(0, how, sighow), },
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -03001188 { .name = "rt_sigqueueinfo", .errmsg = true,
1189 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
1190 { .name = "rt_tgsigqueueinfo", .errmsg = true,
1191 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
Arnaldo Carvalho de Meloa3bca912016-04-06 12:51:33 -03001192 { .name = "sched_setscheduler", .errmsg = true,
1193 .arg_scnprintf = { [1] = SCA_SCHED_POLICY, /* policy */ }, },
Arnaldo Carvalho de Melo997bba82016-03-30 19:43:32 -03001194 { .name = "seccomp", .errmsg = true,
1195 .arg_scnprintf = { [0] = SCA_SECCOMP_OP, /* op */
1196 [1] = SCA_SECCOMP_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -03001197 { .name = "select", .errmsg = true, .timeout = true, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -03001198 { .name = "sendmmsg", .errmsg = true,
Arnaldo Carvalho de Melo8d8c66a2015-08-11 10:57:02 -03001199 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1200 [3] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -03001201 { .name = "sendmsg", .errmsg = true,
Arnaldo Carvalho de Melo8d8c66a2015-08-11 10:57:02 -03001202 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1203 [2] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -03001204 { .name = "sendto", .errmsg = true,
Arnaldo Carvalho de Melo8d8c66a2015-08-11 10:57:02 -03001205 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1206 [3] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Meloc65f1072016-04-06 14:55:18 -03001207 { .name = "set_tid_address", .errpid = true, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -03001208 { .name = "setitimer", .errmsg = true, STRARRAY(0, which, itimers), },
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -03001209 { .name = "setpgid", .errmsg = true, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -03001210 { .name = "setrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001211 { .name = "setxattr", .errmsg = true,
1212 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001213 { .name = "shutdown", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001214 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Meloe10bce82013-09-04 10:27:41 -03001215 { .name = "socket", .errmsg = true,
Arnaldo Carvalho de Meloa28b24b2013-09-04 11:00:44 -03001216 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
1217 [1] = SCA_SK_TYPE, /* type */ },
Arnaldo Carvalho de Meloe10bce82013-09-04 10:27:41 -03001218 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, },
Arnaldo Carvalho de Melo07120aa2013-09-20 12:24:20 -03001219 { .name = "socketpair", .errmsg = true,
1220 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
1221 [1] = SCA_SK_TYPE, /* type */ },
1222 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, },
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -03001223 { .name = "stat", .errmsg = true, .alias = "newstat",
1224 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001225 { .name = "statfs", .errmsg = true,
1226 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
1227 { .name = "swapoff", .errmsg = true,
1228 .arg_scnprintf = { [0] = SCA_FILENAME, /* specialfile */ }, },
1229 { .name = "swapon", .errmsg = true,
1230 .arg_scnprintf = { [0] = SCA_FILENAME, /* specialfile */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001231 { .name = "symlinkat", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001232 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -03001233 { .name = "tgkill", .errmsg = true,
1234 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
1235 { .name = "tkill", .errmsg = true,
1236 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001237 { .name = "truncate", .errmsg = true,
1238 .arg_scnprintf = { [0] = SCA_FILENAME, /* path */ }, },
Arnaldo Carvalho de Meloe5959682013-08-26 12:21:41 -03001239 { .name = "uname", .errmsg = true, .alias = "newuname", },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001240 { .name = "unlinkat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001241 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
1242 [1] = SCA_FILENAME, /* pathname */ }, },
1243 { .name = "utime", .errmsg = true,
1244 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001245 { .name = "utimensat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001246 .arg_scnprintf = { [0] = SCA_FDAT, /* dirfd */
1247 [1] = SCA_FILENAME, /* filename */ }, },
1248 { .name = "utimes", .errmsg = true,
1249 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -03001250 { .name = "vmsplice", .errmsg = true,
1251 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -03001252 { .name = "wait4", .errpid = true,
Arnaldo Carvalho de Melo7206b902016-04-06 14:11:36 -03001253 .arg_scnprintf = { [2] = SCA_WAITID_OPTIONS, /* options */ }, },
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -03001254 { .name = "waitid", .errpid = true,
Arnaldo Carvalho de Melo7206b902016-04-06 14:11:36 -03001255 .arg_scnprintf = { [3] = SCA_WAITID_OPTIONS, /* options */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001256 { .name = "write", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001257 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001258 { .name = "writev", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001259 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001260};
1261
1262static int syscall_fmt__cmp(const void *name, const void *fmtp)
1263{
1264 const struct syscall_fmt *fmt = fmtp;
1265 return strcmp(name, fmt->name);
1266}
1267
1268static struct syscall_fmt *syscall_fmt__find(const char *name)
1269{
1270 const int nmemb = ARRAY_SIZE(syscall_fmts);
1271 return bsearch(name, syscall_fmts, nmemb, sizeof(struct syscall_fmt), syscall_fmt__cmp);
1272}
1273
1274struct syscall {
1275 struct event_format *tp_format;
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001276 int nr_args;
1277 struct format_field *args;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001278 const char *name;
Arnaldo Carvalho de Melo5089f202014-06-17 14:29:24 -03001279 bool is_exit;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001280 struct syscall_fmt *fmt;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001281 size_t (**arg_scnprintf)(char *bf, size_t size, struct syscall_arg *arg);
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -03001282 void **arg_parm;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001283};
1284
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001285static size_t fprintf_duration(unsigned long t, FILE *fp)
1286{
1287 double duration = (double)t / NSEC_PER_MSEC;
1288 size_t printed = fprintf(fp, "(");
1289
1290 if (duration >= 1.0)
1291 printed += color_fprintf(fp, PERF_COLOR_RED, "%6.3f ms", duration);
1292 else if (duration >= 0.01)
1293 printed += color_fprintf(fp, PERF_COLOR_YELLOW, "%6.3f ms", duration);
1294 else
1295 printed += color_fprintf(fp, PERF_COLOR_NORMAL, "%6.3f ms", duration);
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001296 return printed + fprintf(fp, "): ");
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001297}
1298
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001299/**
1300 * filename.ptr: The filename char pointer that will be vfs_getname'd
1301 * filename.entry_str_pos: Where to insert the string translated from
1302 * filename.ptr by the vfs_getname tracepoint/kprobe.
1303 */
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001304struct thread_trace {
1305 u64 entry_time;
1306 u64 exit_time;
1307 bool entry_pending;
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03001308 unsigned long nr_events;
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04001309 unsigned long pfmaj, pfmin;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001310 char *entry_str;
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001311 double runtime_ms;
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001312 struct {
1313 unsigned long ptr;
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03001314 short int entry_str_pos;
1315 bool pending_open;
1316 unsigned int namelen;
1317 char *name;
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001318 } filename;
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001319 struct {
1320 int max;
1321 char **table;
1322 } paths;
David Ahernbf2575c2013-10-08 21:26:53 -06001323
1324 struct intlist *syscall_stats;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001325};
1326
1327static struct thread_trace *thread_trace__new(void)
1328{
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001329 struct thread_trace *ttrace = zalloc(sizeof(struct thread_trace));
1330
1331 if (ttrace)
1332 ttrace->paths.max = -1;
1333
David Ahernbf2575c2013-10-08 21:26:53 -06001334 ttrace->syscall_stats = intlist__new(NULL);
1335
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001336 return ttrace;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001337}
1338
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001339static struct thread_trace *thread__trace(struct thread *thread, FILE *fp)
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001340{
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03001341 struct thread_trace *ttrace;
1342
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001343 if (thread == NULL)
1344 goto fail;
1345
Namhyung Kim89dceb22014-10-06 09:46:03 +09001346 if (thread__priv(thread) == NULL)
1347 thread__set_priv(thread, thread_trace__new());
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001348
Namhyung Kim89dceb22014-10-06 09:46:03 +09001349 if (thread__priv(thread) == NULL)
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001350 goto fail;
1351
Namhyung Kim89dceb22014-10-06 09:46:03 +09001352 ttrace = thread__priv(thread);
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03001353 ++ttrace->nr_events;
1354
1355 return ttrace;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001356fail:
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001357 color_fprintf(fp, PERF_COLOR_RED,
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001358 "WARNING: not enough memory, dropping samples!\n");
1359 return NULL;
1360}
1361
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04001362#define TRACE_PFMAJ (1 << 0)
1363#define TRACE_PFMIN (1 << 1)
1364
Arnaldo Carvalho de Meloe4d44e82015-08-04 22:17:29 -03001365static const size_t trace__entry_str_size = 2048;
1366
Arnaldo Carvalho de Melo97119f32013-09-27 17:34:10 -03001367static int trace__set_fd_pathname(struct thread *thread, int fd, const char *pathname)
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001368{
Namhyung Kim89dceb22014-10-06 09:46:03 +09001369 struct thread_trace *ttrace = thread__priv(thread);
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001370
1371 if (fd > ttrace->paths.max) {
1372 char **npath = realloc(ttrace->paths.table, (fd + 1) * sizeof(char *));
1373
1374 if (npath == NULL)
1375 return -1;
1376
1377 if (ttrace->paths.max != -1) {
1378 memset(npath + ttrace->paths.max + 1, 0,
1379 (fd - ttrace->paths.max) * sizeof(char *));
1380 } else {
1381 memset(npath, 0, (fd + 1) * sizeof(char *));
1382 }
1383
1384 ttrace->paths.table = npath;
1385 ttrace->paths.max = fd;
1386 }
1387
1388 ttrace->paths.table[fd] = strdup(pathname);
1389
1390 return ttrace->paths.table[fd] != NULL ? 0 : -1;
1391}
1392
Arnaldo Carvalho de Melo97119f32013-09-27 17:34:10 -03001393static int thread__read_fd_path(struct thread *thread, int fd)
1394{
1395 char linkname[PATH_MAX], pathname[PATH_MAX];
1396 struct stat st;
1397 int ret;
1398
1399 if (thread->pid_ == thread->tid) {
1400 scnprintf(linkname, sizeof(linkname),
1401 "/proc/%d/fd/%d", thread->pid_, fd);
1402 } else {
1403 scnprintf(linkname, sizeof(linkname),
1404 "/proc/%d/task/%d/fd/%d", thread->pid_, thread->tid, fd);
1405 }
1406
1407 if (lstat(linkname, &st) < 0 || st.st_size + 1 > (off_t)sizeof(pathname))
1408 return -1;
1409
1410 ret = readlink(linkname, pathname, sizeof(pathname));
1411
1412 if (ret < 0 || ret > st.st_size)
1413 return -1;
1414
1415 pathname[ret] = '\0';
1416 return trace__set_fd_pathname(thread, fd, pathname);
1417}
1418
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001419static const char *thread__fd_path(struct thread *thread, int fd,
1420 struct trace *trace)
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001421{
Namhyung Kim89dceb22014-10-06 09:46:03 +09001422 struct thread_trace *ttrace = thread__priv(thread);
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001423
1424 if (ttrace == NULL)
1425 return NULL;
1426
1427 if (fd < 0)
1428 return NULL;
1429
Arnaldo Carvalho de Melocdcd1e62014-06-10 16:00:18 -03001430 if ((fd > ttrace->paths.max || ttrace->paths.table[fd] == NULL)) {
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001431 if (!trace->live)
1432 return NULL;
1433 ++trace->stats.proc_getname;
Arnaldo Carvalho de Melocdcd1e62014-06-10 16:00:18 -03001434 if (thread__read_fd_path(thread, fd))
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001435 return NULL;
1436 }
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001437
1438 return ttrace->paths.table[fd];
1439}
1440
1441static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
1442 struct syscall_arg *arg)
1443{
1444 int fd = arg->val;
1445 size_t printed = scnprintf(bf, size, "%d", fd);
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001446 const char *path = thread__fd_path(arg->thread, fd, arg->trace);
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001447
1448 if (path)
1449 printed += scnprintf(bf + printed, size - printed, "<%s>", path);
1450
1451 return printed;
1452}
1453
1454static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
1455 struct syscall_arg *arg)
1456{
1457 int fd = arg->val;
1458 size_t printed = syscall_arg__scnprintf_fd(bf, size, arg);
Namhyung Kim89dceb22014-10-06 09:46:03 +09001459 struct thread_trace *ttrace = thread__priv(arg->thread);
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001460
Arnaldo Carvalho de Melo04662522013-12-26 17:41:15 -03001461 if (ttrace && fd >= 0 && fd <= ttrace->paths.max)
1462 zfree(&ttrace->paths.table[fd]);
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001463
1464 return printed;
1465}
1466
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001467static void thread__set_filename_pos(struct thread *thread, const char *bf,
1468 unsigned long ptr)
1469{
1470 struct thread_trace *ttrace = thread__priv(thread);
1471
1472 ttrace->filename.ptr = ptr;
1473 ttrace->filename.entry_str_pos = bf - ttrace->entry_str;
1474}
1475
1476static size_t syscall_arg__scnprintf_filename(char *bf, size_t size,
1477 struct syscall_arg *arg)
1478{
1479 unsigned long ptr = arg->val;
1480
1481 if (!arg->trace->vfs_getname)
1482 return scnprintf(bf, size, "%#x", ptr);
1483
1484 thread__set_filename_pos(arg->thread, bf, ptr);
1485 return 0;
1486}
1487
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001488static bool trace__filter_duration(struct trace *trace, double t)
1489{
1490 return t < (trace->duration_filter * NSEC_PER_MSEC);
1491}
1492
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001493static size_t trace__fprintf_tstamp(struct trace *trace, u64 tstamp, FILE *fp)
1494{
1495 double ts = (double)(tstamp - trace->base_time) / NSEC_PER_MSEC;
1496
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001497 return fprintf(fp, "%10.3f ", ts);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001498}
1499
Namhyung Kimf15eb532012-10-05 14:02:16 +09001500static bool done = false;
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03001501static bool interrupted = false;
Namhyung Kimf15eb532012-10-05 14:02:16 +09001502
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03001503static void sig_handler(int sig)
Namhyung Kimf15eb532012-10-05 14:02:16 +09001504{
1505 done = true;
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03001506 interrupted = sig == SIGINT;
Namhyung Kimf15eb532012-10-05 14:02:16 +09001507}
1508
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001509static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thread,
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001510 u64 duration, u64 tstamp, FILE *fp)
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001511{
1512 size_t printed = trace__fprintf_tstamp(trace, tstamp, fp);
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001513 printed += fprintf_duration(duration, fp);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001514
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -03001515 if (trace->multiple_threads) {
1516 if (trace->show_comm)
Frederic Weisbecker1902efe2013-09-11 16:56:44 +02001517 printed += fprintf(fp, "%.14s/", thread__comm_str(thread));
Adrian Hunter38051232013-07-04 16:20:31 +03001518 printed += fprintf(fp, "%d ", thread->tid);
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -03001519 }
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001520
1521 return printed;
1522}
1523
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001524static int trace__process_event(struct trace *trace, struct machine *machine,
Frederic Weisbecker162f0be2013-09-11 16:18:24 +02001525 union perf_event *event, struct perf_sample *sample)
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001526{
1527 int ret = 0;
1528
1529 switch (event->header.type) {
1530 case PERF_RECORD_LOST:
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001531 color_fprintf(trace->output, PERF_COLOR_RED,
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001532 "LOST %" PRIu64 " events!\n", event->lost.lost);
Frederic Weisbecker162f0be2013-09-11 16:18:24 +02001533 ret = machine__process_lost_event(machine, event, sample);
Arnaldo Carvalho de Melo3ed5ca22016-03-30 16:51:17 -03001534 break;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001535 default:
Frederic Weisbecker162f0be2013-09-11 16:18:24 +02001536 ret = machine__process_event(machine, event, sample);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001537 break;
1538 }
1539
1540 return ret;
1541}
1542
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001543static int trace__tool_process(struct perf_tool *tool,
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001544 union perf_event *event,
Frederic Weisbecker162f0be2013-09-11 16:18:24 +02001545 struct perf_sample *sample,
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001546 struct machine *machine)
1547{
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001548 struct trace *trace = container_of(tool, struct trace, tool);
Frederic Weisbecker162f0be2013-09-11 16:18:24 +02001549 return trace__process_event(trace, machine, event, sample);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001550}
1551
1552static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
1553{
Namhyung Kim0a7e6d12014-08-12 15:40:45 +09001554 int err = symbol__init(NULL);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001555
1556 if (err)
1557 return err;
1558
David Ahern8fb598e2013-09-28 13:13:00 -06001559 trace->host = machine__new_host();
1560 if (trace->host == NULL)
1561 return -ENOMEM;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001562
Arnaldo Carvalho de Melo959c2192015-07-24 12:13:05 -03001563 if (trace_event__register_resolver(trace->host, machine__resolve_kernel_addr) < 0)
Arnaldo Carvalho de Melo706c3da2015-07-22 16:16:16 -03001564 return -errno;
1565
Arnaldo Carvalho de Meloa33fbd52013-11-11 11:36:12 -03001566 err = __machine__synthesize_threads(trace->host, &trace->tool, &trace->opts.target,
Kan Liang9d9cad72015-06-17 09:51:11 -04001567 evlist->threads, trace__tool_process, false,
1568 trace->opts.proc_map_timeout);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001569 if (err)
1570 symbol__exit();
1571
1572 return err;
1573}
1574
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001575static int syscall__set_arg_fmts(struct syscall *sc)
1576{
1577 struct format_field *field;
1578 int idx = 0;
1579
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001580 sc->arg_scnprintf = calloc(sc->nr_args, sizeof(void *));
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001581 if (sc->arg_scnprintf == NULL)
1582 return -1;
1583
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -03001584 if (sc->fmt)
1585 sc->arg_parm = sc->fmt->arg_parm;
1586
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001587 for (field = sc->args; field; field = field->next) {
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -03001588 if (sc->fmt && sc->fmt->arg_scnprintf[idx])
1589 sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx];
1590 else if (field->flags & FIELD_IS_POINTER)
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001591 sc->arg_scnprintf[idx] = syscall_arg__scnprintf_hex;
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -03001592 else if (strcmp(field->type, "pid_t") == 0)
1593 sc->arg_scnprintf[idx] = SCA_PID;
Arnaldo Carvalho de Meloba2f22c2016-04-07 12:05:51 -03001594 else if (strcmp(field->type, "umode_t") == 0)
1595 sc->arg_scnprintf[idx] = SCA_MODE_T;
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001596 ++idx;
1597 }
1598
1599 return 0;
1600}
1601
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001602static int trace__read_syscall_info(struct trace *trace, int id)
1603{
1604 char tp_name[128];
1605 struct syscall *sc;
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03001606 const char *name = syscalltbl__name(trace->sctbl, id);
Arnaldo Carvalho de Melo3a531262012-10-20 12:39:03 -03001607
1608 if (name == NULL)
1609 return -1;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001610
1611 if (id > trace->syscalls.max) {
1612 struct syscall *nsyscalls = realloc(trace->syscalls.table, (id + 1) * sizeof(*sc));
1613
1614 if (nsyscalls == NULL)
1615 return -1;
1616
1617 if (trace->syscalls.max != -1) {
1618 memset(nsyscalls + trace->syscalls.max + 1, 0,
1619 (id - trace->syscalls.max) * sizeof(*sc));
1620 } else {
1621 memset(nsyscalls, 0, (id + 1) * sizeof(*sc));
1622 }
1623
1624 trace->syscalls.table = nsyscalls;
1625 trace->syscalls.max = id;
1626 }
1627
1628 sc = trace->syscalls.table + id;
Arnaldo Carvalho de Melo3a531262012-10-20 12:39:03 -03001629 sc->name = name;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001630
Arnaldo Carvalho de Melo3a531262012-10-20 12:39:03 -03001631 sc->fmt = syscall_fmt__find(sc->name);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001632
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -03001633 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name);
Jiri Olsa97978b32013-12-03 14:09:24 +01001634 sc->tp_format = trace_event__tp_format("syscalls", tp_name);
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -03001635
Jiri Olsa8dd2a132015-09-07 10:38:06 +02001636 if (IS_ERR(sc->tp_format) && sc->fmt && sc->fmt->alias) {
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -03001637 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->fmt->alias);
Jiri Olsa97978b32013-12-03 14:09:24 +01001638 sc->tp_format = trace_event__tp_format("syscalls", tp_name);
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -03001639 }
1640
Jiri Olsa8dd2a132015-09-07 10:38:06 +02001641 if (IS_ERR(sc->tp_format))
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001642 return -1;
1643
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001644 sc->args = sc->tp_format->format.fields;
1645 sc->nr_args = sc->tp_format->format.nr_fields;
Taeung Songc42de702016-02-26 22:14:25 +09001646 /*
1647 * We need to check and discard the first variable '__syscall_nr'
1648 * or 'nr' that mean the syscall number. It is needless here.
1649 * So drop '__syscall_nr' or 'nr' field but does not exist on older kernels.
1650 */
1651 if (sc->args && (!strcmp(sc->args->name, "__syscall_nr") || !strcmp(sc->args->name, "nr"))) {
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001652 sc->args = sc->args->next;
1653 --sc->nr_args;
1654 }
1655
Arnaldo Carvalho de Melo5089f202014-06-17 14:29:24 -03001656 sc->is_exit = !strcmp(name, "exit_group") || !strcmp(name, "exit");
1657
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001658 return syscall__set_arg_fmts(sc);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001659}
1660
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001661static int trace__validate_ev_qualifier(struct trace *trace)
1662{
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001663 int err = 0, i;
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001664 struct str_node *pos;
1665
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001666 trace->ev_qualifier_ids.nr = strlist__nr_entries(trace->ev_qualifier);
1667 trace->ev_qualifier_ids.entries = malloc(trace->ev_qualifier_ids.nr *
1668 sizeof(trace->ev_qualifier_ids.entries[0]));
1669
1670 if (trace->ev_qualifier_ids.entries == NULL) {
1671 fputs("Error:\tNot enough memory for allocating events qualifier ids\n",
1672 trace->output);
1673 err = -EINVAL;
1674 goto out;
1675 }
1676
1677 i = 0;
1678
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001679 strlist__for_each(pos, trace->ev_qualifier) {
1680 const char *sc = pos->s;
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03001681 int id = syscalltbl__id(trace->sctbl, sc);
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001682
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001683 if (id < 0) {
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001684 if (err == 0) {
1685 fputs("Error:\tInvalid syscall ", trace->output);
1686 err = -EINVAL;
1687 } else {
1688 fputs(", ", trace->output);
1689 }
1690
1691 fputs(sc, trace->output);
1692 }
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001693
1694 trace->ev_qualifier_ids.entries[i++] = id;
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001695 }
1696
1697 if (err < 0) {
1698 fputs("\nHint:\ttry 'perf list syscalls:sys_enter_*'"
1699 "\nHint:\tand: 'man syscalls'\n", trace->output);
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001700 zfree(&trace->ev_qualifier_ids.entries);
1701 trace->ev_qualifier_ids.nr = 0;
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001702 }
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001703out:
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001704 return err;
1705}
1706
David Ahern55d43bc2015-02-19 15:00:22 -05001707/*
1708 * args is to be interpreted as a series of longs but we need to handle
1709 * 8-byte unaligned accesses. args points to raw_data within the event
1710 * and raw_data is guaranteed to be 8-byte unaligned because it is
1711 * preceded by raw_size which is a u32. So we need to copy args to a temp
1712 * variable to read it. Most notably this avoids extended load instructions
1713 * on unaligned addresses
1714 */
1715
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001716static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
David Ahern55d43bc2015-02-19 15:00:22 -05001717 unsigned char *args, struct trace *trace,
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001718 struct thread *thread)
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001719{
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001720 size_t printed = 0;
David Ahern55d43bc2015-02-19 15:00:22 -05001721 unsigned char *p;
1722 unsigned long val;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001723
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001724 if (sc->args != NULL) {
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001725 struct format_field *field;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001726 u8 bit = 1;
1727 struct syscall_arg arg = {
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001728 .idx = 0,
1729 .mask = 0,
1730 .trace = trace,
1731 .thread = thread,
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001732 };
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001733
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001734 for (field = sc->args; field;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001735 field = field->next, ++arg.idx, bit <<= 1) {
1736 if (arg.mask & bit)
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -03001737 continue;
David Ahern55d43bc2015-02-19 15:00:22 -05001738
1739 /* special care for unaligned accesses */
1740 p = args + sizeof(unsigned long) * arg.idx;
1741 memcpy(&val, p, sizeof(val));
1742
Arnaldo Carvalho de Melo4aa58232013-09-20 12:19:41 -03001743 /*
1744 * Suppress this argument if its value is zero and
1745 * and we don't have a string associated in an
1746 * strarray for it.
1747 */
David Ahern55d43bc2015-02-19 15:00:22 -05001748 if (val == 0 &&
Arnaldo Carvalho de Melo4aa58232013-09-20 12:19:41 -03001749 !(sc->arg_scnprintf &&
1750 sc->arg_scnprintf[arg.idx] == SCA_STRARRAY &&
1751 sc->arg_parm[arg.idx]))
Arnaldo Carvalho de Melo22ae5cf12013-09-12 11:27:34 -03001752 continue;
1753
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001754 printed += scnprintf(bf + printed, size - printed,
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001755 "%s%s: ", printed ? ", " : "", field->name);
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001756 if (sc->arg_scnprintf && sc->arg_scnprintf[arg.idx]) {
David Ahern55d43bc2015-02-19 15:00:22 -05001757 arg.val = val;
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -03001758 if (sc->arg_parm)
1759 arg.parm = sc->arg_parm[arg.idx];
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001760 printed += sc->arg_scnprintf[arg.idx](bf + printed,
1761 size - printed, &arg);
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -03001762 } else {
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001763 printed += scnprintf(bf + printed, size - printed,
David Ahern55d43bc2015-02-19 15:00:22 -05001764 "%ld", val);
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -03001765 }
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001766 }
1767 } else {
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001768 int i = 0;
1769
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001770 while (i < 6) {
David Ahern55d43bc2015-02-19 15:00:22 -05001771 /* special care for unaligned accesses */
1772 p = args + sizeof(unsigned long) * i;
1773 memcpy(&val, p, sizeof(val));
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001774 printed += scnprintf(bf + printed, size - printed,
1775 "%sarg%d: %ld",
David Ahern55d43bc2015-02-19 15:00:22 -05001776 printed ? ", " : "", i, val);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001777 ++i;
1778 }
1779 }
1780
1781 return printed;
1782}
1783
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001784typedef int (*tracepoint_handler)(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04001785 union perf_event *event,
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001786 struct perf_sample *sample);
1787
1788static struct syscall *trace__syscall_info(struct trace *trace,
David Ahernbf2575c2013-10-08 21:26:53 -06001789 struct perf_evsel *evsel, int id)
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001790{
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001791
1792 if (id < 0) {
Arnaldo Carvalho de Meloadaa18b2013-08-22 17:55:25 -03001793
1794 /*
1795 * XXX: Noticed on x86_64, reproduced as far back as 3.0.36, haven't tried
1796 * before that, leaving at a higher verbosity level till that is
1797 * explained. Reproduced with plain ftrace with:
1798 *
1799 * echo 1 > /t/events/raw_syscalls/sys_exit/enable
1800 * grep "NR -1 " /t/trace_pipe
1801 *
1802 * After generating some load on the machine.
1803 */
1804 if (verbose > 1) {
1805 static u64 n;
1806 fprintf(trace->output, "Invalid syscall %d id, skipping (%s, %" PRIu64 ") ...\n",
1807 id, perf_evsel__name(evsel), ++n);
1808 }
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001809 return NULL;
1810 }
1811
1812 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL) &&
1813 trace__read_syscall_info(trace, id))
1814 goto out_cant_read;
1815
1816 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL))
1817 goto out_cant_read;
1818
1819 return &trace->syscalls.table[id];
1820
1821out_cant_read:
Arnaldo Carvalho de Melo7c304ee02013-08-22 16:49:54 -03001822 if (verbose) {
1823 fprintf(trace->output, "Problems reading syscall %d", id);
1824 if (id <= trace->syscalls.max && trace->syscalls.table[id].name != NULL)
1825 fprintf(trace->output, "(%s)", trace->syscalls.table[id].name);
1826 fputs(" information\n", trace->output);
1827 }
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001828 return NULL;
1829}
1830
David Ahernbf2575c2013-10-08 21:26:53 -06001831static void thread__update_stats(struct thread_trace *ttrace,
1832 int id, struct perf_sample *sample)
1833{
1834 struct int_node *inode;
1835 struct stats *stats;
1836 u64 duration = 0;
1837
1838 inode = intlist__findnew(ttrace->syscall_stats, id);
1839 if (inode == NULL)
1840 return;
1841
1842 stats = inode->priv;
1843 if (stats == NULL) {
1844 stats = malloc(sizeof(struct stats));
1845 if (stats == NULL)
1846 return;
1847 init_stats(stats);
1848 inode->priv = stats;
1849 }
1850
1851 if (ttrace->entry_time && sample->time > ttrace->entry_time)
1852 duration = sample->time - ttrace->entry_time;
1853
1854 update_stats(stats, duration);
1855}
1856
Arnaldo Carvalho de Meloe5966632015-02-13 13:22:21 -03001857static int trace__printf_interrupted_entry(struct trace *trace, struct perf_sample *sample)
1858{
1859 struct thread_trace *ttrace;
1860 u64 duration;
1861 size_t printed;
1862
1863 if (trace->current == NULL)
1864 return 0;
1865
1866 ttrace = thread__priv(trace->current);
1867
1868 if (!ttrace->entry_pending)
1869 return 0;
1870
1871 duration = sample->time - ttrace->entry_time;
1872
1873 printed = trace__fprintf_entry_head(trace, trace->current, duration, sample->time, trace->output);
1874 printed += fprintf(trace->output, "%-70s) ...\n", ttrace->entry_str);
1875 ttrace->entry_pending = false;
1876
1877 return printed;
1878}
1879
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001880static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04001881 union perf_event *event __maybe_unused,
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001882 struct perf_sample *sample)
1883{
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001884 char *msg;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001885 void *args;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001886 size_t printed = 0;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001887 struct thread *thread;
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001888 int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
David Ahernbf2575c2013-10-08 21:26:53 -06001889 struct syscall *sc = trace__syscall_info(trace, evsel, id);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001890 struct thread_trace *ttrace;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001891
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001892 if (sc == NULL)
1893 return -1;
1894
David Ahern8fb598e2013-09-28 13:13:00 -06001895 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001896 ttrace = thread__trace(thread, trace->output);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001897 if (ttrace == NULL)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001898 goto out_put;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001899
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -03001900 args = perf_evsel__sc_tp_ptr(evsel, args, sample);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001901
1902 if (ttrace->entry_str == NULL) {
Arnaldo Carvalho de Meloe4d44e82015-08-04 22:17:29 -03001903 ttrace->entry_str = malloc(trace__entry_str_size);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001904 if (!ttrace->entry_str)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001905 goto out_put;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001906 }
1907
David Ahern13f22a22015-03-19 12:23:03 -06001908 if (!trace->summary_only)
Arnaldo Carvalho de Melo6ebad5c2015-03-25 18:01:15 -03001909 trace__printf_interrupted_entry(trace, sample);
Arnaldo Carvalho de Meloe5966632015-02-13 13:22:21 -03001910
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001911 ttrace->entry_time = sample->time;
1912 msg = ttrace->entry_str;
Arnaldo Carvalho de Meloe4d44e82015-08-04 22:17:29 -03001913 printed += scnprintf(msg + printed, trace__entry_str_size - printed, "%s(", sc->name);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001914
Arnaldo Carvalho de Meloe4d44e82015-08-04 22:17:29 -03001915 printed += syscall__scnprintf_args(sc, msg + printed, trace__entry_str_size - printed,
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001916 args, trace, thread);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001917
Arnaldo Carvalho de Melo5089f202014-06-17 14:29:24 -03001918 if (sc->is_exit) {
David Ahernfd2eaba2013-11-12 09:31:15 -07001919 if (!trace->duration_filter && !trace->summary_only) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001920 trace__fprintf_entry_head(trace, thread, 1, sample->time, trace->output);
1921 fprintf(trace->output, "%-70s\n", ttrace->entry_str);
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001922 }
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03001923 } else {
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001924 ttrace->entry_pending = true;
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03001925 /* See trace__vfs_getname & trace__sys_exit */
1926 ttrace->filename.pending_open = false;
1927 }
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001928
Arnaldo Carvalho de Melof3b623b2015-03-02 22:21:35 -03001929 if (trace->current != thread) {
1930 thread__put(trace->current);
1931 trace->current = thread__get(thread);
1932 }
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001933 err = 0;
1934out_put:
1935 thread__put(thread);
1936 return err;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001937}
1938
Arnaldo Carvalho de Melo202ff962016-04-12 10:11:07 -03001939static int trace__fprintf_callchain(struct trace *trace, struct perf_evsel *evsel,
1940 struct perf_sample *sample)
1941{
1942 struct addr_location al;
1943 /* TODO: user-configurable print_opts */
Arnaldo Carvalho de Meloe20ab862016-04-12 15:16:15 -03001944 const unsigned int print_opts = EVSEL__PRINT_SYM |
1945 EVSEL__PRINT_DSO |
1946 EVSEL__PRINT_UNKNOWN_AS_ADDR;
Arnaldo Carvalho de Melo202ff962016-04-12 10:11:07 -03001947
1948 if (sample->callchain == NULL)
1949 return 0;
1950
1951 if (machine__resolve(trace->host, &al, sample) < 0) {
1952 pr_err("Problem processing %s callchain, skipping...\n",
1953 perf_evsel__name(evsel));
1954 return 0;
1955 }
1956
1957 return perf_evsel__fprintf_callchain(evsel, sample, &al, 38, print_opts,
1958 scripting_max_stack, trace->output);
1959}
1960
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001961static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04001962 union perf_event *event __maybe_unused,
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001963 struct perf_sample *sample)
1964{
Chang Hyun Park2c82c3a2014-09-26 21:54:01 +09001965 long ret;
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001966 u64 duration = 0;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001967 struct thread *thread;
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001968 int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
David Ahernbf2575c2013-10-08 21:26:53 -06001969 struct syscall *sc = trace__syscall_info(trace, evsel, id);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001970 struct thread_trace *ttrace;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001971
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001972 if (sc == NULL)
1973 return -1;
1974
David Ahern8fb598e2013-09-28 13:13:00 -06001975 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001976 ttrace = thread__trace(thread, trace->output);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001977 if (ttrace == NULL)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001978 goto out_put;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001979
David Ahernbf2575c2013-10-08 21:26:53 -06001980 if (trace->summary)
1981 thread__update_stats(ttrace, id, sample);
1982
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -03001983 ret = perf_evsel__sc_tp_uint(evsel, ret, sample);
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001984
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03001985 if (id == trace->open_id && ret >= 0 && ttrace->filename.pending_open) {
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03001986 trace__set_fd_pathname(thread, ret, ttrace->filename.name);
1987 ttrace->filename.pending_open = false;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001988 ++trace->stats.vfs_getname;
1989 }
1990
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001991 ttrace->exit_time = sample->time;
1992
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001993 if (ttrace->entry_time) {
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001994 duration = sample->time - ttrace->entry_time;
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001995 if (trace__filter_duration(trace, duration))
1996 goto out;
1997 } else if (trace->duration_filter)
1998 goto out;
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001999
David Ahernfd2eaba2013-11-12 09:31:15 -07002000 if (trace->summary_only)
2001 goto out;
2002
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002003 trace__fprintf_entry_head(trace, thread, duration, sample->time, trace->output);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03002004
2005 if (ttrace->entry_pending) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002006 fprintf(trace->output, "%-70s", ttrace->entry_str);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03002007 } else {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002008 fprintf(trace->output, " ... [");
2009 color_fprintf(trace->output, PERF_COLOR_YELLOW, "continued");
2010 fprintf(trace->output, "]: %s()", sc->name);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03002011 }
2012
Arnaldo Carvalho de Meloda3c9a42013-08-26 11:28:34 -03002013 if (sc->fmt == NULL) {
2014signed_print:
Chang Hyun Park2c82c3a2014-09-26 21:54:01 +09002015 fprintf(trace->output, ") = %ld", ret);
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -03002016 } else if (ret < 0 && (sc->fmt->errmsg || sc->fmt->errpid)) {
Masami Hiramatsu942a91e2014-08-14 02:22:41 +00002017 char bf[STRERR_BUFSIZE];
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03002018 const char *emsg = strerror_r(-ret, bf, sizeof(bf)),
2019 *e = audit_errno_to_name(-ret);
2020
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002021 fprintf(trace->output, ") = -1 %s %s", e, emsg);
Arnaldo Carvalho de Meloda3c9a42013-08-26 11:28:34 -03002022 } else if (ret == 0 && sc->fmt->timeout)
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002023 fprintf(trace->output, ") = 0 Timeout");
Arnaldo Carvalho de Melo04b34722013-08-26 11:36:30 -03002024 else if (sc->fmt->hexret)
Chang Hyun Park2c82c3a2014-09-26 21:54:01 +09002025 fprintf(trace->output, ") = %#lx", ret);
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -03002026 else if (sc->fmt->errpid) {
2027 struct thread *child = machine__find_thread(trace->host, ret, ret);
2028
2029 if (child != NULL) {
2030 fprintf(trace->output, ") = %ld", ret);
2031 if (child->comm_set)
2032 fprintf(trace->output, " (%s)", thread__comm_str(child));
2033 thread__put(child);
2034 }
2035 } else
Arnaldo Carvalho de Meloda3c9a42013-08-26 11:28:34 -03002036 goto signed_print;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03002037
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002038 fputc('\n', trace->output);
Milian Wolff566a0882016-04-08 13:34:15 +02002039
Arnaldo Carvalho de Melo202ff962016-04-12 10:11:07 -03002040 trace__fprintf_callchain(trace, evsel, sample);
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03002041out:
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03002042 ttrace->entry_pending = false;
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002043 err = 0;
2044out_put:
2045 thread__put(thread);
2046 return err;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03002047}
2048
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002049static int trace__vfs_getname(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04002050 union perf_event *event __maybe_unused,
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002051 struct perf_sample *sample)
2052{
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03002053 struct thread *thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
2054 struct thread_trace *ttrace;
2055 size_t filename_len, entry_str_len, to_move;
2056 ssize_t remaining_space;
2057 char *pos;
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03002058 const char *filename = perf_evsel__rawptr(evsel, sample, "pathname");
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03002059
2060 if (!thread)
2061 goto out;
2062
2063 ttrace = thread__priv(thread);
2064 if (!ttrace)
2065 goto out;
2066
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03002067 filename_len = strlen(filename);
2068
2069 if (ttrace->filename.namelen < filename_len) {
2070 char *f = realloc(ttrace->filename.name, filename_len + 1);
2071
2072 if (f == NULL)
2073 goto out;
2074
2075 ttrace->filename.namelen = filename_len;
2076 ttrace->filename.name = f;
2077 }
2078
2079 strcpy(ttrace->filename.name, filename);
2080 ttrace->filename.pending_open = true;
2081
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03002082 if (!ttrace->filename.ptr)
2083 goto out;
2084
2085 entry_str_len = strlen(ttrace->entry_str);
2086 remaining_space = trace__entry_str_size - entry_str_len - 1; /* \0 */
2087 if (remaining_space <= 0)
2088 goto out;
2089
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03002090 if (filename_len > (size_t)remaining_space) {
2091 filename += filename_len - remaining_space;
2092 filename_len = remaining_space;
2093 }
2094
2095 to_move = entry_str_len - ttrace->filename.entry_str_pos + 1; /* \0 */
2096 pos = ttrace->entry_str + ttrace->filename.entry_str_pos;
2097 memmove(pos + filename_len, pos, to_move);
2098 memcpy(pos, filename, filename_len);
2099
2100 ttrace->filename.ptr = 0;
2101 ttrace->filename.entry_str_pos = 0;
2102out:
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002103 return 0;
2104}
2105
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002106static int trace__sched_stat_runtime(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04002107 union perf_event *event __maybe_unused,
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002108 struct perf_sample *sample)
2109{
2110 u64 runtime = perf_evsel__intval(evsel, sample, "runtime");
2111 double runtime_ms = (double)runtime / NSEC_PER_MSEC;
David Ahern8fb598e2013-09-28 13:13:00 -06002112 struct thread *thread = machine__findnew_thread(trace->host,
Adrian Hunter314add62013-08-27 11:23:03 +03002113 sample->pid,
2114 sample->tid);
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002115 struct thread_trace *ttrace = thread__trace(thread, trace->output);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002116
2117 if (ttrace == NULL)
2118 goto out_dump;
2119
2120 ttrace->runtime_ms += runtime_ms;
2121 trace->runtime_ms += runtime_ms;
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002122 thread__put(thread);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002123 return 0;
2124
2125out_dump:
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002126 fprintf(trace->output, "%s: comm=%s,pid=%u,runtime=%" PRIu64 ",vruntime=%" PRIu64 ")\n",
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002127 evsel->name,
2128 perf_evsel__strval(evsel, sample, "comm"),
2129 (pid_t)perf_evsel__intval(evsel, sample, "pid"),
2130 runtime,
2131 perf_evsel__intval(evsel, sample, "vruntime"));
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002132 thread__put(thread);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002133 return 0;
2134}
2135
Wang Nan1d6c9402016-02-26 09:31:55 +00002136static void bpf_output__printer(enum binary_printer_ops op,
2137 unsigned int val, void *extra)
2138{
2139 FILE *output = extra;
2140 unsigned char ch = (unsigned char)val;
2141
2142 switch (op) {
2143 case BINARY_PRINT_CHAR_DATA:
2144 fprintf(output, "%c", isprint(ch) ? ch : '.');
2145 break;
2146 case BINARY_PRINT_DATA_BEGIN:
2147 case BINARY_PRINT_LINE_BEGIN:
2148 case BINARY_PRINT_ADDR:
2149 case BINARY_PRINT_NUM_DATA:
2150 case BINARY_PRINT_NUM_PAD:
2151 case BINARY_PRINT_SEP:
2152 case BINARY_PRINT_CHAR_PAD:
2153 case BINARY_PRINT_LINE_END:
2154 case BINARY_PRINT_DATA_END:
2155 default:
2156 break;
2157 }
2158}
2159
2160static void bpf_output__fprintf(struct trace *trace,
2161 struct perf_sample *sample)
2162{
2163 print_binary(sample->raw_data, sample->raw_size, 8,
2164 bpf_output__printer, trace->output);
2165}
2166
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002167static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
2168 union perf_event *event __maybe_unused,
2169 struct perf_sample *sample)
2170{
2171 trace__printf_interrupted_entry(trace, sample);
2172 trace__fprintf_tstamp(trace, sample->time, trace->output);
Arnaldo Carvalho de Melo08089212015-02-19 21:51:50 -08002173
2174 if (trace->trace_syscalls)
2175 fprintf(trace->output, "( ): ");
2176
2177 fprintf(trace->output, "%s:", evsel->name);
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002178
Wang Nan1d6c9402016-02-26 09:31:55 +00002179 if (perf_evsel__is_bpf_output(evsel)) {
2180 bpf_output__fprintf(trace, sample);
2181 } else if (evsel->tp_format) {
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002182 event_format__fprintf(evsel->tp_format, sample->cpu,
2183 sample->raw_data, sample->raw_size,
2184 trace->output);
2185 }
2186
2187 fprintf(trace->output, ")\n");
Arnaldo Carvalho de Melo202ff962016-04-12 10:11:07 -03002188
2189 trace__fprintf_callchain(trace, evsel, sample);
2190
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002191 return 0;
2192}
2193
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002194static void print_location(FILE *f, struct perf_sample *sample,
2195 struct addr_location *al,
2196 bool print_dso, bool print_sym)
2197{
2198
2199 if ((verbose || print_dso) && al->map)
2200 fprintf(f, "%s@", al->map->dso->long_name);
2201
2202 if ((verbose || print_sym) && al->sym)
Arnaldo Carvalho de Melo4414a3c2014-07-08 15:39:21 -03002203 fprintf(f, "%s+0x%" PRIx64, al->sym->name,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002204 al->addr - al->sym->start);
2205 else if (al->map)
Arnaldo Carvalho de Melo4414a3c2014-07-08 15:39:21 -03002206 fprintf(f, "0x%" PRIx64, al->addr);
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002207 else
Arnaldo Carvalho de Melo4414a3c2014-07-08 15:39:21 -03002208 fprintf(f, "0x%" PRIx64, sample->addr);
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002209}
2210
2211static int trace__pgfault(struct trace *trace,
2212 struct perf_evsel *evsel,
Arnaldo Carvalho de Melo473398a2016-03-22 18:23:43 -03002213 union perf_event *event __maybe_unused,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002214 struct perf_sample *sample)
2215{
2216 struct thread *thread;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002217 struct addr_location al;
2218 char map_type = 'd';
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04002219 struct thread_trace *ttrace;
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002220 int err = -1;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002221
2222 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04002223 ttrace = thread__trace(thread, trace->output);
2224 if (ttrace == NULL)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002225 goto out_put;
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04002226
2227 if (evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ)
2228 ttrace->pfmaj++;
2229 else
2230 ttrace->pfmin++;
2231
2232 if (trace->summary_only)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002233 goto out;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002234
Arnaldo Carvalho de Melo473398a2016-03-22 18:23:43 -03002235 thread__find_addr_location(thread, sample->cpumode, MAP__FUNCTION,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002236 sample->ip, &al);
2237
2238 trace__fprintf_entry_head(trace, thread, 0, sample->time, trace->output);
2239
2240 fprintf(trace->output, "%sfault [",
2241 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ?
2242 "maj" : "min");
2243
2244 print_location(trace->output, sample, &al, false, true);
2245
2246 fprintf(trace->output, "] => ");
2247
Arnaldo Carvalho de Melo473398a2016-03-22 18:23:43 -03002248 thread__find_addr_location(thread, sample->cpumode, MAP__VARIABLE,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002249 sample->addr, &al);
2250
2251 if (!al.map) {
Arnaldo Carvalho de Melo473398a2016-03-22 18:23:43 -03002252 thread__find_addr_location(thread, sample->cpumode,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002253 MAP__FUNCTION, sample->addr, &al);
2254
2255 if (al.map)
2256 map_type = 'x';
2257 else
2258 map_type = '?';
2259 }
2260
2261 print_location(trace->output, sample, &al, true, false);
2262
2263 fprintf(trace->output, " (%c%c)\n", map_type, al.level);
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002264out:
2265 err = 0;
2266out_put:
2267 thread__put(thread);
2268 return err;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002269}
2270
David Ahernbdc89662013-08-28 22:29:53 -06002271static bool skip_sample(struct trace *trace, struct perf_sample *sample)
2272{
2273 if ((trace->pid_list && intlist__find(trace->pid_list, sample->pid)) ||
2274 (trace->tid_list && intlist__find(trace->tid_list, sample->tid)))
2275 return false;
2276
2277 if (trace->pid_list || trace->tid_list)
2278 return true;
2279
2280 return false;
2281}
2282
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03002283static void trace__set_base_time(struct trace *trace,
Arnaldo Carvalho de Melo8a07a802016-03-31 15:19:39 -03002284 struct perf_evsel *evsel,
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03002285 struct perf_sample *sample)
2286{
Arnaldo Carvalho de Melo8a07a802016-03-31 15:19:39 -03002287 /*
2288 * BPF events were not setting PERF_SAMPLE_TIME, so be more robust
2289 * and don't use sample->time unconditionally, we may end up having
2290 * some other event in the future without PERF_SAMPLE_TIME for good
2291 * reason, i.e. we may not be interested in its timestamps, just in
2292 * it taking place, picking some piece of information when it
2293 * appears in our event stream (vfs_getname comes to mind).
2294 */
2295 if (trace->base_time == 0 && !trace->full_time &&
2296 (evsel->attr.sample_type & PERF_SAMPLE_TIME))
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03002297 trace->base_time = sample->time;
2298}
2299
David Ahern6810fc92013-08-28 22:29:52 -06002300static int trace__process_sample(struct perf_tool *tool,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04002301 union perf_event *event,
David Ahern6810fc92013-08-28 22:29:52 -06002302 struct perf_sample *sample,
2303 struct perf_evsel *evsel,
2304 struct machine *machine __maybe_unused)
2305{
2306 struct trace *trace = container_of(tool, struct trace, tool);
2307 int err = 0;
2308
Arnaldo Carvalho de Melo744a9712013-11-06 10:17:38 -03002309 tracepoint_handler handler = evsel->handler;
David Ahern6810fc92013-08-28 22:29:52 -06002310
David Ahernbdc89662013-08-28 22:29:53 -06002311 if (skip_sample(trace, sample))
2312 return 0;
2313
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03002314 trace__set_base_time(trace, evsel, sample);
David Ahern6810fc92013-08-28 22:29:52 -06002315
David Ahern31605652013-12-04 19:41:41 -07002316 if (handler) {
2317 ++trace->nr_events;
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04002318 handler(trace, evsel, event, sample);
David Ahern31605652013-12-04 19:41:41 -07002319 }
David Ahern6810fc92013-08-28 22:29:52 -06002320
2321 return err;
2322}
2323
David Ahernbdc89662013-08-28 22:29:53 -06002324static int parse_target_str(struct trace *trace)
2325{
2326 if (trace->opts.target.pid) {
2327 trace->pid_list = intlist__new(trace->opts.target.pid);
2328 if (trace->pid_list == NULL) {
2329 pr_err("Error parsing process id string\n");
2330 return -EINVAL;
2331 }
2332 }
2333
2334 if (trace->opts.target.tid) {
2335 trace->tid_list = intlist__new(trace->opts.target.tid);
2336 if (trace->tid_list == NULL) {
2337 pr_err("Error parsing thread id string\n");
2338 return -EINVAL;
2339 }
2340 }
2341
2342 return 0;
2343}
2344
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002345static int trace__record(struct trace *trace, int argc, const char **argv)
David Ahern5e2485b2013-09-28 13:13:01 -06002346{
2347 unsigned int rec_argc, i, j;
2348 const char **rec_argv;
2349 const char * const record_args[] = {
2350 "record",
2351 "-R",
2352 "-m", "1024",
2353 "-c", "1",
David Ahern5e2485b2013-09-28 13:13:01 -06002354 };
2355
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002356 const char * const sc_args[] = { "-e", };
2357 unsigned int sc_args_nr = ARRAY_SIZE(sc_args);
2358 const char * const majpf_args[] = { "-e", "major-faults" };
2359 unsigned int majpf_args_nr = ARRAY_SIZE(majpf_args);
2360 const char * const minpf_args[] = { "-e", "minor-faults" };
2361 unsigned int minpf_args_nr = ARRAY_SIZE(minpf_args);
2362
David Ahern9aca7f12013-12-04 19:41:39 -07002363 /* +1 is for the event string below */
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002364 rec_argc = ARRAY_SIZE(record_args) + sc_args_nr + 1 +
2365 majpf_args_nr + minpf_args_nr + argc;
David Ahern5e2485b2013-09-28 13:13:01 -06002366 rec_argv = calloc(rec_argc + 1, sizeof(char *));
2367
2368 if (rec_argv == NULL)
2369 return -ENOMEM;
2370
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002371 j = 0;
David Ahern5e2485b2013-09-28 13:13:01 -06002372 for (i = 0; i < ARRAY_SIZE(record_args); i++)
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002373 rec_argv[j++] = record_args[i];
2374
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002375 if (trace->trace_syscalls) {
2376 for (i = 0; i < sc_args_nr; i++)
2377 rec_argv[j++] = sc_args[i];
David Ahern5e2485b2013-09-28 13:13:01 -06002378
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002379 /* event string may be different for older kernels - e.g., RHEL6 */
2380 if (is_valid_tracepoint("raw_syscalls:sys_enter"))
2381 rec_argv[j++] = "raw_syscalls:sys_enter,raw_syscalls:sys_exit";
2382 else if (is_valid_tracepoint("syscalls:sys_enter"))
2383 rec_argv[j++] = "syscalls:sys_enter,syscalls:sys_exit";
2384 else {
2385 pr_err("Neither raw_syscalls nor syscalls events exist.\n");
2386 return -1;
2387 }
David Ahern9aca7f12013-12-04 19:41:39 -07002388 }
David Ahern9aca7f12013-12-04 19:41:39 -07002389
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002390 if (trace->trace_pgfaults & TRACE_PFMAJ)
2391 for (i = 0; i < majpf_args_nr; i++)
2392 rec_argv[j++] = majpf_args[i];
David Ahern5e2485b2013-09-28 13:13:01 -06002393
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002394 if (trace->trace_pgfaults & TRACE_PFMIN)
2395 for (i = 0; i < minpf_args_nr; i++)
2396 rec_argv[j++] = minpf_args[i];
2397
2398 for (i = 0; i < (unsigned int)argc; i++)
2399 rec_argv[j++] = argv[i];
2400
2401 return cmd_record(j, rec_argv, NULL);
David Ahern5e2485b2013-09-28 13:13:01 -06002402}
2403
David Ahernbf2575c2013-10-08 21:26:53 -06002404static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp);
2405
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002406static bool perf_evlist__add_vfs_getname(struct perf_evlist *evlist)
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002407{
Arnaldo Carvalho de Meloef503832013-11-07 16:41:19 -03002408 struct perf_evsel *evsel = perf_evsel__newtp("probe", "vfs_getname");
Jiri Olsa8dd2a132015-09-07 10:38:06 +02002409
2410 if (IS_ERR(evsel))
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002411 return false;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002412
2413 if (perf_evsel__field(evsel, "pathname") == NULL) {
2414 perf_evsel__delete(evsel);
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002415 return false;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002416 }
2417
Arnaldo Carvalho de Melo744a9712013-11-06 10:17:38 -03002418 evsel->handler = trace__vfs_getname;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002419 perf_evlist__add(evlist, evsel);
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002420 return true;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002421}
2422
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002423static int perf_evlist__add_pgfault(struct perf_evlist *evlist,
2424 u64 config)
2425{
2426 struct perf_evsel *evsel;
2427 struct perf_event_attr attr = {
2428 .type = PERF_TYPE_SOFTWARE,
2429 .mmap_data = 1,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002430 };
2431
2432 attr.config = config;
Arnaldo Carvalho de Melo05247982014-07-23 18:15:09 -03002433 attr.sample_period = 1;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002434
2435 event_attr_init(&attr);
2436
2437 evsel = perf_evsel__new(&attr);
2438 if (!evsel)
2439 return -ENOMEM;
2440
2441 evsel->handler = trace__pgfault;
2442 perf_evlist__add(evlist, evsel);
2443
2444 return 0;
2445}
2446
Arnaldo Carvalho de Meloddbb1b12015-02-21 12:10:29 -08002447static void trace__handle_event(struct trace *trace, union perf_event *event, struct perf_sample *sample)
2448{
2449 const u32 type = event->header.type;
2450 struct perf_evsel *evsel;
2451
Arnaldo Carvalho de Meloddbb1b12015-02-21 12:10:29 -08002452 if (type != PERF_RECORD_SAMPLE) {
2453 trace__process_event(trace, trace->host, event, sample);
2454 return;
2455 }
2456
2457 evsel = perf_evlist__id2evsel(trace->evlist, sample->id);
2458 if (evsel == NULL) {
2459 fprintf(trace->output, "Unknown tp ID %" PRIu64 ", skipping...\n", sample->id);
2460 return;
2461 }
2462
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03002463 trace__set_base_time(trace, evsel, sample);
2464
Arnaldo Carvalho de Meloddbb1b12015-02-21 12:10:29 -08002465 if (evsel->attr.type == PERF_TYPE_TRACEPOINT &&
2466 sample->raw_data == NULL) {
2467 fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n",
2468 perf_evsel__name(evsel), sample->tid,
2469 sample->cpu, sample->raw_size);
2470 } else {
2471 tracepoint_handler handler = evsel->handler;
2472 handler(trace, evsel, event, sample);
2473 }
2474}
2475
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03002476static int trace__add_syscall_newtp(struct trace *trace)
2477{
2478 int ret = -1;
2479 struct perf_evlist *evlist = trace->evlist;
2480 struct perf_evsel *sys_enter, *sys_exit;
2481
2482 sys_enter = perf_evsel__syscall_newtp("sys_enter", trace__sys_enter);
2483 if (sys_enter == NULL)
2484 goto out;
2485
2486 if (perf_evsel__init_sc_tp_ptr_field(sys_enter, args))
2487 goto out_delete_sys_enter;
2488
2489 sys_exit = perf_evsel__syscall_newtp("sys_exit", trace__sys_exit);
2490 if (sys_exit == NULL)
2491 goto out_delete_sys_enter;
2492
2493 if (perf_evsel__init_sc_tp_uint_field(sys_exit, ret))
2494 goto out_delete_sys_exit;
2495
2496 perf_evlist__add(evlist, sys_enter);
2497 perf_evlist__add(evlist, sys_exit);
2498
Arnaldo Carvalho de Melo44621812016-04-11 15:49:11 -03002499 if (trace->opts.callgraph_set && !trace->kernel_syscallchains) {
2500 /*
2501 * We're interested only in the user space callchain
2502 * leading to the syscall, allow overriding that for
2503 * debugging reasons using --kernel_syscall_callchains
2504 */
2505 sys_exit->attr.exclude_callchain_kernel = 1;
2506 }
2507
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03002508 trace->syscalls.events.sys_enter = sys_enter;
2509 trace->syscalls.events.sys_exit = sys_exit;
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03002510
2511 ret = 0;
2512out:
2513 return ret;
2514
2515out_delete_sys_exit:
2516 perf_evsel__delete_priv(sys_exit);
2517out_delete_sys_enter:
2518 perf_evsel__delete_priv(sys_enter);
2519 goto out;
2520}
2521
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002522static int trace__set_ev_qualifier_filter(struct trace *trace)
2523{
2524 int err = -1;
2525 char *filter = asprintf_expr_inout_ints("id", !trace->not_ev_qualifier,
2526 trace->ev_qualifier_ids.nr,
2527 trace->ev_qualifier_ids.entries);
2528
2529 if (filter == NULL)
2530 goto out_enomem;
2531
2532 if (!perf_evsel__append_filter(trace->syscalls.events.sys_enter, "&&", filter))
2533 err = perf_evsel__append_filter(trace->syscalls.events.sys_exit, "&&", filter);
2534
2535 free(filter);
2536out:
2537 return err;
2538out_enomem:
2539 errno = ENOMEM;
2540 goto out;
2541}
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03002542
Namhyung Kimf15eb532012-10-05 14:02:16 +09002543static int trace__run(struct trace *trace, int argc, const char **argv)
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002544{
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002545 struct perf_evlist *evlist = trace->evlist;
Arnaldo Carvalho de Melo94ad89b2015-07-03 17:42:03 -03002546 struct perf_evsel *evsel;
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03002547 int err = -1, i;
2548 unsigned long before;
Namhyung Kimf15eb532012-10-05 14:02:16 +09002549 const bool forks = argc > 0;
Arnaldo Carvalho de Melo46fb3c22014-09-22 14:39:48 -03002550 bool draining = false;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002551
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03002552 trace->live = true;
2553
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03002554 if (trace->trace_syscalls && trace__add_syscall_newtp(trace))
Arnaldo Carvalho de Melo801c67b2015-01-22 10:52:55 -03002555 goto out_error_raw_syscalls;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002556
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002557 if (trace->trace_syscalls)
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002558 trace->vfs_getname = perf_evlist__add_vfs_getname(evlist);
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002559
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002560 if ((trace->trace_pgfaults & TRACE_PFMAJ) &&
Arnaldo Carvalho de Meloe2726d92015-01-22 10:34:22 -03002561 perf_evlist__add_pgfault(evlist, PERF_COUNT_SW_PAGE_FAULTS_MAJ)) {
Arnaldo Carvalho de Melo5ed08da2015-01-22 11:08:04 -03002562 goto out_error_mem;
Arnaldo Carvalho de Meloe2726d92015-01-22 10:34:22 -03002563 }
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002564
2565 if ((trace->trace_pgfaults & TRACE_PFMIN) &&
2566 perf_evlist__add_pgfault(evlist, PERF_COUNT_SW_PAGE_FAULTS_MIN))
Arnaldo Carvalho de Melo5ed08da2015-01-22 11:08:04 -03002567 goto out_error_mem;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002568
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002569 if (trace->sched &&
Arnaldo Carvalho de Melo2cc990b2015-01-22 11:13:43 -03002570 perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime",
2571 trace__sched_stat_runtime))
2572 goto out_error_sched_stat_runtime;
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002573
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002574 err = perf_evlist__create_maps(evlist, &trace->opts.target);
2575 if (err < 0) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002576 fprintf(trace->output, "Problems parsing the target to trace, check your options!\n");
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002577 goto out_delete_evlist;
2578 }
2579
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03002580 err = trace__symbols_init(trace, evlist);
2581 if (err < 0) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002582 fprintf(trace->output, "Problems initializing symbol libraries!\n");
Arnaldo Carvalho de Melo03ad9742014-01-03 15:56:06 -03002583 goto out_delete_evlist;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03002584 }
2585
Arnaldo Carvalho de Melofde54b72016-04-11 18:42:37 -03002586 perf_evlist__config(evlist, &trace->opts, NULL);
2587
2588 if (trace->opts.callgraph_set && trace->syscalls.events.sys_exit) {
2589 perf_evsel__config_callchain(trace->syscalls.events.sys_exit,
2590 &trace->opts, &callchain_param);
2591 /*
2592 * Now we have evsels with different sample_ids, use
2593 * PERF_SAMPLE_IDENTIFIER to map from sample to evsel
2594 * from a fixed position in each ring buffer record.
2595 *
2596 * As of this the changeset introducing this comment, this
2597 * isn't strictly needed, as the fields that can come before
2598 * PERF_SAMPLE_ID are all used, but we'll probably disable
2599 * some of those for things like copying the payload of
2600 * pointer syscall arguments, and for vfs_getname we don't
2601 * need PERF_SAMPLE_ADDR and PERF_SAMPLE_IP, so do this
2602 * here as a warning we need to use PERF_SAMPLE_IDENTIFIER.
2603 */
2604 perf_evlist__set_sample_bit(evlist, IDENTIFIER);
2605 perf_evlist__reset_sample_bit(evlist, ID);
2606 }
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002607
Namhyung Kimf15eb532012-10-05 14:02:16 +09002608 signal(SIGCHLD, sig_handler);
2609 signal(SIGINT, sig_handler);
2610
2611 if (forks) {
Namhyung Kim6ef73ec2013-03-11 16:43:15 +09002612 err = perf_evlist__prepare_workload(evlist, &trace->opts.target,
Arnaldo Carvalho de Melo735f7e02014-01-03 14:56:49 -03002613 argv, false, NULL);
Namhyung Kimf15eb532012-10-05 14:02:16 +09002614 if (err < 0) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002615 fprintf(trace->output, "Couldn't run the workload!\n");
Arnaldo Carvalho de Melo03ad9742014-01-03 15:56:06 -03002616 goto out_delete_evlist;
Namhyung Kimf15eb532012-10-05 14:02:16 +09002617 }
2618 }
2619
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002620 err = perf_evlist__open(evlist);
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002621 if (err < 0)
2622 goto out_error_open;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002623
Wang Nanba504232016-02-26 09:31:54 +00002624 err = bpf__apply_obj_config();
2625 if (err) {
2626 char errbuf[BUFSIZ];
2627
2628 bpf__strerror_apply_obj_config(err, errbuf, sizeof(errbuf));
2629 pr_err("ERROR: Apply config to BPF failed: %s\n",
2630 errbuf);
2631 goto out_error_open;
2632 }
2633
Arnaldo Carvalho de Melo241b0572015-02-21 10:15:21 -08002634 /*
2635 * Better not use !target__has_task() here because we need to cover the
2636 * case where no threads were specified in the command line, but a
2637 * workload was, and in that case we will fill in the thread_map when
2638 * we fork the workload in perf_evlist__prepare_workload.
2639 */
Arnaldo Carvalho de Melof078c382015-02-21 11:36:52 -08002640 if (trace->filter_pids.nr > 0)
2641 err = perf_evlist__set_filter_pids(evlist, trace->filter_pids.nr, trace->filter_pids.entries);
Jiri Olsae13798c2015-06-23 00:36:02 +02002642 else if (thread_map__pid(evlist->threads, 0) == -1)
Arnaldo Carvalho de Melof078c382015-02-21 11:36:52 -08002643 err = perf_evlist__set_filter_pid(evlist, getpid());
2644
Arnaldo Carvalho de Melo94ad89b2015-07-03 17:42:03 -03002645 if (err < 0)
2646 goto out_error_mem;
2647
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002648 if (trace->ev_qualifier_ids.nr > 0) {
2649 err = trace__set_ev_qualifier_filter(trace);
2650 if (err < 0)
2651 goto out_errno;
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002652
Arnaldo Carvalho de Melo2e5e5f82015-08-03 17:12:29 -03002653 pr_debug("event qualifier tracepoint filter: %s\n",
2654 trace->syscalls.events.sys_exit->filter);
2655 }
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002656
Arnaldo Carvalho de Melo94ad89b2015-07-03 17:42:03 -03002657 err = perf_evlist__apply_filters(evlist, &evsel);
2658 if (err < 0)
2659 goto out_error_apply_filters;
Arnaldo Carvalho de Melo241b0572015-02-21 10:15:21 -08002660
Jiri Olsaf8850372013-11-28 17:57:22 +01002661 err = perf_evlist__mmap(evlist, trace->opts.mmap_pages, false);
Arnaldo Carvalho de Meloe09b18d2014-12-11 18:04:10 -03002662 if (err < 0)
2663 goto out_error_mmap;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002664
Arnaldo Carvalho de Melocb24d012015-04-22 10:04:23 -03002665 if (!target__none(&trace->opts.target))
2666 perf_evlist__enable(evlist);
2667
Namhyung Kimf15eb532012-10-05 14:02:16 +09002668 if (forks)
2669 perf_evlist__start_workload(evlist);
2670
Jiri Olsae13798c2015-06-23 00:36:02 +02002671 trace->multiple_threads = thread_map__pid(evlist->threads, 0) == -1 ||
Arnaldo Carvalho de Melo42052be2015-02-13 12:32:45 -03002672 evlist->threads->nr > 1 ||
2673 perf_evlist__first(evlist)->attr.inherit;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002674again:
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03002675 before = trace->nr_events;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002676
2677 for (i = 0; i < evlist->nr_mmaps; i++) {
2678 union perf_event *event;
2679
2680 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002681 struct perf_sample sample;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002682
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03002683 ++trace->nr_events;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002684
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002685 err = perf_evlist__parse_sample(evlist, event, &sample);
2686 if (err) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002687 fprintf(trace->output, "Can't parse sample, err = %d, skipping...\n", err);
Zhouyi Zhou8e50d382013-10-24 15:43:33 +08002688 goto next_event;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002689 }
2690
Arnaldo Carvalho de Meloddbb1b12015-02-21 12:10:29 -08002691 trace__handle_event(trace, event, &sample);
Zhouyi Zhou8e50d382013-10-24 15:43:33 +08002692next_event:
2693 perf_evlist__mmap_consume(evlist, i);
Arnaldo Carvalho de Melo20c5f102013-09-03 11:55:07 -03002694
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002695 if (interrupted)
2696 goto out_disable;
Arnaldo Carvalho de Melo02ac5422015-04-22 11:11:57 -03002697
2698 if (done && !draining) {
2699 perf_evlist__disable(evlist);
2700 draining = true;
2701 }
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002702 }
2703 }
2704
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03002705 if (trace->nr_events == before) {
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002706 int timeout = done ? 100 : -1;
Namhyung Kimf15eb532012-10-05 14:02:16 +09002707
Arnaldo Carvalho de Melo46fb3c22014-09-22 14:39:48 -03002708 if (!draining && perf_evlist__poll(evlist, timeout) > 0) {
2709 if (perf_evlist__filter_pollfd(evlist, POLLERR | POLLHUP) == 0)
2710 draining = true;
2711
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002712 goto again;
Arnaldo Carvalho de Melo46fb3c22014-09-22 14:39:48 -03002713 }
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002714 } else {
2715 goto again;
Namhyung Kimf15eb532012-10-05 14:02:16 +09002716 }
2717
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002718out_disable:
Arnaldo Carvalho de Melof3b623b2015-03-02 22:21:35 -03002719 thread__zput(trace->current);
2720
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002721 perf_evlist__disable(evlist);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002722
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002723 if (!err) {
2724 if (trace->summary)
2725 trace__fprintf_thread_summary(trace, trace->output);
2726
2727 if (trace->show_tool_stats) {
2728 fprintf(trace->output, "Stats:\n "
2729 " vfs_getname : %" PRIu64 "\n"
2730 " proc_getname: %" PRIu64 "\n",
2731 trace->stats.vfs_getname,
2732 trace->stats.proc_getname);
2733 }
2734 }
David Ahernbf2575c2013-10-08 21:26:53 -06002735
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002736out_delete_evlist:
2737 perf_evlist__delete(evlist);
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002738 trace->evlist = NULL;
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03002739 trace->live = false;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002740 return err;
Arnaldo Carvalho de Melo6ef068c2013-10-17 12:07:58 -03002741{
2742 char errbuf[BUFSIZ];
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002743
Arnaldo Carvalho de Melo2cc990b2015-01-22 11:13:43 -03002744out_error_sched_stat_runtime:
Jiri Olsa988bdb32015-09-02 09:56:35 +02002745 tracing_path__strerror_open_tp(errno, errbuf, sizeof(errbuf), "sched", "sched_stat_runtime");
Arnaldo Carvalho de Melo2cc990b2015-01-22 11:13:43 -03002746 goto out_error;
2747
Arnaldo Carvalho de Melo801c67b2015-01-22 10:52:55 -03002748out_error_raw_syscalls:
Jiri Olsa988bdb32015-09-02 09:56:35 +02002749 tracing_path__strerror_open_tp(errno, errbuf, sizeof(errbuf), "raw_syscalls", "sys_(enter|exit)");
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002750 goto out_error;
2751
Arnaldo Carvalho de Meloe09b18d2014-12-11 18:04:10 -03002752out_error_mmap:
2753 perf_evlist__strerror_mmap(evlist, errno, errbuf, sizeof(errbuf));
2754 goto out_error;
2755
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002756out_error_open:
2757 perf_evlist__strerror_open(evlist, errno, errbuf, sizeof(errbuf));
2758
2759out_error:
Arnaldo Carvalho de Melo6ef068c2013-10-17 12:07:58 -03002760 fprintf(trace->output, "%s\n", errbuf);
Ramkumar Ramachandra87f91862013-10-04 10:47:31 +05302761 goto out_delete_evlist;
Arnaldo Carvalho de Melo94ad89b2015-07-03 17:42:03 -03002762
2763out_error_apply_filters:
2764 fprintf(trace->output,
2765 "Failed to set filter \"%s\" on event %s with %d (%s)\n",
2766 evsel->filter, perf_evsel__name(evsel), errno,
2767 strerror_r(errno, errbuf, sizeof(errbuf)));
2768 goto out_delete_evlist;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002769}
Arnaldo Carvalho de Melo5ed08da2015-01-22 11:08:04 -03002770out_error_mem:
2771 fprintf(trace->output, "Not enough memory to run!\n");
2772 goto out_delete_evlist;
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002773
2774out_errno:
2775 fprintf(trace->output, "errno=%d,%s\n", errno, strerror(errno));
2776 goto out_delete_evlist;
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002777}
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002778
David Ahern6810fc92013-08-28 22:29:52 -06002779static int trace__replay(struct trace *trace)
2780{
2781 const struct perf_evsel_str_handler handlers[] = {
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002782 { "probe:vfs_getname", trace__vfs_getname, },
David Ahern6810fc92013-08-28 22:29:52 -06002783 };
Jiri Olsaf5fc14122013-10-15 16:27:32 +02002784 struct perf_data_file file = {
2785 .path = input_name,
2786 .mode = PERF_DATA_MODE_READ,
Yunlong Songe366a6d2015-04-02 21:47:18 +08002787 .force = trace->force,
Jiri Olsaf5fc14122013-10-15 16:27:32 +02002788 };
David Ahern6810fc92013-08-28 22:29:52 -06002789 struct perf_session *session;
Namhyung Kim003824e2013-11-12 15:25:00 +09002790 struct perf_evsel *evsel;
David Ahern6810fc92013-08-28 22:29:52 -06002791 int err = -1;
2792
2793 trace->tool.sample = trace__process_sample;
2794 trace->tool.mmap = perf_event__process_mmap;
David Ahern384c6712013-09-22 19:44:58 -06002795 trace->tool.mmap2 = perf_event__process_mmap2;
David Ahern6810fc92013-08-28 22:29:52 -06002796 trace->tool.comm = perf_event__process_comm;
2797 trace->tool.exit = perf_event__process_exit;
2798 trace->tool.fork = perf_event__process_fork;
2799 trace->tool.attr = perf_event__process_attr;
2800 trace->tool.tracing_data = perf_event__process_tracing_data;
2801 trace->tool.build_id = perf_event__process_build_id;
2802
Jiri Olsa0a8cb852014-07-06 14:18:21 +02002803 trace->tool.ordered_events = true;
David Ahern6810fc92013-08-28 22:29:52 -06002804 trace->tool.ordering_requires_timestamps = true;
2805
2806 /* add tid to output */
2807 trace->multiple_threads = true;
2808
Jiri Olsaf5fc14122013-10-15 16:27:32 +02002809 session = perf_session__new(&file, false, &trace->tool);
David Ahern6810fc92013-08-28 22:29:52 -06002810 if (session == NULL)
Taeung Song52e028342014-09-24 10:33:37 +09002811 return -1;
David Ahern6810fc92013-08-28 22:29:52 -06002812
Namhyung Kim0a7e6d12014-08-12 15:40:45 +09002813 if (symbol__init(&session->header.env) < 0)
Namhyung Kimcb2ffae2014-08-12 15:40:44 +09002814 goto out;
2815
David Ahern8fb598e2013-09-28 13:13:00 -06002816 trace->host = &session->machines.host;
2817
David Ahern6810fc92013-08-28 22:29:52 -06002818 err = perf_session__set_tracepoints_handlers(session, handlers);
2819 if (err)
2820 goto out;
2821
Namhyung Kim003824e2013-11-12 15:25:00 +09002822 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2823 "raw_syscalls:sys_enter");
David Ahern9aca7f12013-12-04 19:41:39 -07002824 /* older kernels have syscalls tp versus raw_syscalls */
2825 if (evsel == NULL)
2826 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2827 "syscalls:sys_enter");
David Ahern6810fc92013-08-28 22:29:52 -06002828
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002829 if (evsel &&
2830 (perf_evsel__init_syscall_tp(evsel, trace__sys_enter) < 0 ||
2831 perf_evsel__init_sc_tp_ptr_field(evsel, args))) {
Namhyung Kim003824e2013-11-12 15:25:00 +09002832 pr_err("Error during initialize raw_syscalls:sys_enter event\n");
2833 goto out;
2834 }
2835
2836 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2837 "raw_syscalls:sys_exit");
David Ahern9aca7f12013-12-04 19:41:39 -07002838 if (evsel == NULL)
2839 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2840 "syscalls:sys_exit");
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002841 if (evsel &&
2842 (perf_evsel__init_syscall_tp(evsel, trace__sys_exit) < 0 ||
2843 perf_evsel__init_sc_tp_uint_field(evsel, ret))) {
Namhyung Kim003824e2013-11-12 15:25:00 +09002844 pr_err("Error during initialize raw_syscalls:sys_exit event\n");
David Ahern6810fc92013-08-28 22:29:52 -06002845 goto out;
2846 }
2847
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002848 evlist__for_each(session->evlist, evsel) {
2849 if (evsel->attr.type == PERF_TYPE_SOFTWARE &&
2850 (evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ||
2851 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MIN ||
2852 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS))
2853 evsel->handler = trace__pgfault;
2854 }
2855
David Ahernbdc89662013-08-28 22:29:53 -06002856 err = parse_target_str(trace);
2857 if (err != 0)
2858 goto out;
2859
David Ahern6810fc92013-08-28 22:29:52 -06002860 setup_pager();
2861
Arnaldo Carvalho de Melob7b61cb2015-03-03 11:58:45 -03002862 err = perf_session__process_events(session);
David Ahern6810fc92013-08-28 22:29:52 -06002863 if (err)
2864 pr_err("Failed to process events, error %d", err);
2865
David Ahernbf2575c2013-10-08 21:26:53 -06002866 else if (trace->summary)
2867 trace__fprintf_thread_summary(trace, trace->output);
2868
David Ahern6810fc92013-08-28 22:29:52 -06002869out:
2870 perf_session__delete(session);
2871
2872 return err;
2873}
2874
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002875static size_t trace__fprintf_threads_header(FILE *fp)
2876{
2877 size_t printed;
2878
Pekka Enberg99ff7152013-11-12 16:42:14 +02002879 printed = fprintf(fp, "\n Summary of events:\n\n");
David Ahernbf2575c2013-10-08 21:26:53 -06002880
2881 return printed;
2882}
2883
2884static size_t thread__dump_stats(struct thread_trace *ttrace,
2885 struct trace *trace, FILE *fp)
2886{
2887 struct stats *stats;
2888 size_t printed = 0;
2889 struct syscall *sc;
2890 struct int_node *inode = intlist__first(ttrace->syscall_stats);
2891
2892 if (inode == NULL)
2893 return 0;
2894
2895 printed += fprintf(fp, "\n");
2896
Milian Wolff834fd462015-08-06 11:24:29 +02002897 printed += fprintf(fp, " syscall calls total min avg max stddev\n");
2898 printed += fprintf(fp, " (msec) (msec) (msec) (msec) (%%)\n");
2899 printed += fprintf(fp, " --------------- -------- --------- --------- --------- --------- ------\n");
Pekka Enberg99ff7152013-11-12 16:42:14 +02002900
David Ahernbf2575c2013-10-08 21:26:53 -06002901 /* each int_node is a syscall */
2902 while (inode) {
2903 stats = inode->priv;
2904 if (stats) {
2905 double min = (double)(stats->min) / NSEC_PER_MSEC;
2906 double max = (double)(stats->max) / NSEC_PER_MSEC;
2907 double avg = avg_stats(stats);
2908 double pct;
2909 u64 n = (u64) stats->n;
2910
2911 pct = avg ? 100.0 * stddev_stats(stats)/avg : 0.0;
2912 avg /= NSEC_PER_MSEC;
2913
2914 sc = &trace->syscalls.table[inode->i];
Pekka Enberg99ff7152013-11-12 16:42:14 +02002915 printed += fprintf(fp, " %-15s", sc->name);
Milian Wolff834fd462015-08-06 11:24:29 +02002916 printed += fprintf(fp, " %8" PRIu64 " %9.3f %9.3f %9.3f",
2917 n, avg * n, min, avg);
Pekka Enberg27a778b2013-11-13 14:21:48 +02002918 printed += fprintf(fp, " %9.3f %9.2f%%\n", max, pct);
David Ahernbf2575c2013-10-08 21:26:53 -06002919 }
2920
2921 inode = intlist__next(inode);
2922 }
2923
2924 printed += fprintf(fp, "\n\n");
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002925
2926 return printed;
2927}
2928
David Ahern896cbb52013-09-28 13:12:59 -06002929/* struct used to pass data to per-thread function */
2930struct summary_data {
2931 FILE *fp;
2932 struct trace *trace;
2933 size_t printed;
2934};
2935
2936static int trace__fprintf_one_thread(struct thread *thread, void *priv)
2937{
2938 struct summary_data *data = priv;
2939 FILE *fp = data->fp;
2940 size_t printed = data->printed;
2941 struct trace *trace = data->trace;
Namhyung Kim89dceb22014-10-06 09:46:03 +09002942 struct thread_trace *ttrace = thread__priv(thread);
David Ahern896cbb52013-09-28 13:12:59 -06002943 double ratio;
2944
2945 if (ttrace == NULL)
2946 return 0;
2947
2948 ratio = (double)ttrace->nr_events / trace->nr_events * 100.0;
2949
Pekka Enberg15e65c62013-11-14 18:43:30 +02002950 printed += fprintf(fp, " %s (%d), ", thread__comm_str(thread), thread->tid);
Pekka Enberg99ff7152013-11-12 16:42:14 +02002951 printed += fprintf(fp, "%lu events, ", ttrace->nr_events);
Pekka Enberg15e65c62013-11-14 18:43:30 +02002952 printed += fprintf(fp, "%.1f%%", ratio);
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04002953 if (ttrace->pfmaj)
2954 printed += fprintf(fp, ", %lu majfaults", ttrace->pfmaj);
2955 if (ttrace->pfmin)
2956 printed += fprintf(fp, ", %lu minfaults", ttrace->pfmin);
Pekka Enberg99ff7152013-11-12 16:42:14 +02002957 printed += fprintf(fp, ", %.3f msec\n", ttrace->runtime_ms);
David Ahernbf2575c2013-10-08 21:26:53 -06002958 printed += thread__dump_stats(ttrace, trace, fp);
David Ahern896cbb52013-09-28 13:12:59 -06002959
2960 data->printed += printed;
2961
2962 return 0;
2963}
2964
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002965static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp)
2966{
David Ahern896cbb52013-09-28 13:12:59 -06002967 struct summary_data data = {
2968 .fp = fp,
2969 .trace = trace
2970 };
2971 data.printed = trace__fprintf_threads_header(fp);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002972
David Ahern896cbb52013-09-28 13:12:59 -06002973 machine__for_each_thread(trace->host, trace__fprintf_one_thread, &data);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002974
David Ahern896cbb52013-09-28 13:12:59 -06002975 return data.printed;
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002976}
2977
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03002978static int trace__set_duration(const struct option *opt, const char *str,
2979 int unset __maybe_unused)
2980{
2981 struct trace *trace = opt->value;
2982
2983 trace->duration_filter = atof(str);
2984 return 0;
2985}
2986
Arnaldo Carvalho de Melof078c382015-02-21 11:36:52 -08002987static int trace__set_filter_pids(const struct option *opt, const char *str,
2988 int unset __maybe_unused)
2989{
2990 int ret = -1;
2991 size_t i;
2992 struct trace *trace = opt->value;
2993 /*
2994 * FIXME: introduce a intarray class, plain parse csv and create a
2995 * { int nr, int entries[] } struct...
2996 */
2997 struct intlist *list = intlist__new(str);
2998
2999 if (list == NULL)
3000 return -1;
3001
3002 i = trace->filter_pids.nr = intlist__nr_entries(list) + 1;
3003 trace->filter_pids.entries = calloc(i, sizeof(pid_t));
3004
3005 if (trace->filter_pids.entries == NULL)
3006 goto out;
3007
3008 trace->filter_pids.entries[0] = getpid();
3009
3010 for (i = 1; i < trace->filter_pids.nr; ++i)
3011 trace->filter_pids.entries[i] = intlist__entry(list, i - 1)->i;
3012
3013 intlist__delete(list);
3014 ret = 0;
3015out:
3016 return ret;
3017}
3018
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003019static int trace__open_output(struct trace *trace, const char *filename)
3020{
3021 struct stat st;
3022
3023 if (!stat(filename, &st) && st.st_size) {
3024 char oldname[PATH_MAX];
3025
3026 scnprintf(oldname, sizeof(oldname), "%s.old", filename);
3027 unlink(oldname);
3028 rename(filename, oldname);
3029 }
3030
3031 trace->output = fopen(filename, "w");
3032
3033 return trace->output == NULL ? -errno : 0;
3034}
3035
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04003036static int parse_pagefaults(const struct option *opt, const char *str,
3037 int unset __maybe_unused)
3038{
3039 int *trace_pgfaults = opt->value;
3040
3041 if (strcmp(str, "all") == 0)
3042 *trace_pgfaults |= TRACE_PFMAJ | TRACE_PFMIN;
3043 else if (strcmp(str, "maj") == 0)
3044 *trace_pgfaults |= TRACE_PFMAJ;
3045 else if (strcmp(str, "min") == 0)
3046 *trace_pgfaults |= TRACE_PFMIN;
3047 else
3048 return -1;
3049
3050 return 0;
3051}
3052
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003053static void evlist__set_evsel_handler(struct perf_evlist *evlist, void *handler)
3054{
3055 struct perf_evsel *evsel;
3056
3057 evlist__for_each(evlist, evsel)
3058 evsel->handler = handler;
3059}
3060
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003061int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
3062{
Yunlong Song6fdd9cb2015-03-18 21:35:57 +08003063 const char *trace_usage[] = {
Namhyung Kimf15eb532012-10-05 14:02:16 +09003064 "perf trace [<options>] [<command>]",
3065 "perf trace [<options>] -- <command> [<options>]",
David Ahern5e2485b2013-09-28 13:13:01 -06003066 "perf trace record [<options>] [<command>]",
3067 "perf trace record [<options>] -- <command> [<options>]",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003068 NULL
3069 };
3070 struct trace trace = {
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003071 .syscalls = {
3072 . max = -1,
3073 },
3074 .opts = {
3075 .target = {
3076 .uid = UINT_MAX,
3077 .uses_mmap = true,
3078 },
3079 .user_freq = UINT_MAX,
3080 .user_interval = ULLONG_MAX,
Arnaldo Carvalho de Melo509051e2014-01-14 17:52:14 -03003081 .no_buffering = true,
Arnaldo Carvalho de Melo38d54472014-12-12 17:28:32 -03003082 .mmap_pages = UINT_MAX,
Kan Liang9d9cad72015-06-17 09:51:11 -04003083 .proc_map_timeout = 500,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003084 },
Milian Wolff007d66a2015-08-05 16:52:23 -03003085 .output = stderr,
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -03003086 .show_comm = true,
Stanislav Fomicheve281a962014-06-26 20:14:28 +04003087 .trace_syscalls = true,
Arnaldo Carvalho de Melo44621812016-04-11 15:49:11 -03003088 .kernel_syscallchains = false,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003089 };
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003090 const char *output_name = NULL;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03003091 const char *ev_qualifier_str = NULL;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003092 const struct option trace_options[] = {
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003093 OPT_CALLBACK(0, "event", &trace.evlist, "event",
3094 "event selector. use 'perf list' to list available events",
3095 parse_events_option),
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -03003096 OPT_BOOLEAN(0, "comm", &trace.show_comm,
3097 "show the thread COMM next to its id"),
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03003098 OPT_BOOLEAN(0, "tool_stats", &trace.show_tool_stats, "show tool stats"),
Arnaldo Carvalho de Melod303e852015-04-23 12:02:07 -03003099 OPT_STRING('e', "expr", &ev_qualifier_str, "expr", "list of syscalls to trace"),
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003100 OPT_STRING('o', "output", &output_name, "file", "output file name"),
David Ahern6810fc92013-08-28 22:29:52 -06003101 OPT_STRING('i', "input", &input_name, "file", "Analyze events in file"),
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003102 OPT_STRING('p', "pid", &trace.opts.target.pid, "pid",
3103 "trace events on existing process id"),
David Ahernac9be8e2013-08-20 11:15:45 -06003104 OPT_STRING('t', "tid", &trace.opts.target.tid, "tid",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003105 "trace events on existing thread id"),
Arnaldo Carvalho de Melofa0e4ff2015-04-23 11:59:20 -03003106 OPT_CALLBACK(0, "filter-pids", &trace, "CSV list of pids",
3107 "pids to filter (by the kernel)", trace__set_filter_pids),
David Ahernac9be8e2013-08-20 11:15:45 -06003108 OPT_BOOLEAN('a', "all-cpus", &trace.opts.target.system_wide,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003109 "system-wide collection from all CPUs"),
David Ahernac9be8e2013-08-20 11:15:45 -06003110 OPT_STRING('C', "cpu", &trace.opts.target.cpu_list, "cpu",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003111 "list of cpus to monitor"),
David Ahern6810fc92013-08-28 22:29:52 -06003112 OPT_BOOLEAN(0, "no-inherit", &trace.opts.no_inherit,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003113 "child tasks do not inherit counters"),
Jiri Olsa994a1f72013-09-01 12:36:12 +02003114 OPT_CALLBACK('m', "mmap-pages", &trace.opts.mmap_pages, "pages",
3115 "number of mmap data pages",
3116 perf_evlist__parse_mmap_pages),
David Ahernac9be8e2013-08-20 11:15:45 -06003117 OPT_STRING('u', "uid", &trace.opts.target.uid_str, "user",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003118 "user to profile"),
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03003119 OPT_CALLBACK(0, "duration", &trace, "float",
3120 "show only events with duration > N.M ms",
3121 trace__set_duration),
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03003122 OPT_BOOLEAN(0, "sched", &trace.sched, "show blocking scheduler events"),
Arnaldo Carvalho de Melo7c304ee02013-08-22 16:49:54 -03003123 OPT_INCR('v', "verbose", &verbose, "be more verbose"),
David Ahern4bb09192013-09-04 12:37:43 -06003124 OPT_BOOLEAN('T', "time", &trace.full_time,
3125 "Show full timestamp, not time relative to first start"),
David Ahernfd2eaba2013-11-12 09:31:15 -07003126 OPT_BOOLEAN('s', "summary", &trace.summary_only,
3127 "Show only syscall summary with statistics"),
3128 OPT_BOOLEAN('S', "with-summary", &trace.summary,
3129 "Show all syscalls and summary with statistics"),
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04003130 OPT_CALLBACK_DEFAULT('F', "pf", &trace.trace_pgfaults, "all|maj|min",
3131 "Trace pagefaults", parse_pagefaults, "maj"),
Stanislav Fomicheve281a962014-06-26 20:14:28 +04003132 OPT_BOOLEAN(0, "syscalls", &trace.trace_syscalls, "Trace syscalls"),
Yunlong Songe366a6d2015-04-02 21:47:18 +08003133 OPT_BOOLEAN('f', "force", &trace.force, "don't complain, do it"),
Milian Wolff566a0882016-04-08 13:34:15 +02003134 OPT_CALLBACK(0, "call-graph", &trace.opts,
3135 "record_mode[,record_size]", record_callchain_help,
3136 &record_parse_callchain_opt),
Arnaldo Carvalho de Melo44621812016-04-11 15:49:11 -03003137 OPT_BOOLEAN(0, "kernel-syscall-graph", &trace.kernel_syscallchains,
3138 "Show the kernel callchains on the syscall exit path"),
Kan Liang9d9cad72015-06-17 09:51:11 -04003139 OPT_UINTEGER(0, "proc-map-timeout", &trace.opts.proc_map_timeout,
3140 "per thread proc mmap processing timeout in ms"),
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003141 OPT_END()
3142 };
Yunlong Song6fdd9cb2015-03-18 21:35:57 +08003143 const char * const trace_subcommands[] = { "record", NULL };
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003144 int err;
Namhyung Kim32caf0d2012-10-05 14:02:13 +09003145 char bf[BUFSIZ];
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003146
Arnaldo Carvalho de Melo4d08cb82015-02-24 15:35:55 -03003147 signal(SIGSEGV, sighandler_dump_stack);
3148 signal(SIGFPE, sighandler_dump_stack);
3149
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003150 trace.evlist = perf_evlist__new();
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03003151 trace.sctbl = syscalltbl__new();
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003152
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03003153 if (trace.evlist == NULL || trace.sctbl == NULL) {
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003154 pr_err("Not enough memory to run!\n");
He Kuangff8f6952015-05-11 12:28:36 +00003155 err = -ENOMEM;
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003156 goto out;
3157 }
3158
Yunlong Song6fdd9cb2015-03-18 21:35:57 +08003159 argc = parse_options_subcommand(argc, argv, trace_options, trace_subcommands,
3160 trace_usage, PARSE_OPT_STOP_AT_NON_OPTION);
David Ahernfd2eaba2013-11-12 09:31:15 -07003161
Wang Nand7888572016-04-08 15:07:24 +00003162 err = bpf__setup_stdout(trace.evlist);
3163 if (err) {
3164 bpf__strerror_setup_stdout(trace.evlist, err, bf, sizeof(bf));
3165 pr_err("ERROR: Setup BPF stdout failed: %s\n", bf);
3166 goto out;
3167 }
3168
Arnaldo Carvalho de Melo59247e32016-04-12 16:05:02 -03003169 err = -1;
3170
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04003171 if (trace.trace_pgfaults) {
3172 trace.opts.sample_address = true;
3173 trace.opts.sample_time = true;
3174 }
3175
Milian Wolff566a0882016-04-08 13:34:15 +02003176 if (trace.opts.callgraph_set)
3177 symbol_conf.use_callchain = true;
3178
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003179 if (trace.evlist->nr_entries > 0)
3180 evlist__set_evsel_handler(trace.evlist, trace__event_handler);
3181
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04003182 if ((argc >= 1) && (strcmp(argv[0], "record") == 0))
3183 return trace__record(&trace, argc-1, &argv[1]);
3184
3185 /* summary_only implies summary option, but don't overwrite summary if set */
3186 if (trace.summary_only)
3187 trace.summary = trace.summary_only;
3188
Arnaldo Carvalho de Melo726f3232015-02-06 10:16:45 +01003189 if (!trace.trace_syscalls && !trace.trace_pgfaults &&
3190 trace.evlist->nr_entries == 0 /* Was --events used? */) {
Stanislav Fomicheve281a962014-06-26 20:14:28 +04003191 pr_err("Please specify something to trace.\n");
3192 return -1;
3193 }
3194
Arnaldo Carvalho de Melo59247e32016-04-12 16:05:02 -03003195 if (!trace.trace_syscalls && ev_qualifier_str) {
3196 pr_err("The -e option can't be used with --no-syscalls.\n");
3197 goto out;
3198 }
3199
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003200 if (output_name != NULL) {
3201 err = trace__open_output(&trace, output_name);
3202 if (err < 0) {
3203 perror("failed to create output file");
3204 goto out;
3205 }
3206 }
3207
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03003208 trace.open_id = syscalltbl__id(trace.sctbl, "open");
3209
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03003210 if (ev_qualifier_str != NULL) {
Arnaldo Carvalho de Melob059efd2013-08-21 12:56:21 -03003211 const char *s = ev_qualifier_str;
Arnaldo Carvalho de Melo005438a82015-07-20 12:02:09 -03003212 struct strlist_config slist_config = {
3213 .dirname = system_path(STRACE_GROUPS_DIR),
3214 };
Arnaldo Carvalho de Melob059efd2013-08-21 12:56:21 -03003215
3216 trace.not_ev_qualifier = *s == '!';
3217 if (trace.not_ev_qualifier)
3218 ++s;
Arnaldo Carvalho de Melo005438a82015-07-20 12:02:09 -03003219 trace.ev_qualifier = strlist__new(s, &slist_config);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03003220 if (trace.ev_qualifier == NULL) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003221 fputs("Not enough memory to parse event qualifier",
3222 trace.output);
3223 err = -ENOMEM;
3224 goto out_close;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03003225 }
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03003226
3227 err = trace__validate_ev_qualifier(&trace);
3228 if (err)
3229 goto out_close;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03003230 }
3231
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003232 err = target__validate(&trace.opts.target);
Namhyung Kim32caf0d2012-10-05 14:02:13 +09003233 if (err) {
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003234 target__strerror(&trace.opts.target, err, bf, sizeof(bf));
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003235 fprintf(trace.output, "%s", bf);
3236 goto out_close;
Namhyung Kim32caf0d2012-10-05 14:02:13 +09003237 }
3238
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003239 err = target__parse_uid(&trace.opts.target);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003240 if (err) {
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003241 target__strerror(&trace.opts.target, err, bf, sizeof(bf));
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003242 fprintf(trace.output, "%s", bf);
3243 goto out_close;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003244 }
3245
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003246 if (!argc && target__none(&trace.opts.target))
Namhyung Kimee761202012-10-05 14:02:14 +09003247 trace.opts.target.system_wide = true;
3248
David Ahern6810fc92013-08-28 22:29:52 -06003249 if (input_name)
3250 err = trace__replay(&trace);
3251 else
3252 err = trace__run(&trace, argc, argv);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03003253
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003254out_close:
3255 if (output_name != NULL)
3256 fclose(trace.output);
3257out:
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03003258 return err;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003259}