blob: 9e38fe973f0c11f2af58ac90eadabab22bfe0af8 [file] [log] [blame]
Arnaldo Carvalho de Meloa598bb52015-08-28 12:02:37 -03001/*
2 * builtin-trace.c
3 *
4 * Builtin 'trace' command:
5 *
6 * Display a continuously updated trace of any workload, CPU, specific PID,
7 * system wide, etc. Default format is loosely strace like, but any other
8 * event may be specified using --event.
9 *
10 * Copyright (C) 2012, 2013, 2014, 2015 Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
11 *
12 * Initially based on the 'trace' prototype by Thomas Gleixner:
13 *
14 * http://lwn.net/Articles/415728/ ("Announcing a new utility: 'trace'")
15 *
16 * Released under the GPL v2. (and only v2, not any later version)
17 */
18
Robert Richter4e319022013-06-11 17:29:18 +020019#include <traceevent/event-parse.h>
Jiri Olsa988bdb32015-09-02 09:56:35 +020020#include <api/fs/tracing_path.h>
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -030021#include "builtin.h"
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -030022#include "util/color.h"
Arnaldo Carvalho de Melo7c304ee02013-08-22 16:49:54 -030023#include "util/debug.h"
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -030024#include "util/evlist.h"
Josh Poimboeuf4b6ab942015-12-15 09:39:39 -060025#include <subcmd/exec-cmd.h>
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -030026#include "util/machine.h"
David Ahern6810fc92013-08-28 22:29:52 -060027#include "util/session.h"
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -030028#include "util/thread.h"
Josh Poimboeuf4b6ab942015-12-15 09:39:39 -060029#include <subcmd/parse-options.h>
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -030030#include "util/strlist.h"
David Ahernbdc89662013-08-28 22:29:53 -060031#include "util/intlist.h"
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -030032#include "util/thread_map.h"
David Ahernbf2575c2013-10-08 21:26:53 -060033#include "util/stat.h"
Jiri Olsa97978b32013-12-03 14:09:24 +010034#include "trace-event.h"
David Ahern9aca7f12013-12-04 19:41:39 -070035#include "util/parse-events.h"
Wang Nanba504232016-02-26 09:31:54 +000036#include "util/bpf-loader.h"
Milian Wolff566a0882016-04-08 13:34:15 +020037#include "callchain.h"
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -030038#include "syscalltbl.h"
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -030039
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -030040#include <libaudit.h> /* FIXME: Still needed for audit_errno_to_name */
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -030041#include <stdlib.h>
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -030042#include <linux/futex.h>
Jiri Olsa8dd2a132015-09-07 10:38:06 +020043#include <linux/err.h>
Arnaldo Carvalho de Melo997bba82016-03-30 19:43:32 -030044#include <linux/seccomp.h>
45#include <linux/filter.h>
46#include <linux/audit.h>
47#include <sys/ptrace.h>
Arnaldo Carvalho de Melo39878d42016-03-30 20:02:15 -030048#include <linux/random.h>
Arnaldo Carvalho de Meloc6d4a492016-04-14 18:29:08 -030049#include <linux/stringify.h>
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -030050
Arnaldo Carvalho de Meloc188e7a2015-05-14 17:39:03 -030051#ifndef O_CLOEXEC
52# define O_CLOEXEC 02000000
53#endif
54
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -030055struct trace {
56 struct perf_tool tool;
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -030057 struct syscalltbl *sctbl;
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -030058 struct {
59 int max;
60 struct syscall *table;
61 struct {
62 struct perf_evsel *sys_enter,
63 *sys_exit;
64 } events;
65 } syscalls;
66 struct record_opts opts;
67 struct perf_evlist *evlist;
68 struct machine *host;
69 struct thread *current;
70 u64 base_time;
71 FILE *output;
72 unsigned long nr_events;
73 struct strlist *ev_qualifier;
74 struct {
75 size_t nr;
76 int *entries;
77 } ev_qualifier_ids;
78 struct intlist *tid_list;
79 struct intlist *pid_list;
80 struct {
81 size_t nr;
82 pid_t *entries;
83 } filter_pids;
84 double duration_filter;
85 double runtime_ms;
86 struct {
87 u64 vfs_getname,
88 proc_getname;
89 } stats;
Arnaldo Carvalho de Meloc6d4a492016-04-14 18:29:08 -030090 unsigned int max_stack;
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -030091 unsigned int min_stack;
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -030092 bool not_ev_qualifier;
93 bool live;
94 bool full_time;
95 bool sched;
96 bool multiple_threads;
97 bool summary;
98 bool summary_only;
99 bool show_comm;
100 bool show_tool_stats;
101 bool trace_syscalls;
Arnaldo Carvalho de Melo44621812016-04-11 15:49:11 -0300102 bool kernel_syscallchains;
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -0300103 bool force;
104 bool vfs_getname;
105 int trace_pgfaults;
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -0300106 int open_id;
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -0300107};
Arnaldo Carvalho de Meloa1c25522015-06-11 22:47:54 -0300108
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300109struct tp_field {
110 int offset;
111 union {
112 u64 (*integer)(struct tp_field *field, struct perf_sample *sample);
113 void *(*pointer)(struct tp_field *field, struct perf_sample *sample);
114 };
115};
116
117#define TP_UINT_FIELD(bits) \
118static u64 tp_field__u##bits(struct tp_field *field, struct perf_sample *sample) \
119{ \
David Ahern55d43bca2015-02-19 15:00:22 -0500120 u##bits value; \
121 memcpy(&value, sample->raw_data + field->offset, sizeof(value)); \
122 return value; \
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300123}
124
125TP_UINT_FIELD(8);
126TP_UINT_FIELD(16);
127TP_UINT_FIELD(32);
128TP_UINT_FIELD(64);
129
130#define TP_UINT_FIELD__SWAPPED(bits) \
131static u64 tp_field__swapped_u##bits(struct tp_field *field, struct perf_sample *sample) \
132{ \
David Ahern55d43bca2015-02-19 15:00:22 -0500133 u##bits value; \
134 memcpy(&value, sample->raw_data + field->offset, sizeof(value)); \
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300135 return bswap_##bits(value);\
136}
137
138TP_UINT_FIELD__SWAPPED(16);
139TP_UINT_FIELD__SWAPPED(32);
140TP_UINT_FIELD__SWAPPED(64);
141
142static int tp_field__init_uint(struct tp_field *field,
143 struct format_field *format_field,
144 bool needs_swap)
145{
146 field->offset = format_field->offset;
147
148 switch (format_field->size) {
149 case 1:
150 field->integer = tp_field__u8;
151 break;
152 case 2:
153 field->integer = needs_swap ? tp_field__swapped_u16 : tp_field__u16;
154 break;
155 case 4:
156 field->integer = needs_swap ? tp_field__swapped_u32 : tp_field__u32;
157 break;
158 case 8:
159 field->integer = needs_swap ? tp_field__swapped_u64 : tp_field__u64;
160 break;
161 default:
162 return -1;
163 }
164
165 return 0;
166}
167
168static void *tp_field__ptr(struct tp_field *field, struct perf_sample *sample)
169{
170 return sample->raw_data + field->offset;
171}
172
173static int tp_field__init_ptr(struct tp_field *field, struct format_field *format_field)
174{
175 field->offset = format_field->offset;
176 field->pointer = tp_field__ptr;
177 return 0;
178}
179
180struct syscall_tp {
181 struct tp_field id;
182 union {
183 struct tp_field args, ret;
184 };
185};
186
187static int perf_evsel__init_tp_uint_field(struct perf_evsel *evsel,
188 struct tp_field *field,
189 const char *name)
190{
191 struct format_field *format_field = perf_evsel__field(evsel, name);
192
193 if (format_field == NULL)
194 return -1;
195
196 return tp_field__init_uint(field, format_field, evsel->needs_swap);
197}
198
199#define perf_evsel__init_sc_tp_uint_field(evsel, name) \
200 ({ struct syscall_tp *sc = evsel->priv;\
201 perf_evsel__init_tp_uint_field(evsel, &sc->name, #name); })
202
203static int perf_evsel__init_tp_ptr_field(struct perf_evsel *evsel,
204 struct tp_field *field,
205 const char *name)
206{
207 struct format_field *format_field = perf_evsel__field(evsel, name);
208
209 if (format_field == NULL)
210 return -1;
211
212 return tp_field__init_ptr(field, format_field);
213}
214
215#define perf_evsel__init_sc_tp_ptr_field(evsel, name) \
216 ({ struct syscall_tp *sc = evsel->priv;\
217 perf_evsel__init_tp_ptr_field(evsel, &sc->name, #name); })
218
219static void perf_evsel__delete_priv(struct perf_evsel *evsel)
220{
Arnaldo Carvalho de Melo04662522013-12-26 17:41:15 -0300221 zfree(&evsel->priv);
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300222 perf_evsel__delete(evsel);
223}
224
Namhyung Kim96695d42013-11-12 08:51:45 -0300225static int perf_evsel__init_syscall_tp(struct perf_evsel *evsel, void *handler)
226{
227 evsel->priv = malloc(sizeof(struct syscall_tp));
228 if (evsel->priv != NULL) {
229 if (perf_evsel__init_sc_tp_uint_field(evsel, id))
230 goto out_delete;
231
232 evsel->handler = handler;
233 return 0;
234 }
235
236 return -ENOMEM;
237
238out_delete:
Arnaldo Carvalho de Melo04662522013-12-26 17:41:15 -0300239 zfree(&evsel->priv);
Namhyung Kim96695d42013-11-12 08:51:45 -0300240 return -ENOENT;
241}
242
Arnaldo Carvalho de Meloef503832013-11-07 16:41:19 -0300243static struct perf_evsel *perf_evsel__syscall_newtp(const char *direction, void *handler)
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300244{
Arnaldo Carvalho de Meloef503832013-11-07 16:41:19 -0300245 struct perf_evsel *evsel = perf_evsel__newtp("raw_syscalls", direction);
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300246
David Ahern9aca7f12013-12-04 19:41:39 -0700247 /* older kernel (e.g., RHEL6) use syscalls:{enter,exit} */
Jiri Olsa8dd2a132015-09-07 10:38:06 +0200248 if (IS_ERR(evsel))
David Ahern9aca7f12013-12-04 19:41:39 -0700249 evsel = perf_evsel__newtp("syscalls", direction);
250
Jiri Olsa8dd2a132015-09-07 10:38:06 +0200251 if (IS_ERR(evsel))
252 return NULL;
253
254 if (perf_evsel__init_syscall_tp(evsel, handler))
255 goto out_delete;
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300256
257 return evsel;
258
259out_delete:
260 perf_evsel__delete_priv(evsel);
261 return NULL;
262}
263
264#define perf_evsel__sc_tp_uint(evsel, name, sample) \
265 ({ struct syscall_tp *fields = evsel->priv; \
266 fields->name.integer(&fields->name, sample); })
267
268#define perf_evsel__sc_tp_ptr(evsel, name, sample) \
269 ({ struct syscall_tp *fields = evsel->priv; \
270 fields->name.pointer(&fields->name, sample); })
271
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300272struct syscall_arg {
273 unsigned long val;
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300274 struct thread *thread;
275 struct trace *trace;
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300276 void *parm;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300277 u8 idx;
278 u8 mask;
279};
280
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300281struct strarray {
Arnaldo Carvalho de Melo03e3adc2013-10-08 16:00:21 -0300282 int offset;
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300283 int nr_entries;
284 const char **entries;
285};
286
287#define DEFINE_STRARRAY(array) struct strarray strarray__##array = { \
288 .nr_entries = ARRAY_SIZE(array), \
289 .entries = array, \
290}
291
Arnaldo Carvalho de Melo03e3adc2013-10-08 16:00:21 -0300292#define DEFINE_STRARRAY_OFFSET(array, off) struct strarray strarray__##array = { \
293 .offset = off, \
294 .nr_entries = ARRAY_SIZE(array), \
295 .entries = array, \
296}
297
Arnaldo Carvalho de Melo975b7c22013-10-08 17:17:43 -0300298static size_t __syscall_arg__scnprintf_strarray(char *bf, size_t size,
299 const char *intfmt,
300 struct syscall_arg *arg)
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300301{
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300302 struct strarray *sa = arg->parm;
Arnaldo Carvalho de Melo03e3adc2013-10-08 16:00:21 -0300303 int idx = arg->val - sa->offset;
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300304
305 if (idx < 0 || idx >= sa->nr_entries)
Arnaldo Carvalho de Melo975b7c22013-10-08 17:17:43 -0300306 return scnprintf(bf, size, intfmt, arg->val);
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300307
308 return scnprintf(bf, size, "%s", sa->entries[idx]);
309}
310
Arnaldo Carvalho de Melo975b7c22013-10-08 17:17:43 -0300311static size_t syscall_arg__scnprintf_strarray(char *bf, size_t size,
312 struct syscall_arg *arg)
313{
314 return __syscall_arg__scnprintf_strarray(bf, size, "%d", arg);
315}
316
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300317#define SCA_STRARRAY syscall_arg__scnprintf_strarray
318
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -0300319#if defined(__i386__) || defined(__x86_64__)
320/*
321 * FIXME: Make this available to all arches as soon as the ioctl beautifier
322 * gets rewritten to support all arches.
323 */
Arnaldo Carvalho de Melo78645cf2013-10-08 17:43:20 -0300324static size_t syscall_arg__scnprintf_strhexarray(char *bf, size_t size,
325 struct syscall_arg *arg)
326{
327 return __syscall_arg__scnprintf_strarray(bf, size, "%#x", arg);
328}
329
330#define SCA_STRHEXARRAY syscall_arg__scnprintf_strhexarray
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -0300331#endif /* defined(__i386__) || defined(__x86_64__) */
Arnaldo Carvalho de Melo78645cf2013-10-08 17:43:20 -0300332
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300333static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
334 struct syscall_arg *arg);
335
336#define SCA_FD syscall_arg__scnprintf_fd
337
338static size_t syscall_arg__scnprintf_fd_at(char *bf, size_t size,
339 struct syscall_arg *arg)
340{
341 int fd = arg->val;
342
343 if (fd == AT_FDCWD)
344 return scnprintf(bf, size, "CWD");
345
346 return syscall_arg__scnprintf_fd(bf, size, arg);
347}
348
349#define SCA_FDAT syscall_arg__scnprintf_fd_at
350
351static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
352 struct syscall_arg *arg);
353
354#define SCA_CLOSE_FD syscall_arg__scnprintf_close_fd
355
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -0300356static size_t syscall_arg__scnprintf_hex(char *bf, size_t size,
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300357 struct syscall_arg *arg)
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -0300358{
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300359 return scnprintf(bf, size, "%#lx", arg->val);
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -0300360}
361
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -0300362#define SCA_HEX syscall_arg__scnprintf_hex
363
Arnaldo Carvalho de Meloa1c25522015-06-11 22:47:54 -0300364static size_t syscall_arg__scnprintf_int(char *bf, size_t size,
365 struct syscall_arg *arg)
366{
367 return scnprintf(bf, size, "%d", arg->val);
368}
369
370#define SCA_INT syscall_arg__scnprintf_int
371
Arnaldo Carvalho de Melo5cea6ff2013-09-20 11:49:50 -0300372static size_t syscall_arg__scnprintf_flock(char *bf, size_t size,
373 struct syscall_arg *arg)
374{
375 int printed = 0, op = arg->val;
376
377 if (op == 0)
378 return scnprintf(bf, size, "NONE");
379#define P_CMD(cmd) \
380 if ((op & LOCK_##cmd) == LOCK_##cmd) { \
381 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #cmd); \
382 op &= ~LOCK_##cmd; \
383 }
384
385 P_CMD(SH);
386 P_CMD(EX);
387 P_CMD(NB);
388 P_CMD(UN);
389 P_CMD(MAND);
390 P_CMD(RW);
391 P_CMD(READ);
392 P_CMD(WRITE);
393#undef P_OP
394
395 if (op)
396 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", op);
397
398 return printed;
399}
400
401#define SCA_FLOCK syscall_arg__scnprintf_flock
402
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300403static 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 -0300404{
405 enum syscall_futex_args {
406 SCF_UADDR = (1 << 0),
407 SCF_OP = (1 << 1),
408 SCF_VAL = (1 << 2),
409 SCF_TIMEOUT = (1 << 3),
410 SCF_UADDR2 = (1 << 4),
411 SCF_VAL3 = (1 << 5),
412 };
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300413 int op = arg->val;
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -0300414 int cmd = op & FUTEX_CMD_MASK;
415 size_t printed = 0;
416
417 switch (cmd) {
418#define P_FUTEX_OP(n) case FUTEX_##n: printed = scnprintf(bf, size, #n);
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300419 P_FUTEX_OP(WAIT); arg->mask |= SCF_VAL3|SCF_UADDR2; break;
420 P_FUTEX_OP(WAKE); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
421 P_FUTEX_OP(FD); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
422 P_FUTEX_OP(REQUEUE); arg->mask |= SCF_VAL3|SCF_TIMEOUT; break;
423 P_FUTEX_OP(CMP_REQUEUE); arg->mask |= SCF_TIMEOUT; break;
424 P_FUTEX_OP(CMP_REQUEUE_PI); arg->mask |= SCF_TIMEOUT; break;
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -0300425 P_FUTEX_OP(WAKE_OP); break;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300426 P_FUTEX_OP(LOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
427 P_FUTEX_OP(UNLOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
428 P_FUTEX_OP(TRYLOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2; break;
429 P_FUTEX_OP(WAIT_BITSET); arg->mask |= SCF_UADDR2; break;
430 P_FUTEX_OP(WAKE_BITSET); arg->mask |= SCF_UADDR2; break;
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -0300431 P_FUTEX_OP(WAIT_REQUEUE_PI); break;
432 default: printed = scnprintf(bf, size, "%#x", cmd); break;
433 }
434
435 if (op & FUTEX_PRIVATE_FLAG)
436 printed += scnprintf(bf + printed, size - printed, "|PRIV");
437
438 if (op & FUTEX_CLOCK_REALTIME)
439 printed += scnprintf(bf + printed, size - printed, "|CLKRT");
440
441 return printed;
442}
443
Arnaldo Carvalho de Meloefe6b882013-09-03 16:15:12 -0300444#define SCA_FUTEX_OP syscall_arg__scnprintf_futex_op
445
Arnaldo Carvalho de Melo729a7842015-10-29 11:48:18 -0300446static const char *bpf_cmd[] = {
447 "MAP_CREATE", "MAP_LOOKUP_ELEM", "MAP_UPDATE_ELEM", "MAP_DELETE_ELEM",
448 "MAP_GET_NEXT_KEY", "PROG_LOAD",
449};
450static DEFINE_STRARRAY(bpf_cmd);
451
Arnaldo Carvalho de Melo03e3adc2013-10-08 16:00:21 -0300452static const char *epoll_ctl_ops[] = { "ADD", "DEL", "MOD", };
453static DEFINE_STRARRAY_OFFSET(epoll_ctl_ops, 1);
Arnaldo Carvalho de Meloeac032c2013-09-20 11:27:32 -0300454
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300455static const char *itimers[] = { "REAL", "VIRTUAL", "PROF", };
456static DEFINE_STRARRAY(itimers);
457
Arnaldo Carvalho de Melob62bee12015-08-11 11:05:36 -0300458static const char *keyctl_options[] = {
459 "GET_KEYRING_ID", "JOIN_SESSION_KEYRING", "UPDATE", "REVOKE", "CHOWN",
460 "SETPERM", "DESCRIBE", "CLEAR", "LINK", "UNLINK", "SEARCH", "READ",
461 "INSTANTIATE", "NEGATE", "SET_REQKEY_KEYRING", "SET_TIMEOUT",
462 "ASSUME_AUTHORITY", "GET_SECURITY", "SESSION_TO_PARENT", "REJECT",
463 "INSTANTIATE_IOV", "INVALIDATE", "GET_PERSISTENT",
464};
465static DEFINE_STRARRAY(keyctl_options);
466
Arnaldo Carvalho de Meloefe6b882013-09-03 16:15:12 -0300467static const char *whences[] = { "SET", "CUR", "END",
468#ifdef SEEK_DATA
469"DATA",
470#endif
471#ifdef SEEK_HOLE
472"HOLE",
473#endif
474};
475static DEFINE_STRARRAY(whences);
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -0300476
Arnaldo Carvalho de Melo80f587d2013-09-03 16:28:58 -0300477static const char *fcntl_cmds[] = {
478 "DUPFD", "GETFD", "SETFD", "GETFL", "SETFL", "GETLK", "SETLK",
479 "SETLKW", "SETOWN", "GETOWN", "SETSIG", "GETSIG", "F_GETLK64",
480 "F_SETLK64", "F_SETLKW64", "F_SETOWN_EX", "F_GETOWN_EX",
481 "F_GETOWNER_UIDS",
482};
483static DEFINE_STRARRAY(fcntl_cmds);
484
Arnaldo Carvalho de Meloc045bf02013-09-04 11:52:33 -0300485static const char *rlimit_resources[] = {
486 "CPU", "FSIZE", "DATA", "STACK", "CORE", "RSS", "NPROC", "NOFILE",
487 "MEMLOCK", "AS", "LOCKS", "SIGPENDING", "MSGQUEUE", "NICE", "RTPRIO",
488 "RTTIME",
489};
490static DEFINE_STRARRAY(rlimit_resources);
491
Arnaldo Carvalho de Meloeb5b1b12013-09-03 16:37:46 -0300492static const char *sighow[] = { "BLOCK", "UNBLOCK", "SETMASK", };
493static DEFINE_STRARRAY(sighow);
494
David Ahern4f8c1b72013-09-22 19:45:00 -0600495static const char *clockid[] = {
496 "REALTIME", "MONOTONIC", "PROCESS_CPUTIME_ID", "THREAD_CPUTIME_ID",
Arnaldo Carvalho de Melo28ebb872015-08-11 10:38:38 -0300497 "MONOTONIC_RAW", "REALTIME_COARSE", "MONOTONIC_COARSE", "BOOTTIME",
498 "REALTIME_ALARM", "BOOTTIME_ALARM", "SGI_CYCLE", "TAI"
David Ahern4f8c1b72013-09-22 19:45:00 -0600499};
500static DEFINE_STRARRAY(clockid);
501
Arnaldo Carvalho de Meloe10bce82013-09-04 10:27:41 -0300502static const char *socket_families[] = {
503 "UNSPEC", "LOCAL", "INET", "AX25", "IPX", "APPLETALK", "NETROM",
504 "BRIDGE", "ATMPVC", "X25", "INET6", "ROSE", "DECnet", "NETBEUI",
505 "SECURITY", "KEY", "NETLINK", "PACKET", "ASH", "ECONET", "ATMSVC",
506 "RDS", "SNA", "IRDA", "PPPOX", "WANPIPE", "LLC", "IB", "CAN", "TIPC",
507 "BLUETOOTH", "IUCV", "RXRPC", "ISDN", "PHONET", "IEEE802154", "CAIF",
508 "ALG", "NFC", "VSOCK",
509};
510static DEFINE_STRARRAY(socket_families);
511
Arnaldo Carvalho de Melo51108992013-09-04 11:42:27 -0300512static size_t syscall_arg__scnprintf_access_mode(char *bf, size_t size,
513 struct syscall_arg *arg)
514{
515 size_t printed = 0;
516 int mode = arg->val;
517
518 if (mode == F_OK) /* 0 */
519 return scnprintf(bf, size, "F");
520#define P_MODE(n) \
521 if (mode & n##_OK) { \
522 printed += scnprintf(bf + printed, size - printed, "%s", #n); \
523 mode &= ~n##_OK; \
524 }
525
526 P_MODE(R);
527 P_MODE(W);
528 P_MODE(X);
529#undef P_MODE
530
531 if (mode)
532 printed += scnprintf(bf + printed, size - printed, "|%#x", mode);
533
534 return printed;
535}
536
537#define SCA_ACCMODE syscall_arg__scnprintf_access_mode
538
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -0300539static size_t syscall_arg__scnprintf_filename(char *bf, size_t size,
540 struct syscall_arg *arg);
541
542#define SCA_FILENAME syscall_arg__scnprintf_filename
543
Arnaldo Carvalho de Melobe65a892013-09-02 16:22:31 -0300544static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300545 struct syscall_arg *arg)
Arnaldo Carvalho de Melobe65a892013-09-02 16:22:31 -0300546{
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300547 int printed = 0, flags = arg->val;
Arnaldo Carvalho de Melobe65a892013-09-02 16:22:31 -0300548
549 if (!(flags & O_CREAT))
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300550 arg->mask |= 1 << (arg->idx + 1); /* Mask the mode parm */
Arnaldo Carvalho de Melobe65a892013-09-02 16:22:31 -0300551
552 if (flags == 0)
553 return scnprintf(bf, size, "RDONLY");
554#define P_FLAG(n) \
555 if (flags & O_##n) { \
556 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
557 flags &= ~O_##n; \
558 }
559
560 P_FLAG(APPEND);
561 P_FLAG(ASYNC);
562 P_FLAG(CLOEXEC);
563 P_FLAG(CREAT);
564 P_FLAG(DIRECT);
565 P_FLAG(DIRECTORY);
566 P_FLAG(EXCL);
567 P_FLAG(LARGEFILE);
568 P_FLAG(NOATIME);
569 P_FLAG(NOCTTY);
570#ifdef O_NONBLOCK
571 P_FLAG(NONBLOCK);
572#elif O_NDELAY
573 P_FLAG(NDELAY);
574#endif
575#ifdef O_PATH
576 P_FLAG(PATH);
577#endif
578 P_FLAG(RDWR);
579#ifdef O_DSYNC
580 if ((flags & O_SYNC) == O_SYNC)
581 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", "SYNC");
582 else {
583 P_FLAG(DSYNC);
584 }
585#else
586 P_FLAG(SYNC);
587#endif
588 P_FLAG(TRUNC);
589 P_FLAG(WRONLY);
590#undef P_FLAG
591
592 if (flags)
593 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
594
595 return printed;
596}
597
598#define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags
599
Arnaldo Carvalho de Melo46cce192013-09-23 12:52:04 -0300600static size_t syscall_arg__scnprintf_pipe_flags(char *bf, size_t size,
601 struct syscall_arg *arg)
602{
603 int printed = 0, flags = arg->val;
604
605#define P_FLAG(n) \
606 if (flags & O_##n) { \
607 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
608 flags &= ~O_##n; \
609 }
610
611 P_FLAG(CLOEXEC);
612 P_FLAG(NONBLOCK);
613#undef P_FLAG
614
615 if (flags)
616 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
617
618 return printed;
619}
620
621#define SCA_PIPE_FLAGS syscall_arg__scnprintf_pipe_flags
622
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -0300623static size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscall_arg *arg)
624{
625 int sig = arg->val;
626
627 switch (sig) {
628#define P_SIGNUM(n) case SIG##n: return scnprintf(bf, size, #n)
629 P_SIGNUM(HUP);
630 P_SIGNUM(INT);
631 P_SIGNUM(QUIT);
632 P_SIGNUM(ILL);
633 P_SIGNUM(TRAP);
634 P_SIGNUM(ABRT);
635 P_SIGNUM(BUS);
636 P_SIGNUM(FPE);
637 P_SIGNUM(KILL);
638 P_SIGNUM(USR1);
639 P_SIGNUM(SEGV);
640 P_SIGNUM(USR2);
641 P_SIGNUM(PIPE);
642 P_SIGNUM(ALRM);
643 P_SIGNUM(TERM);
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -0300644 P_SIGNUM(CHLD);
645 P_SIGNUM(CONT);
646 P_SIGNUM(STOP);
647 P_SIGNUM(TSTP);
648 P_SIGNUM(TTIN);
649 P_SIGNUM(TTOU);
650 P_SIGNUM(URG);
651 P_SIGNUM(XCPU);
652 P_SIGNUM(XFSZ);
653 P_SIGNUM(VTALRM);
654 P_SIGNUM(PROF);
655 P_SIGNUM(WINCH);
656 P_SIGNUM(IO);
657 P_SIGNUM(PWR);
658 P_SIGNUM(SYS);
Ben Hutchings02c5bb42014-02-06 01:00:41 +0000659#ifdef SIGEMT
660 P_SIGNUM(EMT);
661#endif
662#ifdef SIGSTKFLT
663 P_SIGNUM(STKFLT);
664#endif
665#ifdef SIGSWI
666 P_SIGNUM(SWI);
667#endif
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -0300668 default: break;
669 }
670
671 return scnprintf(bf, size, "%#x", sig);
672}
673
674#define SCA_SIGNUM syscall_arg__scnprintf_signum
675
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -0300676#if defined(__i386__) || defined(__x86_64__)
677/*
678 * FIXME: Make this available to all arches.
679 */
Arnaldo Carvalho de Melo78645cf2013-10-08 17:43:20 -0300680#define TCGETS 0x5401
681
682static const char *tioctls[] = {
683 "TCGETS", "TCSETS", "TCSETSW", "TCSETSF", "TCGETA", "TCSETA", "TCSETAW",
684 "TCSETAF", "TCSBRK", "TCXONC", "TCFLSH", "TIOCEXCL", "TIOCNXCL",
685 "TIOCSCTTY", "TIOCGPGRP", "TIOCSPGRP", "TIOCOUTQ", "TIOCSTI",
686 "TIOCGWINSZ", "TIOCSWINSZ", "TIOCMGET", "TIOCMBIS", "TIOCMBIC",
687 "TIOCMSET", "TIOCGSOFTCAR", "TIOCSSOFTCAR", "FIONREAD", "TIOCLINUX",
688 "TIOCCONS", "TIOCGSERIAL", "TIOCSSERIAL", "TIOCPKT", "FIONBIO",
689 "TIOCNOTTY", "TIOCSETD", "TIOCGETD", "TCSBRKP", [0x27] = "TIOCSBRK",
690 "TIOCCBRK", "TIOCGSID", "TCGETS2", "TCSETS2", "TCSETSW2", "TCSETSF2",
691 "TIOCGRS485", "TIOCSRS485", "TIOCGPTN", "TIOCSPTLCK",
692 "TIOCGDEV||TCGETX", "TCSETX", "TCSETXF", "TCSETXW", "TIOCSIG",
693 "TIOCVHANGUP", "TIOCGPKT", "TIOCGPTLCK", "TIOCGEXCL",
694 [0x50] = "FIONCLEX", "FIOCLEX", "FIOASYNC", "TIOCSERCONFIG",
695 "TIOCSERGWILD", "TIOCSERSWILD", "TIOCGLCKTRMIOS", "TIOCSLCKTRMIOS",
696 "TIOCSERGSTRUCT", "TIOCSERGETLSR", "TIOCSERGETMULTI", "TIOCSERSETMULTI",
697 "TIOCMIWAIT", "TIOCGICOUNT", [0x60] = "FIOQSIZE",
698};
699
700static DEFINE_STRARRAY_OFFSET(tioctls, 0x5401);
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -0300701#endif /* defined(__i386__) || defined(__x86_64__) */
Arnaldo Carvalho de Melo78645cf2013-10-08 17:43:20 -0300702
Arnaldo Carvalho de Melo6fb35b92016-04-13 11:50:23 -0300703#ifndef SECCOMP_SET_MODE_STRICT
704#define SECCOMP_SET_MODE_STRICT 0
705#endif
706#ifndef SECCOMP_SET_MODE_FILTER
707#define SECCOMP_SET_MODE_FILTER 1
708#endif
709
Arnaldo Carvalho de Melo997bba82016-03-30 19:43:32 -0300710static size_t syscall_arg__scnprintf_seccomp_op(char *bf, size_t size, struct syscall_arg *arg)
711{
712 int op = arg->val;
713 size_t printed = 0;
714
715 switch (op) {
716#define P_SECCOMP_SET_MODE_OP(n) case SECCOMP_SET_MODE_##n: printed = scnprintf(bf, size, #n); break
717 P_SECCOMP_SET_MODE_OP(STRICT);
718 P_SECCOMP_SET_MODE_OP(FILTER);
719#undef P_SECCOMP_SET_MODE_OP
720 default: printed = scnprintf(bf, size, "%#x", op); break;
721 }
722
723 return printed;
724}
725
726#define SCA_SECCOMP_OP syscall_arg__scnprintf_seccomp_op
727
Arnaldo Carvalho de Melo6fb35b92016-04-13 11:50:23 -0300728#ifndef SECCOMP_FILTER_FLAG_TSYNC
729#define SECCOMP_FILTER_FLAG_TSYNC 1
730#endif
731
Arnaldo Carvalho de Melo997bba82016-03-30 19:43:32 -0300732static size_t syscall_arg__scnprintf_seccomp_flags(char *bf, size_t size,
733 struct syscall_arg *arg)
734{
735 int printed = 0, flags = arg->val;
736
737#define P_FLAG(n) \
738 if (flags & SECCOMP_FILTER_FLAG_##n) { \
739 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
740 flags &= ~SECCOMP_FILTER_FLAG_##n; \
741 }
742
743 P_FLAG(TSYNC);
744#undef P_FLAG
745
746 if (flags)
747 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
748
749 return printed;
750}
751
752#define SCA_SECCOMP_FLAGS syscall_arg__scnprintf_seccomp_flags
753
Arnaldo Carvalho de Meloa355a612016-04-13 11:55:18 -0300754#ifndef GRND_NONBLOCK
755#define GRND_NONBLOCK 0x0001
756#endif
757#ifndef GRND_RANDOM
758#define GRND_RANDOM 0x0002
759#endif
760
Arnaldo Carvalho de Melo39878d42016-03-30 20:02:15 -0300761static size_t syscall_arg__scnprintf_getrandom_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 & GRND_##n) { \
768 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
769 flags &= ~GRND_##n; \
770 }
771
772 P_FLAG(RANDOM);
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_GETRANDOM_FLAGS syscall_arg__scnprintf_getrandom_flags
783
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300784#define STRARRAY(arg, name, array) \
785 .arg_scnprintf = { [arg] = SCA_STRARRAY, }, \
786 .arg_parm = { [arg] = &strarray__##array, }
787
Arnaldo Carvalho de Meloea8dc3c2016-04-13 12:10:19 -0300788#include "trace/beauty/eventfd.c"
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -0300789#include "trace/beauty/pid.c"
Arnaldo Carvalho de Melodf4cb162016-04-13 12:05:44 -0300790#include "trace/beauty/mmap.c"
Arnaldo Carvalho de Meloba2f22c2016-04-07 12:05:51 -0300791#include "trace/beauty/mode_t.c"
Arnaldo Carvalho de Meloa30e6252016-04-27 19:01:52 -0300792#include "trace/beauty/msg_flags.c"
Arnaldo Carvalho de Melo62de3442016-04-26 11:03:03 -0300793#include "trace/beauty/perf_event_open.c"
Arnaldo Carvalho de Meloa3bca912016-04-06 12:51:33 -0300794#include "trace/beauty/sched_policy.c"
Arnaldo Carvalho de Melobbf86c42016-04-14 13:53:10 -0300795#include "trace/beauty/socket_type.c"
Arnaldo Carvalho de Melo7206b902016-04-06 14:11:36 -0300796#include "trace/beauty/waitid_options.c"
Arnaldo Carvalho de Meloa3bca912016-04-06 12:51:33 -0300797
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300798static struct syscall_fmt {
799 const char *name;
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -0300800 const char *alias;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300801 size_t (*arg_scnprintf[6])(char *bf, size_t size, struct syscall_arg *arg);
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300802 void *arg_parm[6];
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300803 bool errmsg;
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -0300804 bool errpid;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300805 bool timeout;
Arnaldo Carvalho de Melo04b34722013-08-26 11:36:30 -0300806 bool hexret;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300807} syscall_fmts[] = {
Arnaldo Carvalho de Melo51108992013-09-04 11:42:27 -0300808 { .name = "access", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300809 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */
810 [1] = SCA_ACCMODE, /* mode */ }, },
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -0300811 { .name = "arch_prctl", .errmsg = true, .alias = "prctl", },
Arnaldo Carvalho de Melo729a7842015-10-29 11:48:18 -0300812 { .name = "bpf", .errmsg = true, STRARRAY(0, cmd, bpf_cmd), },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -0300813 { .name = "brk", .hexret = true,
814 .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300815 { .name = "chdir", .errmsg = true,
816 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
817 { .name = "chmod", .errmsg = true,
818 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
819 { .name = "chroot", .errmsg = true,
820 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
David Ahern4f8c1b72013-09-22 19:45:00 -0600821 { .name = "clock_gettime", .errmsg = true, STRARRAY(0, clk_id, clockid), },
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -0300822 { .name = "clone", .errpid = true, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300823 { .name = "close", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300824 .arg_scnprintf = { [0] = SCA_CLOSE_FD, /* fd */ }, },
Arnaldo Carvalho de Meloa14bb862013-07-30 16:38:23 -0300825 { .name = "connect", .errmsg = true, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300826 { .name = "creat", .errmsg = true,
827 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300828 { .name = "dup", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300829 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300830 { .name = "dup2", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300831 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300832 { .name = "dup3", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300833 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300834 { .name = "epoll_ctl", .errmsg = true, STRARRAY(1, op, epoll_ctl_ops), },
Arnaldo Carvalho de Melo49af9e92013-09-12 12:18:56 -0300835 { .name = "eventfd2", .errmsg = true,
836 .arg_scnprintf = { [1] = SCA_EFD_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300837 { .name = "faccessat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300838 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
839 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300840 { .name = "fadvise64", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300841 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300842 { .name = "fallocate", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300843 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300844 { .name = "fchdir", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300845 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300846 { .name = "fchmod", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300847 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300848 { .name = "fchmodat", .errmsg = true,
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -0300849 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */
850 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300851 { .name = "fchown", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300852 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300853 { .name = "fchownat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300854 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */
855 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300856 { .name = "fcntl", .errmsg = true,
857 .arg_scnprintf = { [0] = SCA_FD, /* fd */
858 [1] = SCA_STRARRAY, /* cmd */ },
859 .arg_parm = { [1] = &strarray__fcntl_cmds, /* cmd */ }, },
860 { .name = "fdatasync", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300861 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo5cea6ff2013-09-20 11:49:50 -0300862 { .name = "flock", .errmsg = true,
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300863 .arg_scnprintf = { [0] = SCA_FD, /* fd */
864 [1] = SCA_FLOCK, /* cmd */ }, },
865 { .name = "fsetxattr", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300866 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300867 { .name = "fstat", .errmsg = true, .alias = "newfstat",
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300868 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300869 { .name = "fstatat", .errmsg = true, .alias = "newfstatat",
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300870 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
871 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300872 { .name = "fstatfs", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300873 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300874 { .name = "fsync", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300875 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300876 { .name = "ftruncate", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300877 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -0300878 { .name = "futex", .errmsg = true,
879 .arg_scnprintf = { [1] = SCA_FUTEX_OP, /* op */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300880 { .name = "futimesat", .errmsg = true,
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -0300881 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */
882 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300883 { .name = "getdents", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300884 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300885 { .name = "getdents64", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300886 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300887 { .name = "getitimer", .errmsg = true, STRARRAY(0, which, itimers), },
Arnaldo Carvalho de Meloc65f1072016-04-06 14:55:18 -0300888 { .name = "getpid", .errpid = true, },
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -0300889 { .name = "getpgid", .errpid = true, },
Arnaldo Carvalho de Meloc65f1072016-04-06 14:55:18 -0300890 { .name = "getppid", .errpid = true, },
Arnaldo Carvalho de Melo39878d42016-03-30 20:02:15 -0300891 { .name = "getrandom", .errmsg = true,
892 .arg_scnprintf = { [2] = SCA_GETRANDOM_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300893 { .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300894 { .name = "getxattr", .errmsg = true,
895 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
896 { .name = "inotify_add_watch", .errmsg = true,
897 .arg_scnprintf = { [1] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -0300898 { .name = "ioctl", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300899 .arg_scnprintf = { [0] = SCA_FD, /* fd */
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -0300900#if defined(__i386__) || defined(__x86_64__)
901/*
902 * FIXME: Make this available to all arches.
903 */
Arnaldo Carvalho de Melo78645cf2013-10-08 17:43:20 -0300904 [1] = SCA_STRHEXARRAY, /* cmd */
905 [2] = SCA_HEX, /* arg */ },
906 .arg_parm = { [1] = &strarray__tioctls, /* cmd */ }, },
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -0300907#else
908 [2] = SCA_HEX, /* arg */ }, },
909#endif
Arnaldo Carvalho de Melob62bee12015-08-11 11:05:36 -0300910 { .name = "keyctl", .errmsg = true, STRARRAY(0, option, keyctl_options), },
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -0300911 { .name = "kill", .errmsg = true,
912 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300913 { .name = "lchown", .errmsg = true,
914 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
915 { .name = "lgetxattr", .errmsg = true,
916 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300917 { .name = "linkat", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300918 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300919 { .name = "listxattr", .errmsg = true,
920 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -0300921 { .name = "llistxattr", .errmsg = true,
922 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
923 { .name = "lremovexattr", .errmsg = true,
924 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300925 { .name = "lseek", .errmsg = true,
926 .arg_scnprintf = { [0] = SCA_FD, /* fd */
927 [2] = SCA_STRARRAY, /* whence */ },
928 .arg_parm = { [2] = &strarray__whences, /* whence */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300929 { .name = "lsetxattr", .errmsg = true,
930 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -0300931 { .name = "lstat", .errmsg = true, .alias = "newlstat",
932 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300933 { .name = "lsxattr", .errmsg = true,
934 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo9e9716d2013-08-23 10:06:41 -0300935 { .name = "madvise", .errmsg = true,
936 .arg_scnprintf = { [0] = SCA_HEX, /* start */
937 [2] = SCA_MADV_BHV, /* behavior */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300938 { .name = "mkdir", .errmsg = true,
939 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300940 { .name = "mkdirat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300941 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */
942 [1] = SCA_FILENAME, /* pathname */ }, },
943 { .name = "mknod", .errmsg = true,
944 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300945 { .name = "mknodat", .errmsg = true,
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -0300946 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */
947 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo3d903aa2013-09-24 00:09:38 -0300948 { .name = "mlock", .errmsg = true,
949 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
950 { .name = "mlockall", .errmsg = true,
951 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -0300952 { .name = "mmap", .hexret = true,
Arnaldo Carvalho de Meloae685382013-08-20 17:44:42 -0300953 .arg_scnprintf = { [0] = SCA_HEX, /* addr */
Arnaldo Carvalho de Melo941557e2013-08-23 10:48:33 -0300954 [2] = SCA_MMAP_PROT, /* prot */
Namhyung Kim73faab32013-11-12 15:24:59 +0900955 [3] = SCA_MMAP_FLAGS, /* flags */
956 [4] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -0300957 { .name = "mprotect", .errmsg = true,
Arnaldo Carvalho de Meloae685382013-08-20 17:44:42 -0300958 .arg_scnprintf = { [0] = SCA_HEX, /* start */
959 [2] = SCA_MMAP_PROT, /* prot */ }, },
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -0300960 { .name = "mq_unlink", .errmsg = true,
961 .arg_scnprintf = { [0] = SCA_FILENAME, /* u_name */ }, },
Arnaldo Carvalho de Meloae685382013-08-20 17:44:42 -0300962 { .name = "mremap", .hexret = true,
963 .arg_scnprintf = { [0] = SCA_HEX, /* addr */
Alex Snast86998dd2014-08-13 18:42:40 +0300964 [3] = SCA_MREMAP_FLAGS, /* flags */
Arnaldo Carvalho de Meloae685382013-08-20 17:44:42 -0300965 [4] = SCA_HEX, /* new_addr */ }, },
Arnaldo Carvalho de Melo3d903aa2013-09-24 00:09:38 -0300966 { .name = "munlock", .errmsg = true,
967 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -0300968 { .name = "munmap", .errmsg = true,
969 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300970 { .name = "name_to_handle_at", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300971 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300972 { .name = "newfstatat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300973 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
974 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melobe65a892013-09-02 16:22:31 -0300975 { .name = "open", .errmsg = true,
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -0300976 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */
977 [1] = SCA_OPEN_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo31cd3852013-09-02 16:40:40 -0300978 { .name = "open_by_handle_at", .errmsg = true,
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300979 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
980 [2] = SCA_OPEN_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo31cd3852013-09-02 16:40:40 -0300981 { .name = "openat", .errmsg = true,
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300982 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300983 [1] = SCA_FILENAME, /* filename */
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300984 [2] = SCA_OPEN_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Meloa1c25522015-06-11 22:47:54 -0300985 { .name = "perf_event_open", .errmsg = true,
Arnaldo Carvalho de Meloccd9b2a2016-04-26 11:40:17 -0300986 .arg_scnprintf = { [2] = SCA_INT, /* cpu */
Arnaldo Carvalho de Meloa1c25522015-06-11 22:47:54 -0300987 [3] = SCA_FD, /* group_fd */
988 [4] = SCA_PERF_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo46cce192013-09-23 12:52:04 -0300989 { .name = "pipe2", .errmsg = true,
990 .arg_scnprintf = { [1] = SCA_PIPE_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -0300991 { .name = "poll", .errmsg = true, .timeout = true, },
992 { .name = "ppoll", .errmsg = true, .timeout = true, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300993 { .name = "pread", .errmsg = true, .alias = "pread64",
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300994 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300995 { .name = "preadv", .errmsg = true, .alias = "pread",
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300996 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300997 { .name = "prlimit64", .errmsg = true, STRARRAY(1, resource, rlimit_resources), },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300998 { .name = "pwrite", .errmsg = true, .alias = "pwrite64",
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 = "pwritev", .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 = "read", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001003 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001004 { .name = "readlink", .errmsg = true,
1005 .arg_scnprintf = { [0] = SCA_FILENAME, /* path */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001006 { .name = "readlinkat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001007 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
1008 [1] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001009 { .name = "readv", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001010 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -03001011 { .name = "recvfrom", .errmsg = true,
Arnaldo Carvalho de Melo8d8c66a2015-08-11 10:57:02 -03001012 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1013 [3] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -03001014 { .name = "recvmmsg", .errmsg = true,
Arnaldo Carvalho de Melo8d8c66a2015-08-11 10:57:02 -03001015 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1016 [3] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -03001017 { .name = "recvmsg", .errmsg = true,
Arnaldo Carvalho de Melo8d8c66a2015-08-11 10:57:02 -03001018 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1019 [2] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001020 { .name = "removexattr", .errmsg = true,
1021 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001022 { .name = "renameat", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001023 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001024 { .name = "rmdir", .errmsg = true,
1025 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -03001026 { .name = "rt_sigaction", .errmsg = true,
1027 .arg_scnprintf = { [0] = SCA_SIGNUM, /* sig */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -03001028 { .name = "rt_sigprocmask", .errmsg = true, STRARRAY(0, how, sighow), },
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -03001029 { .name = "rt_sigqueueinfo", .errmsg = true,
1030 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
1031 { .name = "rt_tgsigqueueinfo", .errmsg = true,
1032 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
Arnaldo Carvalho de Meloa3bca912016-04-06 12:51:33 -03001033 { .name = "sched_setscheduler", .errmsg = true,
1034 .arg_scnprintf = { [1] = SCA_SCHED_POLICY, /* policy */ }, },
Arnaldo Carvalho de Melo997bba82016-03-30 19:43:32 -03001035 { .name = "seccomp", .errmsg = true,
1036 .arg_scnprintf = { [0] = SCA_SECCOMP_OP, /* op */
1037 [1] = SCA_SECCOMP_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -03001038 { .name = "select", .errmsg = true, .timeout = true, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -03001039 { .name = "sendmmsg", .errmsg = true,
Arnaldo Carvalho de Melo8d8c66a2015-08-11 10:57:02 -03001040 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1041 [3] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -03001042 { .name = "sendmsg", .errmsg = true,
Arnaldo Carvalho de Melo8d8c66a2015-08-11 10:57:02 -03001043 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1044 [2] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -03001045 { .name = "sendto", .errmsg = true,
Arnaldo Carvalho de Melo8d8c66a2015-08-11 10:57:02 -03001046 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1047 [3] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Meloc65f1072016-04-06 14:55:18 -03001048 { .name = "set_tid_address", .errpid = true, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -03001049 { .name = "setitimer", .errmsg = true, STRARRAY(0, which, itimers), },
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -03001050 { .name = "setpgid", .errmsg = true, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -03001051 { .name = "setrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001052 { .name = "setxattr", .errmsg = true,
1053 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001054 { .name = "shutdown", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001055 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Meloe10bce82013-09-04 10:27:41 -03001056 { .name = "socket", .errmsg = true,
Arnaldo Carvalho de Meloa28b24b2013-09-04 11:00:44 -03001057 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
1058 [1] = SCA_SK_TYPE, /* type */ },
Arnaldo Carvalho de Meloe10bce82013-09-04 10:27:41 -03001059 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, },
Arnaldo Carvalho de Melo07120aa2013-09-20 12:24:20 -03001060 { .name = "socketpair", .errmsg = true,
1061 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
1062 [1] = SCA_SK_TYPE, /* type */ },
1063 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, },
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -03001064 { .name = "stat", .errmsg = true, .alias = "newstat",
1065 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001066 { .name = "statfs", .errmsg = true,
1067 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
1068 { .name = "swapoff", .errmsg = true,
1069 .arg_scnprintf = { [0] = SCA_FILENAME, /* specialfile */ }, },
1070 { .name = "swapon", .errmsg = true,
1071 .arg_scnprintf = { [0] = SCA_FILENAME, /* specialfile */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001072 { .name = "symlinkat", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001073 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -03001074 { .name = "tgkill", .errmsg = true,
1075 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
1076 { .name = "tkill", .errmsg = true,
1077 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001078 { .name = "truncate", .errmsg = true,
1079 .arg_scnprintf = { [0] = SCA_FILENAME, /* path */ }, },
Arnaldo Carvalho de Meloe5959682013-08-26 12:21:41 -03001080 { .name = "uname", .errmsg = true, .alias = "newuname", },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001081 { .name = "unlinkat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001082 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
1083 [1] = SCA_FILENAME, /* pathname */ }, },
1084 { .name = "utime", .errmsg = true,
1085 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001086 { .name = "utimensat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001087 .arg_scnprintf = { [0] = SCA_FDAT, /* dirfd */
1088 [1] = SCA_FILENAME, /* filename */ }, },
1089 { .name = "utimes", .errmsg = true,
1090 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -03001091 { .name = "vmsplice", .errmsg = true,
1092 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -03001093 { .name = "wait4", .errpid = true,
Arnaldo Carvalho de Melo7206b902016-04-06 14:11:36 -03001094 .arg_scnprintf = { [2] = SCA_WAITID_OPTIONS, /* options */ }, },
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -03001095 { .name = "waitid", .errpid = true,
Arnaldo Carvalho de Melo7206b902016-04-06 14:11:36 -03001096 .arg_scnprintf = { [3] = SCA_WAITID_OPTIONS, /* options */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001097 { .name = "write", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001098 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001099 { .name = "writev", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001100 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001101};
1102
1103static int syscall_fmt__cmp(const void *name, const void *fmtp)
1104{
1105 const struct syscall_fmt *fmt = fmtp;
1106 return strcmp(name, fmt->name);
1107}
1108
1109static struct syscall_fmt *syscall_fmt__find(const char *name)
1110{
1111 const int nmemb = ARRAY_SIZE(syscall_fmts);
1112 return bsearch(name, syscall_fmts, nmemb, sizeof(struct syscall_fmt), syscall_fmt__cmp);
1113}
1114
1115struct syscall {
1116 struct event_format *tp_format;
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001117 int nr_args;
1118 struct format_field *args;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001119 const char *name;
Arnaldo Carvalho de Melo5089f202014-06-17 14:29:24 -03001120 bool is_exit;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001121 struct syscall_fmt *fmt;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001122 size_t (**arg_scnprintf)(char *bf, size_t size, struct syscall_arg *arg);
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -03001123 void **arg_parm;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001124};
1125
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001126static size_t fprintf_duration(unsigned long t, FILE *fp)
1127{
1128 double duration = (double)t / NSEC_PER_MSEC;
1129 size_t printed = fprintf(fp, "(");
1130
1131 if (duration >= 1.0)
1132 printed += color_fprintf(fp, PERF_COLOR_RED, "%6.3f ms", duration);
1133 else if (duration >= 0.01)
1134 printed += color_fprintf(fp, PERF_COLOR_YELLOW, "%6.3f ms", duration);
1135 else
1136 printed += color_fprintf(fp, PERF_COLOR_NORMAL, "%6.3f ms", duration);
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001137 return printed + fprintf(fp, "): ");
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001138}
1139
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001140/**
1141 * filename.ptr: The filename char pointer that will be vfs_getname'd
1142 * filename.entry_str_pos: Where to insert the string translated from
1143 * filename.ptr by the vfs_getname tracepoint/kprobe.
1144 */
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001145struct thread_trace {
1146 u64 entry_time;
1147 u64 exit_time;
1148 bool entry_pending;
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03001149 unsigned long nr_events;
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04001150 unsigned long pfmaj, pfmin;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001151 char *entry_str;
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001152 double runtime_ms;
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001153 struct {
1154 unsigned long ptr;
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03001155 short int entry_str_pos;
1156 bool pending_open;
1157 unsigned int namelen;
1158 char *name;
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001159 } filename;
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001160 struct {
1161 int max;
1162 char **table;
1163 } paths;
David Ahernbf2575c2013-10-08 21:26:53 -06001164
1165 struct intlist *syscall_stats;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001166};
1167
1168static struct thread_trace *thread_trace__new(void)
1169{
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001170 struct thread_trace *ttrace = zalloc(sizeof(struct thread_trace));
1171
1172 if (ttrace)
1173 ttrace->paths.max = -1;
1174
David Ahernbf2575c2013-10-08 21:26:53 -06001175 ttrace->syscall_stats = intlist__new(NULL);
1176
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001177 return ttrace;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001178}
1179
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001180static struct thread_trace *thread__trace(struct thread *thread, FILE *fp)
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001181{
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03001182 struct thread_trace *ttrace;
1183
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001184 if (thread == NULL)
1185 goto fail;
1186
Namhyung Kim89dceb22014-10-06 09:46:03 +09001187 if (thread__priv(thread) == NULL)
1188 thread__set_priv(thread, thread_trace__new());
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001189
Namhyung Kim89dceb22014-10-06 09:46:03 +09001190 if (thread__priv(thread) == NULL)
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001191 goto fail;
1192
Namhyung Kim89dceb22014-10-06 09:46:03 +09001193 ttrace = thread__priv(thread);
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03001194 ++ttrace->nr_events;
1195
1196 return ttrace;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001197fail:
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001198 color_fprintf(fp, PERF_COLOR_RED,
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001199 "WARNING: not enough memory, dropping samples!\n");
1200 return NULL;
1201}
1202
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04001203#define TRACE_PFMAJ (1 << 0)
1204#define TRACE_PFMIN (1 << 1)
1205
Arnaldo Carvalho de Meloe4d44e82015-08-04 22:17:29 -03001206static const size_t trace__entry_str_size = 2048;
1207
Arnaldo Carvalho de Melo97119f32013-09-27 17:34:10 -03001208static int trace__set_fd_pathname(struct thread *thread, int fd, const char *pathname)
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001209{
Namhyung Kim89dceb22014-10-06 09:46:03 +09001210 struct thread_trace *ttrace = thread__priv(thread);
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001211
1212 if (fd > ttrace->paths.max) {
1213 char **npath = realloc(ttrace->paths.table, (fd + 1) * sizeof(char *));
1214
1215 if (npath == NULL)
1216 return -1;
1217
1218 if (ttrace->paths.max != -1) {
1219 memset(npath + ttrace->paths.max + 1, 0,
1220 (fd - ttrace->paths.max) * sizeof(char *));
1221 } else {
1222 memset(npath, 0, (fd + 1) * sizeof(char *));
1223 }
1224
1225 ttrace->paths.table = npath;
1226 ttrace->paths.max = fd;
1227 }
1228
1229 ttrace->paths.table[fd] = strdup(pathname);
1230
1231 return ttrace->paths.table[fd] != NULL ? 0 : -1;
1232}
1233
Arnaldo Carvalho de Melo97119f32013-09-27 17:34:10 -03001234static int thread__read_fd_path(struct thread *thread, int fd)
1235{
1236 char linkname[PATH_MAX], pathname[PATH_MAX];
1237 struct stat st;
1238 int ret;
1239
1240 if (thread->pid_ == thread->tid) {
1241 scnprintf(linkname, sizeof(linkname),
1242 "/proc/%d/fd/%d", thread->pid_, fd);
1243 } else {
1244 scnprintf(linkname, sizeof(linkname),
1245 "/proc/%d/task/%d/fd/%d", thread->pid_, thread->tid, fd);
1246 }
1247
1248 if (lstat(linkname, &st) < 0 || st.st_size + 1 > (off_t)sizeof(pathname))
1249 return -1;
1250
1251 ret = readlink(linkname, pathname, sizeof(pathname));
1252
1253 if (ret < 0 || ret > st.st_size)
1254 return -1;
1255
1256 pathname[ret] = '\0';
1257 return trace__set_fd_pathname(thread, fd, pathname);
1258}
1259
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001260static const char *thread__fd_path(struct thread *thread, int fd,
1261 struct trace *trace)
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001262{
Namhyung Kim89dceb22014-10-06 09:46:03 +09001263 struct thread_trace *ttrace = thread__priv(thread);
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001264
1265 if (ttrace == NULL)
1266 return NULL;
1267
1268 if (fd < 0)
1269 return NULL;
1270
Arnaldo Carvalho de Melocdcd1e62014-06-10 16:00:18 -03001271 if ((fd > ttrace->paths.max || ttrace->paths.table[fd] == NULL)) {
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001272 if (!trace->live)
1273 return NULL;
1274 ++trace->stats.proc_getname;
Arnaldo Carvalho de Melocdcd1e62014-06-10 16:00:18 -03001275 if (thread__read_fd_path(thread, fd))
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001276 return NULL;
1277 }
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001278
1279 return ttrace->paths.table[fd];
1280}
1281
1282static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
1283 struct syscall_arg *arg)
1284{
1285 int fd = arg->val;
1286 size_t printed = scnprintf(bf, size, "%d", fd);
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001287 const char *path = thread__fd_path(arg->thread, fd, arg->trace);
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001288
1289 if (path)
1290 printed += scnprintf(bf + printed, size - printed, "<%s>", path);
1291
1292 return printed;
1293}
1294
1295static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
1296 struct syscall_arg *arg)
1297{
1298 int fd = arg->val;
1299 size_t printed = syscall_arg__scnprintf_fd(bf, size, arg);
Namhyung Kim89dceb22014-10-06 09:46:03 +09001300 struct thread_trace *ttrace = thread__priv(arg->thread);
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001301
Arnaldo Carvalho de Melo04662522013-12-26 17:41:15 -03001302 if (ttrace && fd >= 0 && fd <= ttrace->paths.max)
1303 zfree(&ttrace->paths.table[fd]);
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001304
1305 return printed;
1306}
1307
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001308static void thread__set_filename_pos(struct thread *thread, const char *bf,
1309 unsigned long ptr)
1310{
1311 struct thread_trace *ttrace = thread__priv(thread);
1312
1313 ttrace->filename.ptr = ptr;
1314 ttrace->filename.entry_str_pos = bf - ttrace->entry_str;
1315}
1316
1317static size_t syscall_arg__scnprintf_filename(char *bf, size_t size,
1318 struct syscall_arg *arg)
1319{
1320 unsigned long ptr = arg->val;
1321
1322 if (!arg->trace->vfs_getname)
1323 return scnprintf(bf, size, "%#x", ptr);
1324
1325 thread__set_filename_pos(arg->thread, bf, ptr);
1326 return 0;
1327}
1328
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001329static bool trace__filter_duration(struct trace *trace, double t)
1330{
1331 return t < (trace->duration_filter * NSEC_PER_MSEC);
1332}
1333
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001334static size_t trace__fprintf_tstamp(struct trace *trace, u64 tstamp, FILE *fp)
1335{
1336 double ts = (double)(tstamp - trace->base_time) / NSEC_PER_MSEC;
1337
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001338 return fprintf(fp, "%10.3f ", ts);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001339}
1340
Namhyung Kimf15eb532012-10-05 14:02:16 +09001341static bool done = false;
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03001342static bool interrupted = false;
Namhyung Kimf15eb532012-10-05 14:02:16 +09001343
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03001344static void sig_handler(int sig)
Namhyung Kimf15eb532012-10-05 14:02:16 +09001345{
1346 done = true;
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03001347 interrupted = sig == SIGINT;
Namhyung Kimf15eb532012-10-05 14:02:16 +09001348}
1349
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001350static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thread,
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001351 u64 duration, u64 tstamp, FILE *fp)
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001352{
1353 size_t printed = trace__fprintf_tstamp(trace, tstamp, fp);
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001354 printed += fprintf_duration(duration, fp);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001355
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -03001356 if (trace->multiple_threads) {
1357 if (trace->show_comm)
Frederic Weisbecker1902efe2013-09-11 16:56:44 +02001358 printed += fprintf(fp, "%.14s/", thread__comm_str(thread));
Adrian Hunter38051232013-07-04 16:20:31 +03001359 printed += fprintf(fp, "%d ", thread->tid);
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -03001360 }
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001361
1362 return printed;
1363}
1364
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001365static int trace__process_event(struct trace *trace, struct machine *machine,
Frederic Weisbecker162f0be2013-09-11 16:18:24 +02001366 union perf_event *event, struct perf_sample *sample)
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001367{
1368 int ret = 0;
1369
1370 switch (event->header.type) {
1371 case PERF_RECORD_LOST:
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001372 color_fprintf(trace->output, PERF_COLOR_RED,
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001373 "LOST %" PRIu64 " events!\n", event->lost.lost);
Frederic Weisbecker162f0be2013-09-11 16:18:24 +02001374 ret = machine__process_lost_event(machine, event, sample);
Arnaldo Carvalho de Melo3ed5ca22016-03-30 16:51:17 -03001375 break;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001376 default:
Frederic Weisbecker162f0be2013-09-11 16:18:24 +02001377 ret = machine__process_event(machine, event, sample);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001378 break;
1379 }
1380
1381 return ret;
1382}
1383
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001384static int trace__tool_process(struct perf_tool *tool,
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001385 union perf_event *event,
Frederic Weisbecker162f0be2013-09-11 16:18:24 +02001386 struct perf_sample *sample,
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001387 struct machine *machine)
1388{
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001389 struct trace *trace = container_of(tool, struct trace, tool);
Frederic Weisbecker162f0be2013-09-11 16:18:24 +02001390 return trace__process_event(trace, machine, event, sample);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001391}
1392
1393static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
1394{
Namhyung Kim0a7e6d12014-08-12 15:40:45 +09001395 int err = symbol__init(NULL);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001396
1397 if (err)
1398 return err;
1399
David Ahern8fb598e2013-09-28 13:13:00 -06001400 trace->host = machine__new_host();
1401 if (trace->host == NULL)
1402 return -ENOMEM;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001403
Arnaldo Carvalho de Melo959c2192015-07-24 12:13:05 -03001404 if (trace_event__register_resolver(trace->host, machine__resolve_kernel_addr) < 0)
Arnaldo Carvalho de Melo706c3da2015-07-22 16:16:16 -03001405 return -errno;
1406
Arnaldo Carvalho de Meloa33fbd52013-11-11 11:36:12 -03001407 err = __machine__synthesize_threads(trace->host, &trace->tool, &trace->opts.target,
Kan Liang9d9cad72015-06-17 09:51:11 -04001408 evlist->threads, trace__tool_process, false,
1409 trace->opts.proc_map_timeout);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001410 if (err)
1411 symbol__exit();
1412
1413 return err;
1414}
1415
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001416static int syscall__set_arg_fmts(struct syscall *sc)
1417{
1418 struct format_field *field;
1419 int idx = 0;
1420
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001421 sc->arg_scnprintf = calloc(sc->nr_args, sizeof(void *));
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001422 if (sc->arg_scnprintf == NULL)
1423 return -1;
1424
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -03001425 if (sc->fmt)
1426 sc->arg_parm = sc->fmt->arg_parm;
1427
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001428 for (field = sc->args; field; field = field->next) {
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -03001429 if (sc->fmt && sc->fmt->arg_scnprintf[idx])
1430 sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx];
1431 else if (field->flags & FIELD_IS_POINTER)
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001432 sc->arg_scnprintf[idx] = syscall_arg__scnprintf_hex;
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -03001433 else if (strcmp(field->type, "pid_t") == 0)
1434 sc->arg_scnprintf[idx] = SCA_PID;
Arnaldo Carvalho de Meloba2f22c2016-04-07 12:05:51 -03001435 else if (strcmp(field->type, "umode_t") == 0)
1436 sc->arg_scnprintf[idx] = SCA_MODE_T;
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001437 ++idx;
1438 }
1439
1440 return 0;
1441}
1442
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001443static int trace__read_syscall_info(struct trace *trace, int id)
1444{
1445 char tp_name[128];
1446 struct syscall *sc;
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03001447 const char *name = syscalltbl__name(trace->sctbl, id);
Arnaldo Carvalho de Melo3a531262012-10-20 12:39:03 -03001448
1449 if (name == NULL)
1450 return -1;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001451
1452 if (id > trace->syscalls.max) {
1453 struct syscall *nsyscalls = realloc(trace->syscalls.table, (id + 1) * sizeof(*sc));
1454
1455 if (nsyscalls == NULL)
1456 return -1;
1457
1458 if (trace->syscalls.max != -1) {
1459 memset(nsyscalls + trace->syscalls.max + 1, 0,
1460 (id - trace->syscalls.max) * sizeof(*sc));
1461 } else {
1462 memset(nsyscalls, 0, (id + 1) * sizeof(*sc));
1463 }
1464
1465 trace->syscalls.table = nsyscalls;
1466 trace->syscalls.max = id;
1467 }
1468
1469 sc = trace->syscalls.table + id;
Arnaldo Carvalho de Melo3a531262012-10-20 12:39:03 -03001470 sc->name = name;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001471
Arnaldo Carvalho de Melo3a531262012-10-20 12:39:03 -03001472 sc->fmt = syscall_fmt__find(sc->name);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001473
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -03001474 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name);
Jiri Olsa97978b32013-12-03 14:09:24 +01001475 sc->tp_format = trace_event__tp_format("syscalls", tp_name);
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -03001476
Jiri Olsa8dd2a132015-09-07 10:38:06 +02001477 if (IS_ERR(sc->tp_format) && sc->fmt && sc->fmt->alias) {
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -03001478 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->fmt->alias);
Jiri Olsa97978b32013-12-03 14:09:24 +01001479 sc->tp_format = trace_event__tp_format("syscalls", tp_name);
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -03001480 }
1481
Jiri Olsa8dd2a132015-09-07 10:38:06 +02001482 if (IS_ERR(sc->tp_format))
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001483 return -1;
1484
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001485 sc->args = sc->tp_format->format.fields;
1486 sc->nr_args = sc->tp_format->format.nr_fields;
Taeung Songc42de702016-02-26 22:14:25 +09001487 /*
1488 * We need to check and discard the first variable '__syscall_nr'
1489 * or 'nr' that mean the syscall number. It is needless here.
1490 * So drop '__syscall_nr' or 'nr' field but does not exist on older kernels.
1491 */
1492 if (sc->args && (!strcmp(sc->args->name, "__syscall_nr") || !strcmp(sc->args->name, "nr"))) {
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001493 sc->args = sc->args->next;
1494 --sc->nr_args;
1495 }
1496
Arnaldo Carvalho de Melo5089f202014-06-17 14:29:24 -03001497 sc->is_exit = !strcmp(name, "exit_group") || !strcmp(name, "exit");
1498
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001499 return syscall__set_arg_fmts(sc);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001500}
1501
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001502static int trace__validate_ev_qualifier(struct trace *trace)
1503{
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001504 int err = 0, i;
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001505 struct str_node *pos;
1506
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001507 trace->ev_qualifier_ids.nr = strlist__nr_entries(trace->ev_qualifier);
1508 trace->ev_qualifier_ids.entries = malloc(trace->ev_qualifier_ids.nr *
1509 sizeof(trace->ev_qualifier_ids.entries[0]));
1510
1511 if (trace->ev_qualifier_ids.entries == NULL) {
1512 fputs("Error:\tNot enough memory for allocating events qualifier ids\n",
1513 trace->output);
1514 err = -EINVAL;
1515 goto out;
1516 }
1517
1518 i = 0;
1519
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001520 strlist__for_each(pos, trace->ev_qualifier) {
1521 const char *sc = pos->s;
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03001522 int id = syscalltbl__id(trace->sctbl, sc);
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001523
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001524 if (id < 0) {
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001525 if (err == 0) {
1526 fputs("Error:\tInvalid syscall ", trace->output);
1527 err = -EINVAL;
1528 } else {
1529 fputs(", ", trace->output);
1530 }
1531
1532 fputs(sc, trace->output);
1533 }
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001534
1535 trace->ev_qualifier_ids.entries[i++] = id;
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001536 }
1537
1538 if (err < 0) {
1539 fputs("\nHint:\ttry 'perf list syscalls:sys_enter_*'"
1540 "\nHint:\tand: 'man syscalls'\n", trace->output);
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001541 zfree(&trace->ev_qualifier_ids.entries);
1542 trace->ev_qualifier_ids.nr = 0;
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001543 }
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001544out:
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001545 return err;
1546}
1547
David Ahern55d43bca2015-02-19 15:00:22 -05001548/*
1549 * args is to be interpreted as a series of longs but we need to handle
1550 * 8-byte unaligned accesses. args points to raw_data within the event
1551 * and raw_data is guaranteed to be 8-byte unaligned because it is
1552 * preceded by raw_size which is a u32. So we need to copy args to a temp
1553 * variable to read it. Most notably this avoids extended load instructions
1554 * on unaligned addresses
1555 */
1556
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001557static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
David Ahern55d43bca2015-02-19 15:00:22 -05001558 unsigned char *args, struct trace *trace,
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001559 struct thread *thread)
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001560{
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001561 size_t printed = 0;
David Ahern55d43bca2015-02-19 15:00:22 -05001562 unsigned char *p;
1563 unsigned long val;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001564
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001565 if (sc->args != NULL) {
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001566 struct format_field *field;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001567 u8 bit = 1;
1568 struct syscall_arg arg = {
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001569 .idx = 0,
1570 .mask = 0,
1571 .trace = trace,
1572 .thread = thread,
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001573 };
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001574
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001575 for (field = sc->args; field;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001576 field = field->next, ++arg.idx, bit <<= 1) {
1577 if (arg.mask & bit)
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -03001578 continue;
David Ahern55d43bca2015-02-19 15:00:22 -05001579
1580 /* special care for unaligned accesses */
1581 p = args + sizeof(unsigned long) * arg.idx;
1582 memcpy(&val, p, sizeof(val));
1583
Arnaldo Carvalho de Melo4aa58232013-09-20 12:19:41 -03001584 /*
1585 * Suppress this argument if its value is zero and
1586 * and we don't have a string associated in an
1587 * strarray for it.
1588 */
David Ahern55d43bca2015-02-19 15:00:22 -05001589 if (val == 0 &&
Arnaldo Carvalho de Melo4aa58232013-09-20 12:19:41 -03001590 !(sc->arg_scnprintf &&
1591 sc->arg_scnprintf[arg.idx] == SCA_STRARRAY &&
1592 sc->arg_parm[arg.idx]))
Arnaldo Carvalho de Melo22ae5cf12013-09-12 11:27:34 -03001593 continue;
1594
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001595 printed += scnprintf(bf + printed, size - printed,
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001596 "%s%s: ", printed ? ", " : "", field->name);
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001597 if (sc->arg_scnprintf && sc->arg_scnprintf[arg.idx]) {
David Ahern55d43bca2015-02-19 15:00:22 -05001598 arg.val = val;
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -03001599 if (sc->arg_parm)
1600 arg.parm = sc->arg_parm[arg.idx];
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001601 printed += sc->arg_scnprintf[arg.idx](bf + printed,
1602 size - printed, &arg);
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -03001603 } else {
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001604 printed += scnprintf(bf + printed, size - printed,
David Ahern55d43bca2015-02-19 15:00:22 -05001605 "%ld", val);
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -03001606 }
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001607 }
1608 } else {
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001609 int i = 0;
1610
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001611 while (i < 6) {
David Ahern55d43bca2015-02-19 15:00:22 -05001612 /* special care for unaligned accesses */
1613 p = args + sizeof(unsigned long) * i;
1614 memcpy(&val, p, sizeof(val));
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001615 printed += scnprintf(bf + printed, size - printed,
1616 "%sarg%d: %ld",
David Ahern55d43bca2015-02-19 15:00:22 -05001617 printed ? ", " : "", i, val);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001618 ++i;
1619 }
1620 }
1621
1622 return printed;
1623}
1624
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001625typedef int (*tracepoint_handler)(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04001626 union perf_event *event,
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001627 struct perf_sample *sample);
1628
1629static struct syscall *trace__syscall_info(struct trace *trace,
David Ahernbf2575c2013-10-08 21:26:53 -06001630 struct perf_evsel *evsel, int id)
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001631{
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001632
1633 if (id < 0) {
Arnaldo Carvalho de Meloadaa18b2013-08-22 17:55:25 -03001634
1635 /*
1636 * XXX: Noticed on x86_64, reproduced as far back as 3.0.36, haven't tried
1637 * before that, leaving at a higher verbosity level till that is
1638 * explained. Reproduced with plain ftrace with:
1639 *
1640 * echo 1 > /t/events/raw_syscalls/sys_exit/enable
1641 * grep "NR -1 " /t/trace_pipe
1642 *
1643 * After generating some load on the machine.
1644 */
1645 if (verbose > 1) {
1646 static u64 n;
1647 fprintf(trace->output, "Invalid syscall %d id, skipping (%s, %" PRIu64 ") ...\n",
1648 id, perf_evsel__name(evsel), ++n);
1649 }
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001650 return NULL;
1651 }
1652
1653 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL) &&
1654 trace__read_syscall_info(trace, id))
1655 goto out_cant_read;
1656
1657 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL))
1658 goto out_cant_read;
1659
1660 return &trace->syscalls.table[id];
1661
1662out_cant_read:
Arnaldo Carvalho de Melo7c304ee02013-08-22 16:49:54 -03001663 if (verbose) {
1664 fprintf(trace->output, "Problems reading syscall %d", id);
1665 if (id <= trace->syscalls.max && trace->syscalls.table[id].name != NULL)
1666 fprintf(trace->output, "(%s)", trace->syscalls.table[id].name);
1667 fputs(" information\n", trace->output);
1668 }
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001669 return NULL;
1670}
1671
David Ahernbf2575c2013-10-08 21:26:53 -06001672static void thread__update_stats(struct thread_trace *ttrace,
1673 int id, struct perf_sample *sample)
1674{
1675 struct int_node *inode;
1676 struct stats *stats;
1677 u64 duration = 0;
1678
1679 inode = intlist__findnew(ttrace->syscall_stats, id);
1680 if (inode == NULL)
1681 return;
1682
1683 stats = inode->priv;
1684 if (stats == NULL) {
1685 stats = malloc(sizeof(struct stats));
1686 if (stats == NULL)
1687 return;
1688 init_stats(stats);
1689 inode->priv = stats;
1690 }
1691
1692 if (ttrace->entry_time && sample->time > ttrace->entry_time)
1693 duration = sample->time - ttrace->entry_time;
1694
1695 update_stats(stats, duration);
1696}
1697
Arnaldo Carvalho de Meloe5966632015-02-13 13:22:21 -03001698static int trace__printf_interrupted_entry(struct trace *trace, struct perf_sample *sample)
1699{
1700 struct thread_trace *ttrace;
1701 u64 duration;
1702 size_t printed;
1703
1704 if (trace->current == NULL)
1705 return 0;
1706
1707 ttrace = thread__priv(trace->current);
1708
1709 if (!ttrace->entry_pending)
1710 return 0;
1711
1712 duration = sample->time - ttrace->entry_time;
1713
1714 printed = trace__fprintf_entry_head(trace, trace->current, duration, sample->time, trace->output);
1715 printed += fprintf(trace->output, "%-70s) ...\n", ttrace->entry_str);
1716 ttrace->entry_pending = false;
1717
1718 return printed;
1719}
1720
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001721static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04001722 union perf_event *event __maybe_unused,
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001723 struct perf_sample *sample)
1724{
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001725 char *msg;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001726 void *args;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001727 size_t printed = 0;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001728 struct thread *thread;
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001729 int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
David Ahernbf2575c2013-10-08 21:26:53 -06001730 struct syscall *sc = trace__syscall_info(trace, evsel, id);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001731 struct thread_trace *ttrace;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001732
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001733 if (sc == NULL)
1734 return -1;
1735
David Ahern8fb598e2013-09-28 13:13:00 -06001736 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001737 ttrace = thread__trace(thread, trace->output);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001738 if (ttrace == NULL)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001739 goto out_put;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001740
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -03001741 args = perf_evsel__sc_tp_ptr(evsel, args, sample);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001742
1743 if (ttrace->entry_str == NULL) {
Arnaldo Carvalho de Meloe4d44e82015-08-04 22:17:29 -03001744 ttrace->entry_str = malloc(trace__entry_str_size);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001745 if (!ttrace->entry_str)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001746 goto out_put;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001747 }
1748
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -03001749 if (!(trace->duration_filter || trace->summary_only || trace->min_stack))
Arnaldo Carvalho de Melo6ebad5c2015-03-25 18:01:15 -03001750 trace__printf_interrupted_entry(trace, sample);
Arnaldo Carvalho de Meloe5966632015-02-13 13:22:21 -03001751
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001752 ttrace->entry_time = sample->time;
1753 msg = ttrace->entry_str;
Arnaldo Carvalho de Meloe4d44e82015-08-04 22:17:29 -03001754 printed += scnprintf(msg + printed, trace__entry_str_size - printed, "%s(", sc->name);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001755
Arnaldo Carvalho de Meloe4d44e82015-08-04 22:17:29 -03001756 printed += syscall__scnprintf_args(sc, msg + printed, trace__entry_str_size - printed,
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001757 args, trace, thread);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001758
Arnaldo Carvalho de Melo5089f202014-06-17 14:29:24 -03001759 if (sc->is_exit) {
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -03001760 if (!(trace->duration_filter || trace->summary_only || trace->min_stack)) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001761 trace__fprintf_entry_head(trace, thread, 1, sample->time, trace->output);
1762 fprintf(trace->output, "%-70s\n", ttrace->entry_str);
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001763 }
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03001764 } else {
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001765 ttrace->entry_pending = true;
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03001766 /* See trace__vfs_getname & trace__sys_exit */
1767 ttrace->filename.pending_open = false;
1768 }
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001769
Arnaldo Carvalho de Melof3b623b2015-03-02 22:21:35 -03001770 if (trace->current != thread) {
1771 thread__put(trace->current);
1772 trace->current = thread__get(thread);
1773 }
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001774 err = 0;
1775out_put:
1776 thread__put(thread);
1777 return err;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001778}
1779
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -03001780static int trace__resolve_callchain(struct trace *trace, struct perf_evsel *evsel,
1781 struct perf_sample *sample,
1782 struct callchain_cursor *cursor)
Arnaldo Carvalho de Melo202ff962016-04-12 10:11:07 -03001783{
1784 struct addr_location al;
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -03001785
1786 if (machine__resolve(trace->host, &al, sample) < 0 ||
1787 thread__resolve_callchain(al.thread, cursor, evsel, sample, NULL, NULL, trace->max_stack))
1788 return -1;
1789
1790 return 0;
1791}
1792
1793static int trace__fprintf_callchain(struct trace *trace, struct perf_sample *sample)
1794{
Arnaldo Carvalho de Melo202ff962016-04-12 10:11:07 -03001795 /* TODO: user-configurable print_opts */
Arnaldo Carvalho de Meloe20ab862016-04-12 15:16:15 -03001796 const unsigned int print_opts = EVSEL__PRINT_SYM |
1797 EVSEL__PRINT_DSO |
1798 EVSEL__PRINT_UNKNOWN_AS_ADDR;
Arnaldo Carvalho de Melo202ff962016-04-12 10:11:07 -03001799
Arnaldo Carvalho de Melod327e602016-04-14 17:53:49 -03001800 return sample__fprintf_callchain(sample, 38, print_opts, &callchain_cursor, trace->output);
Arnaldo Carvalho de Melo202ff962016-04-12 10:11:07 -03001801}
1802
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001803static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04001804 union perf_event *event __maybe_unused,
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001805 struct perf_sample *sample)
1806{
Chang Hyun Park2c82c3a2014-09-26 21:54:01 +09001807 long ret;
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001808 u64 duration = 0;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001809 struct thread *thread;
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -03001810 int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1, callchain_ret = 0;
David Ahernbf2575c2013-10-08 21:26:53 -06001811 struct syscall *sc = trace__syscall_info(trace, evsel, id);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001812 struct thread_trace *ttrace;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001813
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001814 if (sc == NULL)
1815 return -1;
1816
David Ahern8fb598e2013-09-28 13:13:00 -06001817 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001818 ttrace = thread__trace(thread, trace->output);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001819 if (ttrace == NULL)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001820 goto out_put;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001821
David Ahernbf2575c2013-10-08 21:26:53 -06001822 if (trace->summary)
1823 thread__update_stats(ttrace, id, sample);
1824
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -03001825 ret = perf_evsel__sc_tp_uint(evsel, ret, sample);
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001826
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03001827 if (id == trace->open_id && ret >= 0 && ttrace->filename.pending_open) {
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03001828 trace__set_fd_pathname(thread, ret, ttrace->filename.name);
1829 ttrace->filename.pending_open = false;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001830 ++trace->stats.vfs_getname;
1831 }
1832
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001833 ttrace->exit_time = sample->time;
1834
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001835 if (ttrace->entry_time) {
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001836 duration = sample->time - ttrace->entry_time;
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001837 if (trace__filter_duration(trace, duration))
1838 goto out;
1839 } else if (trace->duration_filter)
1840 goto out;
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001841
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -03001842 if (sample->callchain) {
1843 callchain_ret = trace__resolve_callchain(trace, evsel, sample, &callchain_cursor);
1844 if (callchain_ret == 0) {
1845 if (callchain_cursor.nr < trace->min_stack)
1846 goto out;
1847 callchain_ret = 1;
1848 }
1849 }
1850
David Ahernfd2eaba2013-11-12 09:31:15 -07001851 if (trace->summary_only)
1852 goto out;
1853
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001854 trace__fprintf_entry_head(trace, thread, duration, sample->time, trace->output);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001855
1856 if (ttrace->entry_pending) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001857 fprintf(trace->output, "%-70s", ttrace->entry_str);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001858 } else {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001859 fprintf(trace->output, " ... [");
1860 color_fprintf(trace->output, PERF_COLOR_YELLOW, "continued");
1861 fprintf(trace->output, "]: %s()", sc->name);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001862 }
1863
Arnaldo Carvalho de Meloda3c9a42013-08-26 11:28:34 -03001864 if (sc->fmt == NULL) {
1865signed_print:
Chang Hyun Park2c82c3a2014-09-26 21:54:01 +09001866 fprintf(trace->output, ") = %ld", ret);
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -03001867 } else if (ret < 0 && (sc->fmt->errmsg || sc->fmt->errpid)) {
Masami Hiramatsu942a91e2014-08-14 02:22:41 +00001868 char bf[STRERR_BUFSIZE];
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001869 const char *emsg = strerror_r(-ret, bf, sizeof(bf)),
1870 *e = audit_errno_to_name(-ret);
1871
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001872 fprintf(trace->output, ") = -1 %s %s", e, emsg);
Arnaldo Carvalho de Meloda3c9a42013-08-26 11:28:34 -03001873 } else if (ret == 0 && sc->fmt->timeout)
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001874 fprintf(trace->output, ") = 0 Timeout");
Arnaldo Carvalho de Melo04b34722013-08-26 11:36:30 -03001875 else if (sc->fmt->hexret)
Chang Hyun Park2c82c3a2014-09-26 21:54:01 +09001876 fprintf(trace->output, ") = %#lx", ret);
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -03001877 else if (sc->fmt->errpid) {
1878 struct thread *child = machine__find_thread(trace->host, ret, ret);
1879
1880 if (child != NULL) {
1881 fprintf(trace->output, ") = %ld", ret);
1882 if (child->comm_set)
1883 fprintf(trace->output, " (%s)", thread__comm_str(child));
1884 thread__put(child);
1885 }
1886 } else
Arnaldo Carvalho de Meloda3c9a42013-08-26 11:28:34 -03001887 goto signed_print;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001888
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001889 fputc('\n', trace->output);
Milian Wolff566a0882016-04-08 13:34:15 +02001890
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -03001891 if (callchain_ret > 0)
1892 trace__fprintf_callchain(trace, sample);
1893 else if (callchain_ret < 0)
1894 pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel));
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001895out:
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001896 ttrace->entry_pending = false;
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001897 err = 0;
1898out_put:
1899 thread__put(thread);
1900 return err;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001901}
1902
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001903static int trace__vfs_getname(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04001904 union perf_event *event __maybe_unused,
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001905 struct perf_sample *sample)
1906{
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001907 struct thread *thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
1908 struct thread_trace *ttrace;
1909 size_t filename_len, entry_str_len, to_move;
1910 ssize_t remaining_space;
1911 char *pos;
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03001912 const char *filename = perf_evsel__rawptr(evsel, sample, "pathname");
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001913
1914 if (!thread)
1915 goto out;
1916
1917 ttrace = thread__priv(thread);
1918 if (!ttrace)
1919 goto out;
1920
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03001921 filename_len = strlen(filename);
1922
1923 if (ttrace->filename.namelen < filename_len) {
1924 char *f = realloc(ttrace->filename.name, filename_len + 1);
1925
1926 if (f == NULL)
1927 goto out;
1928
1929 ttrace->filename.namelen = filename_len;
1930 ttrace->filename.name = f;
1931 }
1932
1933 strcpy(ttrace->filename.name, filename);
1934 ttrace->filename.pending_open = true;
1935
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001936 if (!ttrace->filename.ptr)
1937 goto out;
1938
1939 entry_str_len = strlen(ttrace->entry_str);
1940 remaining_space = trace__entry_str_size - entry_str_len - 1; /* \0 */
1941 if (remaining_space <= 0)
1942 goto out;
1943
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001944 if (filename_len > (size_t)remaining_space) {
1945 filename += filename_len - remaining_space;
1946 filename_len = remaining_space;
1947 }
1948
1949 to_move = entry_str_len - ttrace->filename.entry_str_pos + 1; /* \0 */
1950 pos = ttrace->entry_str + ttrace->filename.entry_str_pos;
1951 memmove(pos + filename_len, pos, to_move);
1952 memcpy(pos, filename, filename_len);
1953
1954 ttrace->filename.ptr = 0;
1955 ttrace->filename.entry_str_pos = 0;
1956out:
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001957 return 0;
1958}
1959
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001960static int trace__sched_stat_runtime(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04001961 union perf_event *event __maybe_unused,
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001962 struct perf_sample *sample)
1963{
1964 u64 runtime = perf_evsel__intval(evsel, sample, "runtime");
1965 double runtime_ms = (double)runtime / NSEC_PER_MSEC;
David Ahern8fb598e2013-09-28 13:13:00 -06001966 struct thread *thread = machine__findnew_thread(trace->host,
Adrian Hunter314add62013-08-27 11:23:03 +03001967 sample->pid,
1968 sample->tid);
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001969 struct thread_trace *ttrace = thread__trace(thread, trace->output);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001970
1971 if (ttrace == NULL)
1972 goto out_dump;
1973
1974 ttrace->runtime_ms += runtime_ms;
1975 trace->runtime_ms += runtime_ms;
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001976 thread__put(thread);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001977 return 0;
1978
1979out_dump:
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001980 fprintf(trace->output, "%s: comm=%s,pid=%u,runtime=%" PRIu64 ",vruntime=%" PRIu64 ")\n",
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001981 evsel->name,
1982 perf_evsel__strval(evsel, sample, "comm"),
1983 (pid_t)perf_evsel__intval(evsel, sample, "pid"),
1984 runtime,
1985 perf_evsel__intval(evsel, sample, "vruntime"));
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001986 thread__put(thread);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001987 return 0;
1988}
1989
Wang Nan1d6c9402016-02-26 09:31:55 +00001990static void bpf_output__printer(enum binary_printer_ops op,
1991 unsigned int val, void *extra)
1992{
1993 FILE *output = extra;
1994 unsigned char ch = (unsigned char)val;
1995
1996 switch (op) {
1997 case BINARY_PRINT_CHAR_DATA:
1998 fprintf(output, "%c", isprint(ch) ? ch : '.');
1999 break;
2000 case BINARY_PRINT_DATA_BEGIN:
2001 case BINARY_PRINT_LINE_BEGIN:
2002 case BINARY_PRINT_ADDR:
2003 case BINARY_PRINT_NUM_DATA:
2004 case BINARY_PRINT_NUM_PAD:
2005 case BINARY_PRINT_SEP:
2006 case BINARY_PRINT_CHAR_PAD:
2007 case BINARY_PRINT_LINE_END:
2008 case BINARY_PRINT_DATA_END:
2009 default:
2010 break;
2011 }
2012}
2013
2014static void bpf_output__fprintf(struct trace *trace,
2015 struct perf_sample *sample)
2016{
2017 print_binary(sample->raw_data, sample->raw_size, 8,
2018 bpf_output__printer, trace->output);
2019}
2020
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002021static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
2022 union perf_event *event __maybe_unused,
2023 struct perf_sample *sample)
2024{
Arnaldo Carvalho de Melo7ad35612016-04-20 19:55:48 -03002025 int callchain_ret = 0;
2026
2027 if (sample->callchain) {
2028 callchain_ret = trace__resolve_callchain(trace, evsel, sample, &callchain_cursor);
2029 if (callchain_ret == 0) {
2030 if (callchain_cursor.nr < trace->min_stack)
2031 goto out;
2032 callchain_ret = 1;
2033 }
2034 }
2035
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002036 trace__printf_interrupted_entry(trace, sample);
2037 trace__fprintf_tstamp(trace, sample->time, trace->output);
Arnaldo Carvalho de Melo08089212015-02-19 21:51:50 -08002038
2039 if (trace->trace_syscalls)
2040 fprintf(trace->output, "( ): ");
2041
2042 fprintf(trace->output, "%s:", evsel->name);
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002043
Wang Nan1d6c9402016-02-26 09:31:55 +00002044 if (perf_evsel__is_bpf_output(evsel)) {
2045 bpf_output__fprintf(trace, sample);
2046 } else if (evsel->tp_format) {
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002047 event_format__fprintf(evsel->tp_format, sample->cpu,
2048 sample->raw_data, sample->raw_size,
2049 trace->output);
2050 }
2051
2052 fprintf(trace->output, ")\n");
Arnaldo Carvalho de Melo202ff962016-04-12 10:11:07 -03002053
Arnaldo Carvalho de Melo7ad35612016-04-20 19:55:48 -03002054 if (callchain_ret > 0)
2055 trace__fprintf_callchain(trace, sample);
2056 else if (callchain_ret < 0)
2057 pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel));
2058out:
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002059 return 0;
2060}
2061
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002062static void print_location(FILE *f, struct perf_sample *sample,
2063 struct addr_location *al,
2064 bool print_dso, bool print_sym)
2065{
2066
2067 if ((verbose || print_dso) && al->map)
2068 fprintf(f, "%s@", al->map->dso->long_name);
2069
2070 if ((verbose || print_sym) && al->sym)
Arnaldo Carvalho de Melo4414a3c2014-07-08 15:39:21 -03002071 fprintf(f, "%s+0x%" PRIx64, al->sym->name,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002072 al->addr - al->sym->start);
2073 else if (al->map)
Arnaldo Carvalho de Melo4414a3c2014-07-08 15:39:21 -03002074 fprintf(f, "0x%" PRIx64, al->addr);
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002075 else
Arnaldo Carvalho de Melo4414a3c2014-07-08 15:39:21 -03002076 fprintf(f, "0x%" PRIx64, sample->addr);
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002077}
2078
2079static int trace__pgfault(struct trace *trace,
2080 struct perf_evsel *evsel,
Arnaldo Carvalho de Melo473398a2016-03-22 18:23:43 -03002081 union perf_event *event __maybe_unused,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002082 struct perf_sample *sample)
2083{
2084 struct thread *thread;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002085 struct addr_location al;
2086 char map_type = 'd';
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04002087 struct thread_trace *ttrace;
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002088 int err = -1;
Arnaldo Carvalho de Melo1df54292016-04-20 20:06:02 -03002089 int callchain_ret = 0;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002090
2091 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
Arnaldo Carvalho de Melo1df54292016-04-20 20:06:02 -03002092
2093 if (sample->callchain) {
2094 callchain_ret = trace__resolve_callchain(trace, evsel, sample, &callchain_cursor);
2095 if (callchain_ret == 0) {
2096 if (callchain_cursor.nr < trace->min_stack)
2097 goto out_put;
2098 callchain_ret = 1;
2099 }
2100 }
2101
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04002102 ttrace = thread__trace(thread, trace->output);
2103 if (ttrace == NULL)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002104 goto out_put;
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04002105
2106 if (evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ)
2107 ttrace->pfmaj++;
2108 else
2109 ttrace->pfmin++;
2110
2111 if (trace->summary_only)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002112 goto out;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002113
Arnaldo Carvalho de Melo473398a2016-03-22 18:23:43 -03002114 thread__find_addr_location(thread, sample->cpumode, MAP__FUNCTION,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002115 sample->ip, &al);
2116
2117 trace__fprintf_entry_head(trace, thread, 0, sample->time, trace->output);
2118
2119 fprintf(trace->output, "%sfault [",
2120 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ?
2121 "maj" : "min");
2122
2123 print_location(trace->output, sample, &al, false, true);
2124
2125 fprintf(trace->output, "] => ");
2126
Arnaldo Carvalho de Melo473398a2016-03-22 18:23:43 -03002127 thread__find_addr_location(thread, sample->cpumode, MAP__VARIABLE,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002128 sample->addr, &al);
2129
2130 if (!al.map) {
Arnaldo Carvalho de Melo473398a2016-03-22 18:23:43 -03002131 thread__find_addr_location(thread, sample->cpumode,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002132 MAP__FUNCTION, sample->addr, &al);
2133
2134 if (al.map)
2135 map_type = 'x';
2136 else
2137 map_type = '?';
2138 }
2139
2140 print_location(trace->output, sample, &al, true, false);
2141
2142 fprintf(trace->output, " (%c%c)\n", map_type, al.level);
Arnaldo Carvalho de Melo0c3a6ef2016-04-19 16:31:12 -03002143
Arnaldo Carvalho de Melo1df54292016-04-20 20:06:02 -03002144 if (callchain_ret > 0)
2145 trace__fprintf_callchain(trace, sample);
2146 else if (callchain_ret < 0)
2147 pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel));
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002148out:
2149 err = 0;
2150out_put:
2151 thread__put(thread);
2152 return err;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002153}
2154
David Ahernbdc89662013-08-28 22:29:53 -06002155static bool skip_sample(struct trace *trace, struct perf_sample *sample)
2156{
2157 if ((trace->pid_list && intlist__find(trace->pid_list, sample->pid)) ||
2158 (trace->tid_list && intlist__find(trace->tid_list, sample->tid)))
2159 return false;
2160
2161 if (trace->pid_list || trace->tid_list)
2162 return true;
2163
2164 return false;
2165}
2166
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03002167static void trace__set_base_time(struct trace *trace,
Arnaldo Carvalho de Melo8a07a802016-03-31 15:19:39 -03002168 struct perf_evsel *evsel,
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03002169 struct perf_sample *sample)
2170{
Arnaldo Carvalho de Melo8a07a802016-03-31 15:19:39 -03002171 /*
2172 * BPF events were not setting PERF_SAMPLE_TIME, so be more robust
2173 * and don't use sample->time unconditionally, we may end up having
2174 * some other event in the future without PERF_SAMPLE_TIME for good
2175 * reason, i.e. we may not be interested in its timestamps, just in
2176 * it taking place, picking some piece of information when it
2177 * appears in our event stream (vfs_getname comes to mind).
2178 */
2179 if (trace->base_time == 0 && !trace->full_time &&
2180 (evsel->attr.sample_type & PERF_SAMPLE_TIME))
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03002181 trace->base_time = sample->time;
2182}
2183
David Ahern6810fc92013-08-28 22:29:52 -06002184static int trace__process_sample(struct perf_tool *tool,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04002185 union perf_event *event,
David Ahern6810fc92013-08-28 22:29:52 -06002186 struct perf_sample *sample,
2187 struct perf_evsel *evsel,
2188 struct machine *machine __maybe_unused)
2189{
2190 struct trace *trace = container_of(tool, struct trace, tool);
2191 int err = 0;
2192
Arnaldo Carvalho de Melo744a9712013-11-06 10:17:38 -03002193 tracepoint_handler handler = evsel->handler;
David Ahern6810fc92013-08-28 22:29:52 -06002194
David Ahernbdc89662013-08-28 22:29:53 -06002195 if (skip_sample(trace, sample))
2196 return 0;
2197
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03002198 trace__set_base_time(trace, evsel, sample);
David Ahern6810fc92013-08-28 22:29:52 -06002199
David Ahern31605652013-12-04 19:41:41 -07002200 if (handler) {
2201 ++trace->nr_events;
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04002202 handler(trace, evsel, event, sample);
David Ahern31605652013-12-04 19:41:41 -07002203 }
David Ahern6810fc92013-08-28 22:29:52 -06002204
2205 return err;
2206}
2207
David Ahernbdc89662013-08-28 22:29:53 -06002208static int parse_target_str(struct trace *trace)
2209{
2210 if (trace->opts.target.pid) {
2211 trace->pid_list = intlist__new(trace->opts.target.pid);
2212 if (trace->pid_list == NULL) {
2213 pr_err("Error parsing process id string\n");
2214 return -EINVAL;
2215 }
2216 }
2217
2218 if (trace->opts.target.tid) {
2219 trace->tid_list = intlist__new(trace->opts.target.tid);
2220 if (trace->tid_list == NULL) {
2221 pr_err("Error parsing thread id string\n");
2222 return -EINVAL;
2223 }
2224 }
2225
2226 return 0;
2227}
2228
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002229static int trace__record(struct trace *trace, int argc, const char **argv)
David Ahern5e2485b2013-09-28 13:13:01 -06002230{
2231 unsigned int rec_argc, i, j;
2232 const char **rec_argv;
2233 const char * const record_args[] = {
2234 "record",
2235 "-R",
2236 "-m", "1024",
2237 "-c", "1",
David Ahern5e2485b2013-09-28 13:13:01 -06002238 };
2239
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002240 const char * const sc_args[] = { "-e", };
2241 unsigned int sc_args_nr = ARRAY_SIZE(sc_args);
2242 const char * const majpf_args[] = { "-e", "major-faults" };
2243 unsigned int majpf_args_nr = ARRAY_SIZE(majpf_args);
2244 const char * const minpf_args[] = { "-e", "minor-faults" };
2245 unsigned int minpf_args_nr = ARRAY_SIZE(minpf_args);
2246
David Ahern9aca7f12013-12-04 19:41:39 -07002247 /* +1 is for the event string below */
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002248 rec_argc = ARRAY_SIZE(record_args) + sc_args_nr + 1 +
2249 majpf_args_nr + minpf_args_nr + argc;
David Ahern5e2485b2013-09-28 13:13:01 -06002250 rec_argv = calloc(rec_argc + 1, sizeof(char *));
2251
2252 if (rec_argv == NULL)
2253 return -ENOMEM;
2254
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002255 j = 0;
David Ahern5e2485b2013-09-28 13:13:01 -06002256 for (i = 0; i < ARRAY_SIZE(record_args); i++)
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002257 rec_argv[j++] = record_args[i];
2258
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002259 if (trace->trace_syscalls) {
2260 for (i = 0; i < sc_args_nr; i++)
2261 rec_argv[j++] = sc_args[i];
David Ahern5e2485b2013-09-28 13:13:01 -06002262
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002263 /* event string may be different for older kernels - e.g., RHEL6 */
2264 if (is_valid_tracepoint("raw_syscalls:sys_enter"))
2265 rec_argv[j++] = "raw_syscalls:sys_enter,raw_syscalls:sys_exit";
2266 else if (is_valid_tracepoint("syscalls:sys_enter"))
2267 rec_argv[j++] = "syscalls:sys_enter,syscalls:sys_exit";
2268 else {
2269 pr_err("Neither raw_syscalls nor syscalls events exist.\n");
2270 return -1;
2271 }
David Ahern9aca7f12013-12-04 19:41:39 -07002272 }
David Ahern9aca7f12013-12-04 19:41:39 -07002273
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002274 if (trace->trace_pgfaults & TRACE_PFMAJ)
2275 for (i = 0; i < majpf_args_nr; i++)
2276 rec_argv[j++] = majpf_args[i];
David Ahern5e2485b2013-09-28 13:13:01 -06002277
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002278 if (trace->trace_pgfaults & TRACE_PFMIN)
2279 for (i = 0; i < minpf_args_nr; i++)
2280 rec_argv[j++] = minpf_args[i];
2281
2282 for (i = 0; i < (unsigned int)argc; i++)
2283 rec_argv[j++] = argv[i];
2284
2285 return cmd_record(j, rec_argv, NULL);
David Ahern5e2485b2013-09-28 13:13:01 -06002286}
2287
David Ahernbf2575c2013-10-08 21:26:53 -06002288static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp);
2289
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002290static bool perf_evlist__add_vfs_getname(struct perf_evlist *evlist)
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002291{
Arnaldo Carvalho de Meloef503832013-11-07 16:41:19 -03002292 struct perf_evsel *evsel = perf_evsel__newtp("probe", "vfs_getname");
Jiri Olsa8dd2a132015-09-07 10:38:06 +02002293
2294 if (IS_ERR(evsel))
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002295 return false;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002296
2297 if (perf_evsel__field(evsel, "pathname") == NULL) {
2298 perf_evsel__delete(evsel);
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002299 return false;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002300 }
2301
Arnaldo Carvalho de Melo744a9712013-11-06 10:17:38 -03002302 evsel->handler = trace__vfs_getname;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002303 perf_evlist__add(evlist, evsel);
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002304 return true;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002305}
2306
Arnaldo Carvalho de Melo0ae537c2016-04-19 16:00:01 -03002307static struct perf_evsel *perf_evsel__new_pgfault(u64 config)
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002308{
2309 struct perf_evsel *evsel;
2310 struct perf_event_attr attr = {
2311 .type = PERF_TYPE_SOFTWARE,
2312 .mmap_data = 1,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002313 };
2314
2315 attr.config = config;
Arnaldo Carvalho de Melo05247982014-07-23 18:15:09 -03002316 attr.sample_period = 1;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002317
2318 event_attr_init(&attr);
2319
2320 evsel = perf_evsel__new(&attr);
Arnaldo Carvalho de Melo0ae537c2016-04-19 16:00:01 -03002321 if (evsel)
2322 evsel->handler = trace__pgfault;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002323
Arnaldo Carvalho de Melo0ae537c2016-04-19 16:00:01 -03002324 return evsel;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002325}
2326
Arnaldo Carvalho de Meloddbb1b12015-02-21 12:10:29 -08002327static void trace__handle_event(struct trace *trace, union perf_event *event, struct perf_sample *sample)
2328{
2329 const u32 type = event->header.type;
2330 struct perf_evsel *evsel;
2331
Arnaldo Carvalho de Meloddbb1b12015-02-21 12:10:29 -08002332 if (type != PERF_RECORD_SAMPLE) {
2333 trace__process_event(trace, trace->host, event, sample);
2334 return;
2335 }
2336
2337 evsel = perf_evlist__id2evsel(trace->evlist, sample->id);
2338 if (evsel == NULL) {
2339 fprintf(trace->output, "Unknown tp ID %" PRIu64 ", skipping...\n", sample->id);
2340 return;
2341 }
2342
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03002343 trace__set_base_time(trace, evsel, sample);
2344
Arnaldo Carvalho de Meloddbb1b12015-02-21 12:10:29 -08002345 if (evsel->attr.type == PERF_TYPE_TRACEPOINT &&
2346 sample->raw_data == NULL) {
2347 fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n",
2348 perf_evsel__name(evsel), sample->tid,
2349 sample->cpu, sample->raw_size);
2350 } else {
2351 tracepoint_handler handler = evsel->handler;
2352 handler(trace, evsel, event, sample);
2353 }
2354}
2355
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03002356static int trace__add_syscall_newtp(struct trace *trace)
2357{
2358 int ret = -1;
2359 struct perf_evlist *evlist = trace->evlist;
2360 struct perf_evsel *sys_enter, *sys_exit;
2361
2362 sys_enter = perf_evsel__syscall_newtp("sys_enter", trace__sys_enter);
2363 if (sys_enter == NULL)
2364 goto out;
2365
2366 if (perf_evsel__init_sc_tp_ptr_field(sys_enter, args))
2367 goto out_delete_sys_enter;
2368
2369 sys_exit = perf_evsel__syscall_newtp("sys_exit", trace__sys_exit);
2370 if (sys_exit == NULL)
2371 goto out_delete_sys_enter;
2372
2373 if (perf_evsel__init_sc_tp_uint_field(sys_exit, ret))
2374 goto out_delete_sys_exit;
2375
2376 perf_evlist__add(evlist, sys_enter);
2377 perf_evlist__add(evlist, sys_exit);
2378
Arnaldo Carvalho de Melo2ddd5c02016-04-18 12:09:08 -03002379 if (callchain_param.enabled && !trace->kernel_syscallchains) {
Arnaldo Carvalho de Melo44621812016-04-11 15:49:11 -03002380 /*
2381 * We're interested only in the user space callchain
2382 * leading to the syscall, allow overriding that for
2383 * debugging reasons using --kernel_syscall_callchains
2384 */
2385 sys_exit->attr.exclude_callchain_kernel = 1;
2386 }
2387
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03002388 trace->syscalls.events.sys_enter = sys_enter;
2389 trace->syscalls.events.sys_exit = sys_exit;
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03002390
2391 ret = 0;
2392out:
2393 return ret;
2394
2395out_delete_sys_exit:
2396 perf_evsel__delete_priv(sys_exit);
2397out_delete_sys_enter:
2398 perf_evsel__delete_priv(sys_enter);
2399 goto out;
2400}
2401
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002402static int trace__set_ev_qualifier_filter(struct trace *trace)
2403{
2404 int err = -1;
2405 char *filter = asprintf_expr_inout_ints("id", !trace->not_ev_qualifier,
2406 trace->ev_qualifier_ids.nr,
2407 trace->ev_qualifier_ids.entries);
2408
2409 if (filter == NULL)
2410 goto out_enomem;
2411
2412 if (!perf_evsel__append_filter(trace->syscalls.events.sys_enter, "&&", filter))
2413 err = perf_evsel__append_filter(trace->syscalls.events.sys_exit, "&&", filter);
2414
2415 free(filter);
2416out:
2417 return err;
2418out_enomem:
2419 errno = ENOMEM;
2420 goto out;
2421}
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03002422
Namhyung Kimf15eb532012-10-05 14:02:16 +09002423static int trace__run(struct trace *trace, int argc, const char **argv)
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002424{
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002425 struct perf_evlist *evlist = trace->evlist;
Arnaldo Carvalho de Melo0ae537c2016-04-19 16:00:01 -03002426 struct perf_evsel *evsel, *pgfault_maj = NULL, *pgfault_min = NULL;
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03002427 int err = -1, i;
2428 unsigned long before;
Namhyung Kimf15eb532012-10-05 14:02:16 +09002429 const bool forks = argc > 0;
Arnaldo Carvalho de Melo46fb3c22014-09-22 14:39:48 -03002430 bool draining = false;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002431
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03002432 trace->live = true;
2433
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03002434 if (trace->trace_syscalls && trace__add_syscall_newtp(trace))
Arnaldo Carvalho de Melo801c67b2015-01-22 10:52:55 -03002435 goto out_error_raw_syscalls;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002436
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002437 if (trace->trace_syscalls)
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002438 trace->vfs_getname = perf_evlist__add_vfs_getname(evlist);
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002439
Arnaldo Carvalho de Melo0ae537c2016-04-19 16:00:01 -03002440 if ((trace->trace_pgfaults & TRACE_PFMAJ)) {
2441 pgfault_maj = perf_evsel__new_pgfault(PERF_COUNT_SW_PAGE_FAULTS_MAJ);
2442 if (pgfault_maj == NULL)
2443 goto out_error_mem;
2444 perf_evlist__add(evlist, pgfault_maj);
Arnaldo Carvalho de Meloe2726d92015-01-22 10:34:22 -03002445 }
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002446
Arnaldo Carvalho de Melo0ae537c2016-04-19 16:00:01 -03002447 if ((trace->trace_pgfaults & TRACE_PFMIN)) {
2448 pgfault_min = perf_evsel__new_pgfault(PERF_COUNT_SW_PAGE_FAULTS_MIN);
2449 if (pgfault_min == NULL)
2450 goto out_error_mem;
2451 perf_evlist__add(evlist, pgfault_min);
2452 }
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002453
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002454 if (trace->sched &&
Arnaldo Carvalho de Melo2cc990b2015-01-22 11:13:43 -03002455 perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime",
2456 trace__sched_stat_runtime))
2457 goto out_error_sched_stat_runtime;
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002458
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002459 err = perf_evlist__create_maps(evlist, &trace->opts.target);
2460 if (err < 0) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002461 fprintf(trace->output, "Problems parsing the target to trace, check your options!\n");
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002462 goto out_delete_evlist;
2463 }
2464
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03002465 err = trace__symbols_init(trace, evlist);
2466 if (err < 0) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002467 fprintf(trace->output, "Problems initializing symbol libraries!\n");
Arnaldo Carvalho de Melo03ad9742014-01-03 15:56:06 -03002468 goto out_delete_evlist;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03002469 }
2470
Arnaldo Carvalho de Melofde54b72016-04-11 18:42:37 -03002471 perf_evlist__config(evlist, &trace->opts, NULL);
2472
Arnaldo Carvalho de Melo0c3a6ef2016-04-19 16:31:12 -03002473 if (callchain_param.enabled) {
2474 bool use_identifier = false;
2475
2476 if (trace->syscalls.events.sys_exit) {
2477 perf_evsel__config_callchain(trace->syscalls.events.sys_exit,
2478 &trace->opts, &callchain_param);
2479 use_identifier = true;
2480 }
2481
2482 if (pgfault_maj) {
2483 perf_evsel__config_callchain(pgfault_maj, &trace->opts, &callchain_param);
2484 use_identifier = true;
2485 }
2486
2487 if (pgfault_min) {
2488 perf_evsel__config_callchain(pgfault_min, &trace->opts, &callchain_param);
2489 use_identifier = true;
2490 }
2491
2492 if (use_identifier) {
2493 /*
2494 * Now we have evsels with different sample_ids, use
2495 * PERF_SAMPLE_IDENTIFIER to map from sample to evsel
2496 * from a fixed position in each ring buffer record.
2497 *
2498 * As of this the changeset introducing this comment, this
2499 * isn't strictly needed, as the fields that can come before
2500 * PERF_SAMPLE_ID are all used, but we'll probably disable
2501 * some of those for things like copying the payload of
2502 * pointer syscall arguments, and for vfs_getname we don't
2503 * need PERF_SAMPLE_ADDR and PERF_SAMPLE_IP, so do this
2504 * here as a warning we need to use PERF_SAMPLE_IDENTIFIER.
2505 */
2506 perf_evlist__set_sample_bit(evlist, IDENTIFIER);
2507 perf_evlist__reset_sample_bit(evlist, ID);
2508 }
Arnaldo Carvalho de Melofde54b72016-04-11 18:42:37 -03002509 }
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002510
Namhyung Kimf15eb532012-10-05 14:02:16 +09002511 signal(SIGCHLD, sig_handler);
2512 signal(SIGINT, sig_handler);
2513
2514 if (forks) {
Namhyung Kim6ef73ec2013-03-11 16:43:15 +09002515 err = perf_evlist__prepare_workload(evlist, &trace->opts.target,
Arnaldo Carvalho de Melo735f7e02014-01-03 14:56:49 -03002516 argv, false, NULL);
Namhyung Kimf15eb532012-10-05 14:02:16 +09002517 if (err < 0) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002518 fprintf(trace->output, "Couldn't run the workload!\n");
Arnaldo Carvalho de Melo03ad9742014-01-03 15:56:06 -03002519 goto out_delete_evlist;
Namhyung Kimf15eb532012-10-05 14:02:16 +09002520 }
2521 }
2522
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002523 err = perf_evlist__open(evlist);
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002524 if (err < 0)
2525 goto out_error_open;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002526
Wang Nanba504232016-02-26 09:31:54 +00002527 err = bpf__apply_obj_config();
2528 if (err) {
2529 char errbuf[BUFSIZ];
2530
2531 bpf__strerror_apply_obj_config(err, errbuf, sizeof(errbuf));
2532 pr_err("ERROR: Apply config to BPF failed: %s\n",
2533 errbuf);
2534 goto out_error_open;
2535 }
2536
Arnaldo Carvalho de Melo241b0572015-02-21 10:15:21 -08002537 /*
2538 * Better not use !target__has_task() here because we need to cover the
2539 * case where no threads were specified in the command line, but a
2540 * workload was, and in that case we will fill in the thread_map when
2541 * we fork the workload in perf_evlist__prepare_workload.
2542 */
Arnaldo Carvalho de Melof078c382015-02-21 11:36:52 -08002543 if (trace->filter_pids.nr > 0)
2544 err = perf_evlist__set_filter_pids(evlist, trace->filter_pids.nr, trace->filter_pids.entries);
Jiri Olsae13798c2015-06-23 00:36:02 +02002545 else if (thread_map__pid(evlist->threads, 0) == -1)
Arnaldo Carvalho de Melof078c382015-02-21 11:36:52 -08002546 err = perf_evlist__set_filter_pid(evlist, getpid());
2547
Arnaldo Carvalho de Melo94ad89b2015-07-03 17:42:03 -03002548 if (err < 0)
2549 goto out_error_mem;
2550
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002551 if (trace->ev_qualifier_ids.nr > 0) {
2552 err = trace__set_ev_qualifier_filter(trace);
2553 if (err < 0)
2554 goto out_errno;
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002555
Arnaldo Carvalho de Melo2e5e5f82015-08-03 17:12:29 -03002556 pr_debug("event qualifier tracepoint filter: %s\n",
2557 trace->syscalls.events.sys_exit->filter);
2558 }
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002559
Arnaldo Carvalho de Melo94ad89b2015-07-03 17:42:03 -03002560 err = perf_evlist__apply_filters(evlist, &evsel);
2561 if (err < 0)
2562 goto out_error_apply_filters;
Arnaldo Carvalho de Melo241b0572015-02-21 10:15:21 -08002563
Jiri Olsaf8850372013-11-28 17:57:22 +01002564 err = perf_evlist__mmap(evlist, trace->opts.mmap_pages, false);
Arnaldo Carvalho de Meloe09b18d2014-12-11 18:04:10 -03002565 if (err < 0)
2566 goto out_error_mmap;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002567
Arnaldo Carvalho de Melocb24d012015-04-22 10:04:23 -03002568 if (!target__none(&trace->opts.target))
2569 perf_evlist__enable(evlist);
2570
Namhyung Kimf15eb532012-10-05 14:02:16 +09002571 if (forks)
2572 perf_evlist__start_workload(evlist);
2573
Jiri Olsae13798c2015-06-23 00:36:02 +02002574 trace->multiple_threads = thread_map__pid(evlist->threads, 0) == -1 ||
Arnaldo Carvalho de Melo42052be2015-02-13 12:32:45 -03002575 evlist->threads->nr > 1 ||
2576 perf_evlist__first(evlist)->attr.inherit;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002577again:
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03002578 before = trace->nr_events;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002579
2580 for (i = 0; i < evlist->nr_mmaps; i++) {
2581 union perf_event *event;
2582
2583 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002584 struct perf_sample sample;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002585
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03002586 ++trace->nr_events;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002587
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002588 err = perf_evlist__parse_sample(evlist, event, &sample);
2589 if (err) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002590 fprintf(trace->output, "Can't parse sample, err = %d, skipping...\n", err);
Zhouyi Zhou8e50d382013-10-24 15:43:33 +08002591 goto next_event;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002592 }
2593
Arnaldo Carvalho de Meloddbb1b12015-02-21 12:10:29 -08002594 trace__handle_event(trace, event, &sample);
Zhouyi Zhou8e50d382013-10-24 15:43:33 +08002595next_event:
2596 perf_evlist__mmap_consume(evlist, i);
Arnaldo Carvalho de Melo20c5f102013-09-03 11:55:07 -03002597
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002598 if (interrupted)
2599 goto out_disable;
Arnaldo Carvalho de Melo02ac5422015-04-22 11:11:57 -03002600
2601 if (done && !draining) {
2602 perf_evlist__disable(evlist);
2603 draining = true;
2604 }
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002605 }
2606 }
2607
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03002608 if (trace->nr_events == before) {
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002609 int timeout = done ? 100 : -1;
Namhyung Kimf15eb532012-10-05 14:02:16 +09002610
Arnaldo Carvalho de Melo46fb3c22014-09-22 14:39:48 -03002611 if (!draining && perf_evlist__poll(evlist, timeout) > 0) {
2612 if (perf_evlist__filter_pollfd(evlist, POLLERR | POLLHUP) == 0)
2613 draining = true;
2614
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002615 goto again;
Arnaldo Carvalho de Melo46fb3c22014-09-22 14:39:48 -03002616 }
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002617 } else {
2618 goto again;
Namhyung Kimf15eb532012-10-05 14:02:16 +09002619 }
2620
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002621out_disable:
Arnaldo Carvalho de Melof3b623b2015-03-02 22:21:35 -03002622 thread__zput(trace->current);
2623
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002624 perf_evlist__disable(evlist);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002625
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002626 if (!err) {
2627 if (trace->summary)
2628 trace__fprintf_thread_summary(trace, trace->output);
2629
2630 if (trace->show_tool_stats) {
2631 fprintf(trace->output, "Stats:\n "
2632 " vfs_getname : %" PRIu64 "\n"
2633 " proc_getname: %" PRIu64 "\n",
2634 trace->stats.vfs_getname,
2635 trace->stats.proc_getname);
2636 }
2637 }
David Ahernbf2575c2013-10-08 21:26:53 -06002638
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002639out_delete_evlist:
2640 perf_evlist__delete(evlist);
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002641 trace->evlist = NULL;
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03002642 trace->live = false;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002643 return err;
Arnaldo Carvalho de Melo6ef068c2013-10-17 12:07:58 -03002644{
2645 char errbuf[BUFSIZ];
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002646
Arnaldo Carvalho de Melo2cc990b2015-01-22 11:13:43 -03002647out_error_sched_stat_runtime:
Jiri Olsa988bdb32015-09-02 09:56:35 +02002648 tracing_path__strerror_open_tp(errno, errbuf, sizeof(errbuf), "sched", "sched_stat_runtime");
Arnaldo Carvalho de Melo2cc990b2015-01-22 11:13:43 -03002649 goto out_error;
2650
Arnaldo Carvalho de Melo801c67b2015-01-22 10:52:55 -03002651out_error_raw_syscalls:
Jiri Olsa988bdb32015-09-02 09:56:35 +02002652 tracing_path__strerror_open_tp(errno, errbuf, sizeof(errbuf), "raw_syscalls", "sys_(enter|exit)");
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002653 goto out_error;
2654
Arnaldo Carvalho de Meloe09b18d2014-12-11 18:04:10 -03002655out_error_mmap:
2656 perf_evlist__strerror_mmap(evlist, errno, errbuf, sizeof(errbuf));
2657 goto out_error;
2658
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002659out_error_open:
2660 perf_evlist__strerror_open(evlist, errno, errbuf, sizeof(errbuf));
2661
2662out_error:
Arnaldo Carvalho de Melo6ef068c2013-10-17 12:07:58 -03002663 fprintf(trace->output, "%s\n", errbuf);
Ramkumar Ramachandra87f91862013-10-04 10:47:31 +05302664 goto out_delete_evlist;
Arnaldo Carvalho de Melo94ad89b2015-07-03 17:42:03 -03002665
2666out_error_apply_filters:
2667 fprintf(trace->output,
2668 "Failed to set filter \"%s\" on event %s with %d (%s)\n",
2669 evsel->filter, perf_evsel__name(evsel), errno,
2670 strerror_r(errno, errbuf, sizeof(errbuf)));
2671 goto out_delete_evlist;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002672}
Arnaldo Carvalho de Melo5ed08da2015-01-22 11:08:04 -03002673out_error_mem:
2674 fprintf(trace->output, "Not enough memory to run!\n");
2675 goto out_delete_evlist;
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002676
2677out_errno:
2678 fprintf(trace->output, "errno=%d,%s\n", errno, strerror(errno));
2679 goto out_delete_evlist;
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002680}
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002681
David Ahern6810fc92013-08-28 22:29:52 -06002682static int trace__replay(struct trace *trace)
2683{
2684 const struct perf_evsel_str_handler handlers[] = {
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002685 { "probe:vfs_getname", trace__vfs_getname, },
David Ahern6810fc92013-08-28 22:29:52 -06002686 };
Jiri Olsaf5fc14122013-10-15 16:27:32 +02002687 struct perf_data_file file = {
2688 .path = input_name,
2689 .mode = PERF_DATA_MODE_READ,
Yunlong Songe366a6d2015-04-02 21:47:18 +08002690 .force = trace->force,
Jiri Olsaf5fc14122013-10-15 16:27:32 +02002691 };
David Ahern6810fc92013-08-28 22:29:52 -06002692 struct perf_session *session;
Namhyung Kim003824e2013-11-12 15:25:00 +09002693 struct perf_evsel *evsel;
David Ahern6810fc92013-08-28 22:29:52 -06002694 int err = -1;
2695
2696 trace->tool.sample = trace__process_sample;
2697 trace->tool.mmap = perf_event__process_mmap;
David Ahern384c6712013-09-22 19:44:58 -06002698 trace->tool.mmap2 = perf_event__process_mmap2;
David Ahern6810fc92013-08-28 22:29:52 -06002699 trace->tool.comm = perf_event__process_comm;
2700 trace->tool.exit = perf_event__process_exit;
2701 trace->tool.fork = perf_event__process_fork;
2702 trace->tool.attr = perf_event__process_attr;
2703 trace->tool.tracing_data = perf_event__process_tracing_data;
2704 trace->tool.build_id = perf_event__process_build_id;
2705
Jiri Olsa0a8cb852014-07-06 14:18:21 +02002706 trace->tool.ordered_events = true;
David Ahern6810fc92013-08-28 22:29:52 -06002707 trace->tool.ordering_requires_timestamps = true;
2708
2709 /* add tid to output */
2710 trace->multiple_threads = true;
2711
Jiri Olsaf5fc14122013-10-15 16:27:32 +02002712 session = perf_session__new(&file, false, &trace->tool);
David Ahern6810fc92013-08-28 22:29:52 -06002713 if (session == NULL)
Taeung Song52e028342014-09-24 10:33:37 +09002714 return -1;
David Ahern6810fc92013-08-28 22:29:52 -06002715
Namhyung Kim0a7e6d12014-08-12 15:40:45 +09002716 if (symbol__init(&session->header.env) < 0)
Namhyung Kimcb2ffae2014-08-12 15:40:44 +09002717 goto out;
2718
David Ahern8fb598e2013-09-28 13:13:00 -06002719 trace->host = &session->machines.host;
2720
David Ahern6810fc92013-08-28 22:29:52 -06002721 err = perf_session__set_tracepoints_handlers(session, handlers);
2722 if (err)
2723 goto out;
2724
Namhyung Kim003824e2013-11-12 15:25:00 +09002725 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2726 "raw_syscalls:sys_enter");
David Ahern9aca7f12013-12-04 19:41:39 -07002727 /* older kernels have syscalls tp versus raw_syscalls */
2728 if (evsel == NULL)
2729 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2730 "syscalls:sys_enter");
David Ahern6810fc92013-08-28 22:29:52 -06002731
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002732 if (evsel &&
2733 (perf_evsel__init_syscall_tp(evsel, trace__sys_enter) < 0 ||
2734 perf_evsel__init_sc_tp_ptr_field(evsel, args))) {
Namhyung Kim003824e2013-11-12 15:25:00 +09002735 pr_err("Error during initialize raw_syscalls:sys_enter event\n");
2736 goto out;
2737 }
2738
2739 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2740 "raw_syscalls:sys_exit");
David Ahern9aca7f12013-12-04 19:41:39 -07002741 if (evsel == NULL)
2742 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2743 "syscalls:sys_exit");
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002744 if (evsel &&
2745 (perf_evsel__init_syscall_tp(evsel, trace__sys_exit) < 0 ||
2746 perf_evsel__init_sc_tp_uint_field(evsel, ret))) {
Namhyung Kim003824e2013-11-12 15:25:00 +09002747 pr_err("Error during initialize raw_syscalls:sys_exit event\n");
David Ahern6810fc92013-08-28 22:29:52 -06002748 goto out;
2749 }
2750
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002751 evlist__for_each(session->evlist, evsel) {
2752 if (evsel->attr.type == PERF_TYPE_SOFTWARE &&
2753 (evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ||
2754 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MIN ||
2755 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS))
2756 evsel->handler = trace__pgfault;
2757 }
2758
David Ahernbdc89662013-08-28 22:29:53 -06002759 err = parse_target_str(trace);
2760 if (err != 0)
2761 goto out;
2762
David Ahern6810fc92013-08-28 22:29:52 -06002763 setup_pager();
2764
Arnaldo Carvalho de Melob7b61cb2015-03-03 11:58:45 -03002765 err = perf_session__process_events(session);
David Ahern6810fc92013-08-28 22:29:52 -06002766 if (err)
2767 pr_err("Failed to process events, error %d", err);
2768
David Ahernbf2575c2013-10-08 21:26:53 -06002769 else if (trace->summary)
2770 trace__fprintf_thread_summary(trace, trace->output);
2771
David Ahern6810fc92013-08-28 22:29:52 -06002772out:
2773 perf_session__delete(session);
2774
2775 return err;
2776}
2777
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002778static size_t trace__fprintf_threads_header(FILE *fp)
2779{
2780 size_t printed;
2781
Pekka Enberg99ff7152013-11-12 16:42:14 +02002782 printed = fprintf(fp, "\n Summary of events:\n\n");
David Ahernbf2575c2013-10-08 21:26:53 -06002783
2784 return printed;
2785}
2786
2787static size_t thread__dump_stats(struct thread_trace *ttrace,
2788 struct trace *trace, FILE *fp)
2789{
2790 struct stats *stats;
2791 size_t printed = 0;
2792 struct syscall *sc;
2793 struct int_node *inode = intlist__first(ttrace->syscall_stats);
2794
2795 if (inode == NULL)
2796 return 0;
2797
2798 printed += fprintf(fp, "\n");
2799
Milian Wolff834fd462015-08-06 11:24:29 +02002800 printed += fprintf(fp, " syscall calls total min avg max stddev\n");
2801 printed += fprintf(fp, " (msec) (msec) (msec) (msec) (%%)\n");
2802 printed += fprintf(fp, " --------------- -------- --------- --------- --------- --------- ------\n");
Pekka Enberg99ff7152013-11-12 16:42:14 +02002803
David Ahernbf2575c2013-10-08 21:26:53 -06002804 /* each int_node is a syscall */
2805 while (inode) {
2806 stats = inode->priv;
2807 if (stats) {
2808 double min = (double)(stats->min) / NSEC_PER_MSEC;
2809 double max = (double)(stats->max) / NSEC_PER_MSEC;
2810 double avg = avg_stats(stats);
2811 double pct;
2812 u64 n = (u64) stats->n;
2813
2814 pct = avg ? 100.0 * stddev_stats(stats)/avg : 0.0;
2815 avg /= NSEC_PER_MSEC;
2816
2817 sc = &trace->syscalls.table[inode->i];
Pekka Enberg99ff7152013-11-12 16:42:14 +02002818 printed += fprintf(fp, " %-15s", sc->name);
Milian Wolff834fd462015-08-06 11:24:29 +02002819 printed += fprintf(fp, " %8" PRIu64 " %9.3f %9.3f %9.3f",
2820 n, avg * n, min, avg);
Pekka Enberg27a778b2013-11-13 14:21:48 +02002821 printed += fprintf(fp, " %9.3f %9.2f%%\n", max, pct);
David Ahernbf2575c2013-10-08 21:26:53 -06002822 }
2823
2824 inode = intlist__next(inode);
2825 }
2826
2827 printed += fprintf(fp, "\n\n");
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002828
2829 return printed;
2830}
2831
David Ahern896cbb52013-09-28 13:12:59 -06002832/* struct used to pass data to per-thread function */
2833struct summary_data {
2834 FILE *fp;
2835 struct trace *trace;
2836 size_t printed;
2837};
2838
2839static int trace__fprintf_one_thread(struct thread *thread, void *priv)
2840{
2841 struct summary_data *data = priv;
2842 FILE *fp = data->fp;
2843 size_t printed = data->printed;
2844 struct trace *trace = data->trace;
Namhyung Kim89dceb22014-10-06 09:46:03 +09002845 struct thread_trace *ttrace = thread__priv(thread);
David Ahern896cbb52013-09-28 13:12:59 -06002846 double ratio;
2847
2848 if (ttrace == NULL)
2849 return 0;
2850
2851 ratio = (double)ttrace->nr_events / trace->nr_events * 100.0;
2852
Pekka Enberg15e65c62013-11-14 18:43:30 +02002853 printed += fprintf(fp, " %s (%d), ", thread__comm_str(thread), thread->tid);
Pekka Enberg99ff7152013-11-12 16:42:14 +02002854 printed += fprintf(fp, "%lu events, ", ttrace->nr_events);
Pekka Enberg15e65c62013-11-14 18:43:30 +02002855 printed += fprintf(fp, "%.1f%%", ratio);
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04002856 if (ttrace->pfmaj)
2857 printed += fprintf(fp, ", %lu majfaults", ttrace->pfmaj);
2858 if (ttrace->pfmin)
2859 printed += fprintf(fp, ", %lu minfaults", ttrace->pfmin);
Pekka Enberg99ff7152013-11-12 16:42:14 +02002860 printed += fprintf(fp, ", %.3f msec\n", ttrace->runtime_ms);
David Ahernbf2575c2013-10-08 21:26:53 -06002861 printed += thread__dump_stats(ttrace, trace, fp);
David Ahern896cbb52013-09-28 13:12:59 -06002862
2863 data->printed += printed;
2864
2865 return 0;
2866}
2867
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002868static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp)
2869{
David Ahern896cbb52013-09-28 13:12:59 -06002870 struct summary_data data = {
2871 .fp = fp,
2872 .trace = trace
2873 };
2874 data.printed = trace__fprintf_threads_header(fp);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002875
David Ahern896cbb52013-09-28 13:12:59 -06002876 machine__for_each_thread(trace->host, trace__fprintf_one_thread, &data);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002877
David Ahern896cbb52013-09-28 13:12:59 -06002878 return data.printed;
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002879}
2880
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03002881static int trace__set_duration(const struct option *opt, const char *str,
2882 int unset __maybe_unused)
2883{
2884 struct trace *trace = opt->value;
2885
2886 trace->duration_filter = atof(str);
2887 return 0;
2888}
2889
Arnaldo Carvalho de Melof078c382015-02-21 11:36:52 -08002890static int trace__set_filter_pids(const struct option *opt, const char *str,
2891 int unset __maybe_unused)
2892{
2893 int ret = -1;
2894 size_t i;
2895 struct trace *trace = opt->value;
2896 /*
2897 * FIXME: introduce a intarray class, plain parse csv and create a
2898 * { int nr, int entries[] } struct...
2899 */
2900 struct intlist *list = intlist__new(str);
2901
2902 if (list == NULL)
2903 return -1;
2904
2905 i = trace->filter_pids.nr = intlist__nr_entries(list) + 1;
2906 trace->filter_pids.entries = calloc(i, sizeof(pid_t));
2907
2908 if (trace->filter_pids.entries == NULL)
2909 goto out;
2910
2911 trace->filter_pids.entries[0] = getpid();
2912
2913 for (i = 1; i < trace->filter_pids.nr; ++i)
2914 trace->filter_pids.entries[i] = intlist__entry(list, i - 1)->i;
2915
2916 intlist__delete(list);
2917 ret = 0;
2918out:
2919 return ret;
2920}
2921
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002922static int trace__open_output(struct trace *trace, const char *filename)
2923{
2924 struct stat st;
2925
2926 if (!stat(filename, &st) && st.st_size) {
2927 char oldname[PATH_MAX];
2928
2929 scnprintf(oldname, sizeof(oldname), "%s.old", filename);
2930 unlink(oldname);
2931 rename(filename, oldname);
2932 }
2933
2934 trace->output = fopen(filename, "w");
2935
2936 return trace->output == NULL ? -errno : 0;
2937}
2938
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002939static int parse_pagefaults(const struct option *opt, const char *str,
2940 int unset __maybe_unused)
2941{
2942 int *trace_pgfaults = opt->value;
2943
2944 if (strcmp(str, "all") == 0)
2945 *trace_pgfaults |= TRACE_PFMAJ | TRACE_PFMIN;
2946 else if (strcmp(str, "maj") == 0)
2947 *trace_pgfaults |= TRACE_PFMAJ;
2948 else if (strcmp(str, "min") == 0)
2949 *trace_pgfaults |= TRACE_PFMIN;
2950 else
2951 return -1;
2952
2953 return 0;
2954}
2955
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002956static void evlist__set_evsel_handler(struct perf_evlist *evlist, void *handler)
2957{
2958 struct perf_evsel *evsel;
2959
2960 evlist__for_each(evlist, evsel)
2961 evsel->handler = handler;
2962}
2963
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002964int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
2965{
Yunlong Song6fdd9cb2015-03-18 21:35:57 +08002966 const char *trace_usage[] = {
Namhyung Kimf15eb532012-10-05 14:02:16 +09002967 "perf trace [<options>] [<command>]",
2968 "perf trace [<options>] -- <command> [<options>]",
David Ahern5e2485b2013-09-28 13:13:01 -06002969 "perf trace record [<options>] [<command>]",
2970 "perf trace record [<options>] -- <command> [<options>]",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002971 NULL
2972 };
2973 struct trace trace = {
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002974 .syscalls = {
2975 . max = -1,
2976 },
2977 .opts = {
2978 .target = {
2979 .uid = UINT_MAX,
2980 .uses_mmap = true,
2981 },
2982 .user_freq = UINT_MAX,
2983 .user_interval = ULLONG_MAX,
Arnaldo Carvalho de Melo509051e2014-01-14 17:52:14 -03002984 .no_buffering = true,
Arnaldo Carvalho de Melo38d54472014-12-12 17:28:32 -03002985 .mmap_pages = UINT_MAX,
Kan Liang9d9cad72015-06-17 09:51:11 -04002986 .proc_map_timeout = 500,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002987 },
Milian Wolff007d66a2015-08-05 16:52:23 -03002988 .output = stderr,
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -03002989 .show_comm = true,
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002990 .trace_syscalls = true,
Arnaldo Carvalho de Melo44621812016-04-11 15:49:11 -03002991 .kernel_syscallchains = false,
Arnaldo Carvalho de Melo05614992016-04-15 16:41:19 -03002992 .max_stack = UINT_MAX,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002993 };
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002994 const char *output_name = NULL;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03002995 const char *ev_qualifier_str = NULL;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002996 const struct option trace_options[] = {
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002997 OPT_CALLBACK(0, "event", &trace.evlist, "event",
2998 "event selector. use 'perf list' to list available events",
2999 parse_events_option),
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -03003000 OPT_BOOLEAN(0, "comm", &trace.show_comm,
3001 "show the thread COMM next to its id"),
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03003002 OPT_BOOLEAN(0, "tool_stats", &trace.show_tool_stats, "show tool stats"),
Arnaldo Carvalho de Melod303e852015-04-23 12:02:07 -03003003 OPT_STRING('e', "expr", &ev_qualifier_str, "expr", "list of syscalls to trace"),
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003004 OPT_STRING('o', "output", &output_name, "file", "output file name"),
David Ahern6810fc92013-08-28 22:29:52 -06003005 OPT_STRING('i', "input", &input_name, "file", "Analyze events in file"),
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003006 OPT_STRING('p', "pid", &trace.opts.target.pid, "pid",
3007 "trace events on existing process id"),
David Ahernac9be8e2013-08-20 11:15:45 -06003008 OPT_STRING('t', "tid", &trace.opts.target.tid, "tid",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003009 "trace events on existing thread id"),
Arnaldo Carvalho de Melofa0e4ff2015-04-23 11:59:20 -03003010 OPT_CALLBACK(0, "filter-pids", &trace, "CSV list of pids",
3011 "pids to filter (by the kernel)", trace__set_filter_pids),
David Ahernac9be8e2013-08-20 11:15:45 -06003012 OPT_BOOLEAN('a', "all-cpus", &trace.opts.target.system_wide,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003013 "system-wide collection from all CPUs"),
David Ahernac9be8e2013-08-20 11:15:45 -06003014 OPT_STRING('C', "cpu", &trace.opts.target.cpu_list, "cpu",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003015 "list of cpus to monitor"),
David Ahern6810fc92013-08-28 22:29:52 -06003016 OPT_BOOLEAN(0, "no-inherit", &trace.opts.no_inherit,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003017 "child tasks do not inherit counters"),
Jiri Olsa994a1f72013-09-01 12:36:12 +02003018 OPT_CALLBACK('m', "mmap-pages", &trace.opts.mmap_pages, "pages",
3019 "number of mmap data pages",
3020 perf_evlist__parse_mmap_pages),
David Ahernac9be8e2013-08-20 11:15:45 -06003021 OPT_STRING('u', "uid", &trace.opts.target.uid_str, "user",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003022 "user to profile"),
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03003023 OPT_CALLBACK(0, "duration", &trace, "float",
3024 "show only events with duration > N.M ms",
3025 trace__set_duration),
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03003026 OPT_BOOLEAN(0, "sched", &trace.sched, "show blocking scheduler events"),
Arnaldo Carvalho de Melo7c304ee02013-08-22 16:49:54 -03003027 OPT_INCR('v', "verbose", &verbose, "be more verbose"),
David Ahern4bb09192013-09-04 12:37:43 -06003028 OPT_BOOLEAN('T', "time", &trace.full_time,
3029 "Show full timestamp, not time relative to first start"),
David Ahernfd2eaba2013-11-12 09:31:15 -07003030 OPT_BOOLEAN('s', "summary", &trace.summary_only,
3031 "Show only syscall summary with statistics"),
3032 OPT_BOOLEAN('S', "with-summary", &trace.summary,
3033 "Show all syscalls and summary with statistics"),
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04003034 OPT_CALLBACK_DEFAULT('F', "pf", &trace.trace_pgfaults, "all|maj|min",
3035 "Trace pagefaults", parse_pagefaults, "maj"),
Stanislav Fomicheve281a962014-06-26 20:14:28 +04003036 OPT_BOOLEAN(0, "syscalls", &trace.trace_syscalls, "Trace syscalls"),
Yunlong Songe366a6d2015-04-02 21:47:18 +08003037 OPT_BOOLEAN('f', "force", &trace.force, "don't complain, do it"),
Milian Wolff566a0882016-04-08 13:34:15 +02003038 OPT_CALLBACK(0, "call-graph", &trace.opts,
3039 "record_mode[,record_size]", record_callchain_help,
3040 &record_parse_callchain_opt),
Arnaldo Carvalho de Melo44621812016-04-11 15:49:11 -03003041 OPT_BOOLEAN(0, "kernel-syscall-graph", &trace.kernel_syscallchains,
3042 "Show the kernel callchains on the syscall exit path"),
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -03003043 OPT_UINTEGER(0, "min-stack", &trace.min_stack,
3044 "Set the minimum stack depth when parsing the callchain, "
3045 "anything below the specified depth will be ignored."),
Arnaldo Carvalho de Meloc6d4a492016-04-14 18:29:08 -03003046 OPT_UINTEGER(0, "max-stack", &trace.max_stack,
3047 "Set the maximum stack depth when parsing the callchain, "
3048 "anything beyond the specified depth will be ignored. "
Arnaldo Carvalho de Melo4cb93442016-04-27 10:16:24 -03003049 "Default: kernel.perf_event_max_stack or " __stringify(PERF_MAX_STACK_DEPTH)),
Kan Liang9d9cad72015-06-17 09:51:11 -04003050 OPT_UINTEGER(0, "proc-map-timeout", &trace.opts.proc_map_timeout,
3051 "per thread proc mmap processing timeout in ms"),
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003052 OPT_END()
3053 };
Arnaldo Carvalho de Meloccd62a82016-04-16 09:36:32 -03003054 bool __maybe_unused max_stack_user_set = true;
Arnaldo Carvalho de Melof3e459d2016-04-15 17:52:34 -03003055 bool mmap_pages_user_set = true;
Yunlong Song6fdd9cb2015-03-18 21:35:57 +08003056 const char * const trace_subcommands[] = { "record", NULL };
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003057 int err;
Namhyung Kim32caf0d2012-10-05 14:02:13 +09003058 char bf[BUFSIZ];
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003059
Arnaldo Carvalho de Melo4d08cb82015-02-24 15:35:55 -03003060 signal(SIGSEGV, sighandler_dump_stack);
3061 signal(SIGFPE, sighandler_dump_stack);
3062
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003063 trace.evlist = perf_evlist__new();
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03003064 trace.sctbl = syscalltbl__new();
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003065
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03003066 if (trace.evlist == NULL || trace.sctbl == NULL) {
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003067 pr_err("Not enough memory to run!\n");
He Kuangff8f6952015-05-11 12:28:36 +00003068 err = -ENOMEM;
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003069 goto out;
3070 }
3071
Yunlong Song6fdd9cb2015-03-18 21:35:57 +08003072 argc = parse_options_subcommand(argc, argv, trace_options, trace_subcommands,
3073 trace_usage, PARSE_OPT_STOP_AT_NON_OPTION);
David Ahernfd2eaba2013-11-12 09:31:15 -07003074
Wang Nand7888572016-04-08 15:07:24 +00003075 err = bpf__setup_stdout(trace.evlist);
3076 if (err) {
3077 bpf__strerror_setup_stdout(trace.evlist, err, bf, sizeof(bf));
3078 pr_err("ERROR: Setup BPF stdout failed: %s\n", bf);
3079 goto out;
3080 }
3081
Arnaldo Carvalho de Melo59247e32016-04-12 16:05:02 -03003082 err = -1;
3083
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04003084 if (trace.trace_pgfaults) {
3085 trace.opts.sample_address = true;
3086 trace.opts.sample_time = true;
3087 }
3088
Arnaldo Carvalho de Melof3e459d2016-04-15 17:52:34 -03003089 if (trace.opts.mmap_pages == UINT_MAX)
3090 mmap_pages_user_set = false;
3091
Arnaldo Carvalho de Melo05614992016-04-15 16:41:19 -03003092 if (trace.max_stack == UINT_MAX) {
Arnaldo Carvalho de Melo4cb93442016-04-27 10:16:24 -03003093 trace.max_stack = sysctl_perf_event_max_stack;
Arnaldo Carvalho de Melo05614992016-04-15 16:41:19 -03003094 max_stack_user_set = false;
3095 }
3096
3097#ifdef HAVE_DWARF_UNWIND_SUPPORT
Arnaldo Carvalho de Melo2ddd5c02016-04-18 12:09:08 -03003098 if ((trace.min_stack || max_stack_user_set) && !callchain_param.enabled)
Arnaldo Carvalho de Melo05614992016-04-15 16:41:19 -03003099 record_opts__parse_callchain(&trace.opts, &callchain_param, "dwarf", false);
3100#endif
3101
Arnaldo Carvalho de Melo2ddd5c02016-04-18 12:09:08 -03003102 if (callchain_param.enabled) {
Arnaldo Carvalho de Melof3e459d2016-04-15 17:52:34 -03003103 if (!mmap_pages_user_set && geteuid() == 0)
3104 trace.opts.mmap_pages = perf_event_mlock_kb_in_pages() * 4;
3105
Milian Wolff566a0882016-04-08 13:34:15 +02003106 symbol_conf.use_callchain = true;
Arnaldo Carvalho de Melof3e459d2016-04-15 17:52:34 -03003107 }
Milian Wolff566a0882016-04-08 13:34:15 +02003108
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003109 if (trace.evlist->nr_entries > 0)
3110 evlist__set_evsel_handler(trace.evlist, trace__event_handler);
3111
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04003112 if ((argc >= 1) && (strcmp(argv[0], "record") == 0))
3113 return trace__record(&trace, argc-1, &argv[1]);
3114
3115 /* summary_only implies summary option, but don't overwrite summary if set */
3116 if (trace.summary_only)
3117 trace.summary = trace.summary_only;
3118
Arnaldo Carvalho de Melo726f3232015-02-06 10:16:45 +01003119 if (!trace.trace_syscalls && !trace.trace_pgfaults &&
3120 trace.evlist->nr_entries == 0 /* Was --events used? */) {
Stanislav Fomicheve281a962014-06-26 20:14:28 +04003121 pr_err("Please specify something to trace.\n");
3122 return -1;
3123 }
3124
Arnaldo Carvalho de Melo59247e32016-04-12 16:05:02 -03003125 if (!trace.trace_syscalls && ev_qualifier_str) {
3126 pr_err("The -e option can't be used with --no-syscalls.\n");
3127 goto out;
3128 }
3129
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003130 if (output_name != NULL) {
3131 err = trace__open_output(&trace, output_name);
3132 if (err < 0) {
3133 perror("failed to create output file");
3134 goto out;
3135 }
3136 }
3137
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03003138 trace.open_id = syscalltbl__id(trace.sctbl, "open");
3139
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03003140 if (ev_qualifier_str != NULL) {
Arnaldo Carvalho de Melob059efd2013-08-21 12:56:21 -03003141 const char *s = ev_qualifier_str;
Arnaldo Carvalho de Melo005438a82015-07-20 12:02:09 -03003142 struct strlist_config slist_config = {
3143 .dirname = system_path(STRACE_GROUPS_DIR),
3144 };
Arnaldo Carvalho de Melob059efd2013-08-21 12:56:21 -03003145
3146 trace.not_ev_qualifier = *s == '!';
3147 if (trace.not_ev_qualifier)
3148 ++s;
Arnaldo Carvalho de Melo005438a82015-07-20 12:02:09 -03003149 trace.ev_qualifier = strlist__new(s, &slist_config);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03003150 if (trace.ev_qualifier == NULL) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003151 fputs("Not enough memory to parse event qualifier",
3152 trace.output);
3153 err = -ENOMEM;
3154 goto out_close;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03003155 }
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03003156
3157 err = trace__validate_ev_qualifier(&trace);
3158 if (err)
3159 goto out_close;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03003160 }
3161
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003162 err = target__validate(&trace.opts.target);
Namhyung Kim32caf0d2012-10-05 14:02:13 +09003163 if (err) {
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003164 target__strerror(&trace.opts.target, err, bf, sizeof(bf));
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003165 fprintf(trace.output, "%s", bf);
3166 goto out_close;
Namhyung Kim32caf0d2012-10-05 14:02:13 +09003167 }
3168
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003169 err = target__parse_uid(&trace.opts.target);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003170 if (err) {
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003171 target__strerror(&trace.opts.target, err, bf, sizeof(bf));
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003172 fprintf(trace.output, "%s", bf);
3173 goto out_close;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003174 }
3175
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003176 if (!argc && target__none(&trace.opts.target))
Namhyung Kimee761202012-10-05 14:02:14 +09003177 trace.opts.target.system_wide = true;
3178
David Ahern6810fc92013-08-28 22:29:52 -06003179 if (input_name)
3180 err = trace__replay(&trace);
3181 else
3182 err = trace__run(&trace, argc, argv);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03003183
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003184out_close:
3185 if (output_name != NULL)
3186 fclose(trace.output);
3187out:
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03003188 return err;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003189}