blob: 6a64cb1344c701c39e41ce62499220f639740dd2 [file] [log] [blame]
Arnaldo Carvalho de Meloa598bb52015-08-28 12:02:37 -03001/*
2 * builtin-trace.c
3 *
4 * Builtin 'trace' command:
5 *
6 * Display a continuously updated trace of any workload, CPU, specific PID,
7 * system wide, etc. Default format is loosely strace like, but any other
8 * event may be specified using --event.
9 *
10 * Copyright (C) 2012, 2013, 2014, 2015 Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
11 *
12 * Initially based on the 'trace' prototype by Thomas Gleixner:
13 *
14 * http://lwn.net/Articles/415728/ ("Announcing a new utility: 'trace'")
15 *
16 * Released under the GPL v2. (and only v2, not any later version)
17 */
18
Robert Richter4e319022013-06-11 17:29:18 +020019#include <traceevent/event-parse.h>
Jiri Olsa988bdb32015-09-02 09:56:35 +020020#include <api/fs/tracing_path.h>
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -030021#include "builtin.h"
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -030022#include "util/color.h"
Arnaldo Carvalho de Melo7c304ee02013-08-22 16:49:54 -030023#include "util/debug.h"
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -030024#include "util/evlist.h"
Josh Poimboeuf4b6ab942015-12-15 09:39:39 -060025#include <subcmd/exec-cmd.h>
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -030026#include "util/machine.h"
David Ahern6810fc92013-08-28 22:29:52 -060027#include "util/session.h"
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -030028#include "util/thread.h"
Josh Poimboeuf4b6ab942015-12-15 09:39:39 -060029#include <subcmd/parse-options.h>
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -030030#include "util/strlist.h"
David Ahernbdc89662013-08-28 22:29:53 -060031#include "util/intlist.h"
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -030032#include "util/thread_map.h"
David Ahernbf2575c2013-10-08 21:26:53 -060033#include "util/stat.h"
Jiri Olsa97978b32013-12-03 14:09:24 +010034#include "trace-event.h"
David Ahern9aca7f12013-12-04 19:41:39 -070035#include "util/parse-events.h"
Wang Nanba504232016-02-26 09:31:54 +000036#include "util/bpf-loader.h"
Milian Wolff566a0882016-04-08 13:34:15 +020037#include "callchain.h"
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -030038#include "syscalltbl.h"
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -030039
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -030040#include <libaudit.h> /* FIXME: Still needed for audit_errno_to_name */
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -030041#include <stdlib.h>
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -030042#include <linux/futex.h>
Jiri Olsa8dd2a132015-09-07 10:38:06 +020043#include <linux/err.h>
Arnaldo Carvalho de Melo997bba82016-03-30 19:43:32 -030044#include <linux/seccomp.h>
45#include <linux/filter.h>
46#include <linux/audit.h>
47#include <sys/ptrace.h>
Arnaldo Carvalho de Melo39878d42016-03-30 20:02:15 -030048#include <linux/random.h>
Arnaldo Carvalho de Meloc6d4a492016-04-14 18:29:08 -030049#include <linux/stringify.h>
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -030050
Arnaldo Carvalho de Meloc188e7a2015-05-14 17:39:03 -030051#ifndef O_CLOEXEC
52# define O_CLOEXEC 02000000
53#endif
54
Arnaldo Carvalho de Meloc188e7a2015-05-14 17:39:03 -030055#ifndef MSG_CMSG_CLOEXEC
56# define MSG_CMSG_CLOEXEC 0x40000000
57#endif
58
Arnaldo Carvalho de Meloa1c25522015-06-11 22:47:54 -030059#ifndef PERF_FLAG_FD_NO_GROUP
60# define PERF_FLAG_FD_NO_GROUP (1UL << 0)
61#endif
62
63#ifndef PERF_FLAG_FD_OUTPUT
64# define PERF_FLAG_FD_OUTPUT (1UL << 1)
65#endif
66
67#ifndef PERF_FLAG_PID_CGROUP
68# define PERF_FLAG_PID_CGROUP (1UL << 2) /* pid=cgroup id, per-cpu mode only */
69#endif
70
71#ifndef PERF_FLAG_FD_CLOEXEC
72# define PERF_FLAG_FD_CLOEXEC (1UL << 3) /* O_CLOEXEC */
73#endif
74
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -030075struct trace {
76 struct perf_tool tool;
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -030077 struct syscalltbl *sctbl;
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -030078 struct {
79 int max;
80 struct syscall *table;
81 struct {
82 struct perf_evsel *sys_enter,
83 *sys_exit;
84 } events;
85 } syscalls;
86 struct record_opts opts;
87 struct perf_evlist *evlist;
88 struct machine *host;
89 struct thread *current;
90 u64 base_time;
91 FILE *output;
92 unsigned long nr_events;
93 struct strlist *ev_qualifier;
94 struct {
95 size_t nr;
96 int *entries;
97 } ev_qualifier_ids;
98 struct intlist *tid_list;
99 struct intlist *pid_list;
100 struct {
101 size_t nr;
102 pid_t *entries;
103 } filter_pids;
104 double duration_filter;
105 double runtime_ms;
106 struct {
107 u64 vfs_getname,
108 proc_getname;
109 } stats;
Arnaldo Carvalho de Meloc6d4a492016-04-14 18:29:08 -0300110 unsigned int max_stack;
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -0300111 unsigned int min_stack;
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -0300112 bool not_ev_qualifier;
113 bool live;
114 bool full_time;
115 bool sched;
116 bool multiple_threads;
117 bool summary;
118 bool summary_only;
119 bool show_comm;
120 bool show_tool_stats;
121 bool trace_syscalls;
Arnaldo Carvalho de Melo44621812016-04-11 15:49:11 -0300122 bool kernel_syscallchains;
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -0300123 bool force;
124 bool vfs_getname;
125 int trace_pgfaults;
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -0300126 int open_id;
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -0300127};
Arnaldo Carvalho de Meloa1c25522015-06-11 22:47:54 -0300128
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300129struct tp_field {
130 int offset;
131 union {
132 u64 (*integer)(struct tp_field *field, struct perf_sample *sample);
133 void *(*pointer)(struct tp_field *field, struct perf_sample *sample);
134 };
135};
136
137#define TP_UINT_FIELD(bits) \
138static u64 tp_field__u##bits(struct tp_field *field, struct perf_sample *sample) \
139{ \
David Ahern55d43bca2015-02-19 15:00:22 -0500140 u##bits value; \
141 memcpy(&value, sample->raw_data + field->offset, sizeof(value)); \
142 return value; \
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300143}
144
145TP_UINT_FIELD(8);
146TP_UINT_FIELD(16);
147TP_UINT_FIELD(32);
148TP_UINT_FIELD(64);
149
150#define TP_UINT_FIELD__SWAPPED(bits) \
151static u64 tp_field__swapped_u##bits(struct tp_field *field, struct perf_sample *sample) \
152{ \
David Ahern55d43bca2015-02-19 15:00:22 -0500153 u##bits value; \
154 memcpy(&value, sample->raw_data + field->offset, sizeof(value)); \
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300155 return bswap_##bits(value);\
156}
157
158TP_UINT_FIELD__SWAPPED(16);
159TP_UINT_FIELD__SWAPPED(32);
160TP_UINT_FIELD__SWAPPED(64);
161
162static int tp_field__init_uint(struct tp_field *field,
163 struct format_field *format_field,
164 bool needs_swap)
165{
166 field->offset = format_field->offset;
167
168 switch (format_field->size) {
169 case 1:
170 field->integer = tp_field__u8;
171 break;
172 case 2:
173 field->integer = needs_swap ? tp_field__swapped_u16 : tp_field__u16;
174 break;
175 case 4:
176 field->integer = needs_swap ? tp_field__swapped_u32 : tp_field__u32;
177 break;
178 case 8:
179 field->integer = needs_swap ? tp_field__swapped_u64 : tp_field__u64;
180 break;
181 default:
182 return -1;
183 }
184
185 return 0;
186}
187
188static void *tp_field__ptr(struct tp_field *field, struct perf_sample *sample)
189{
190 return sample->raw_data + field->offset;
191}
192
193static int tp_field__init_ptr(struct tp_field *field, struct format_field *format_field)
194{
195 field->offset = format_field->offset;
196 field->pointer = tp_field__ptr;
197 return 0;
198}
199
200struct syscall_tp {
201 struct tp_field id;
202 union {
203 struct tp_field args, ret;
204 };
205};
206
207static int perf_evsel__init_tp_uint_field(struct perf_evsel *evsel,
208 struct tp_field *field,
209 const char *name)
210{
211 struct format_field *format_field = perf_evsel__field(evsel, name);
212
213 if (format_field == NULL)
214 return -1;
215
216 return tp_field__init_uint(field, format_field, evsel->needs_swap);
217}
218
219#define perf_evsel__init_sc_tp_uint_field(evsel, name) \
220 ({ struct syscall_tp *sc = evsel->priv;\
221 perf_evsel__init_tp_uint_field(evsel, &sc->name, #name); })
222
223static int perf_evsel__init_tp_ptr_field(struct perf_evsel *evsel,
224 struct tp_field *field,
225 const char *name)
226{
227 struct format_field *format_field = perf_evsel__field(evsel, name);
228
229 if (format_field == NULL)
230 return -1;
231
232 return tp_field__init_ptr(field, format_field);
233}
234
235#define perf_evsel__init_sc_tp_ptr_field(evsel, name) \
236 ({ struct syscall_tp *sc = evsel->priv;\
237 perf_evsel__init_tp_ptr_field(evsel, &sc->name, #name); })
238
239static void perf_evsel__delete_priv(struct perf_evsel *evsel)
240{
Arnaldo Carvalho de Melo04662522013-12-26 17:41:15 -0300241 zfree(&evsel->priv);
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300242 perf_evsel__delete(evsel);
243}
244
Namhyung Kim96695d42013-11-12 08:51:45 -0300245static int perf_evsel__init_syscall_tp(struct perf_evsel *evsel, void *handler)
246{
247 evsel->priv = malloc(sizeof(struct syscall_tp));
248 if (evsel->priv != NULL) {
249 if (perf_evsel__init_sc_tp_uint_field(evsel, id))
250 goto out_delete;
251
252 evsel->handler = handler;
253 return 0;
254 }
255
256 return -ENOMEM;
257
258out_delete:
Arnaldo Carvalho de Melo04662522013-12-26 17:41:15 -0300259 zfree(&evsel->priv);
Namhyung Kim96695d42013-11-12 08:51:45 -0300260 return -ENOENT;
261}
262
Arnaldo Carvalho de Meloef503832013-11-07 16:41:19 -0300263static struct perf_evsel *perf_evsel__syscall_newtp(const char *direction, void *handler)
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300264{
Arnaldo Carvalho de Meloef503832013-11-07 16:41:19 -0300265 struct perf_evsel *evsel = perf_evsel__newtp("raw_syscalls", direction);
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300266
David Ahern9aca7f12013-12-04 19:41:39 -0700267 /* older kernel (e.g., RHEL6) use syscalls:{enter,exit} */
Jiri Olsa8dd2a132015-09-07 10:38:06 +0200268 if (IS_ERR(evsel))
David Ahern9aca7f12013-12-04 19:41:39 -0700269 evsel = perf_evsel__newtp("syscalls", direction);
270
Jiri Olsa8dd2a132015-09-07 10:38:06 +0200271 if (IS_ERR(evsel))
272 return NULL;
273
274 if (perf_evsel__init_syscall_tp(evsel, handler))
275 goto out_delete;
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300276
277 return evsel;
278
279out_delete:
280 perf_evsel__delete_priv(evsel);
281 return NULL;
282}
283
284#define perf_evsel__sc_tp_uint(evsel, name, sample) \
285 ({ struct syscall_tp *fields = evsel->priv; \
286 fields->name.integer(&fields->name, sample); })
287
288#define perf_evsel__sc_tp_ptr(evsel, name, sample) \
289 ({ struct syscall_tp *fields = evsel->priv; \
290 fields->name.pointer(&fields->name, sample); })
291
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300292struct syscall_arg {
293 unsigned long val;
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300294 struct thread *thread;
295 struct trace *trace;
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300296 void *parm;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300297 u8 idx;
298 u8 mask;
299};
300
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300301struct strarray {
Arnaldo Carvalho de Melo03e3adc2013-10-08 16:00:21 -0300302 int offset;
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300303 int nr_entries;
304 const char **entries;
305};
306
307#define DEFINE_STRARRAY(array) struct strarray strarray__##array = { \
308 .nr_entries = ARRAY_SIZE(array), \
309 .entries = array, \
310}
311
Arnaldo Carvalho de Melo03e3adc2013-10-08 16:00:21 -0300312#define DEFINE_STRARRAY_OFFSET(array, off) struct strarray strarray__##array = { \
313 .offset = off, \
314 .nr_entries = ARRAY_SIZE(array), \
315 .entries = array, \
316}
317
Arnaldo Carvalho de Melo975b7c22013-10-08 17:17:43 -0300318static size_t __syscall_arg__scnprintf_strarray(char *bf, size_t size,
319 const char *intfmt,
320 struct syscall_arg *arg)
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300321{
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300322 struct strarray *sa = arg->parm;
Arnaldo Carvalho de Melo03e3adc2013-10-08 16:00:21 -0300323 int idx = arg->val - sa->offset;
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300324
325 if (idx < 0 || idx >= sa->nr_entries)
Arnaldo Carvalho de Melo975b7c22013-10-08 17:17:43 -0300326 return scnprintf(bf, size, intfmt, arg->val);
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300327
328 return scnprintf(bf, size, "%s", sa->entries[idx]);
329}
330
Arnaldo Carvalho de Melo975b7c22013-10-08 17:17:43 -0300331static size_t syscall_arg__scnprintf_strarray(char *bf, size_t size,
332 struct syscall_arg *arg)
333{
334 return __syscall_arg__scnprintf_strarray(bf, size, "%d", arg);
335}
336
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300337#define SCA_STRARRAY syscall_arg__scnprintf_strarray
338
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -0300339#if defined(__i386__) || defined(__x86_64__)
340/*
341 * FIXME: Make this available to all arches as soon as the ioctl beautifier
342 * gets rewritten to support all arches.
343 */
Arnaldo Carvalho de Melo78645cf2013-10-08 17:43:20 -0300344static size_t syscall_arg__scnprintf_strhexarray(char *bf, size_t size,
345 struct syscall_arg *arg)
346{
347 return __syscall_arg__scnprintf_strarray(bf, size, "%#x", arg);
348}
349
350#define SCA_STRHEXARRAY syscall_arg__scnprintf_strhexarray
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -0300351#endif /* defined(__i386__) || defined(__x86_64__) */
Arnaldo Carvalho de Melo78645cf2013-10-08 17:43:20 -0300352
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300353static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
354 struct syscall_arg *arg);
355
356#define SCA_FD syscall_arg__scnprintf_fd
357
358static size_t syscall_arg__scnprintf_fd_at(char *bf, size_t size,
359 struct syscall_arg *arg)
360{
361 int fd = arg->val;
362
363 if (fd == AT_FDCWD)
364 return scnprintf(bf, size, "CWD");
365
366 return syscall_arg__scnprintf_fd(bf, size, arg);
367}
368
369#define SCA_FDAT syscall_arg__scnprintf_fd_at
370
371static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
372 struct syscall_arg *arg);
373
374#define SCA_CLOSE_FD syscall_arg__scnprintf_close_fd
375
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -0300376static size_t syscall_arg__scnprintf_hex(char *bf, size_t size,
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300377 struct syscall_arg *arg)
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -0300378{
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300379 return scnprintf(bf, size, "%#lx", arg->val);
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -0300380}
381
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -0300382#define SCA_HEX syscall_arg__scnprintf_hex
383
Arnaldo Carvalho de Meloa1c25522015-06-11 22:47:54 -0300384static size_t syscall_arg__scnprintf_int(char *bf, size_t size,
385 struct syscall_arg *arg)
386{
387 return scnprintf(bf, size, "%d", arg->val);
388}
389
390#define SCA_INT syscall_arg__scnprintf_int
391
Arnaldo Carvalho de Melo5cea6ff2013-09-20 11:49:50 -0300392static size_t syscall_arg__scnprintf_flock(char *bf, size_t size,
393 struct syscall_arg *arg)
394{
395 int printed = 0, op = arg->val;
396
397 if (op == 0)
398 return scnprintf(bf, size, "NONE");
399#define P_CMD(cmd) \
400 if ((op & LOCK_##cmd) == LOCK_##cmd) { \
401 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #cmd); \
402 op &= ~LOCK_##cmd; \
403 }
404
405 P_CMD(SH);
406 P_CMD(EX);
407 P_CMD(NB);
408 P_CMD(UN);
409 P_CMD(MAND);
410 P_CMD(RW);
411 P_CMD(READ);
412 P_CMD(WRITE);
413#undef P_OP
414
415 if (op)
416 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", op);
417
418 return printed;
419}
420
421#define SCA_FLOCK syscall_arg__scnprintf_flock
422
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300423static 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 -0300424{
425 enum syscall_futex_args {
426 SCF_UADDR = (1 << 0),
427 SCF_OP = (1 << 1),
428 SCF_VAL = (1 << 2),
429 SCF_TIMEOUT = (1 << 3),
430 SCF_UADDR2 = (1 << 4),
431 SCF_VAL3 = (1 << 5),
432 };
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300433 int op = arg->val;
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -0300434 int cmd = op & FUTEX_CMD_MASK;
435 size_t printed = 0;
436
437 switch (cmd) {
438#define P_FUTEX_OP(n) case FUTEX_##n: printed = scnprintf(bf, size, #n);
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300439 P_FUTEX_OP(WAIT); arg->mask |= SCF_VAL3|SCF_UADDR2; break;
440 P_FUTEX_OP(WAKE); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
441 P_FUTEX_OP(FD); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
442 P_FUTEX_OP(REQUEUE); arg->mask |= SCF_VAL3|SCF_TIMEOUT; break;
443 P_FUTEX_OP(CMP_REQUEUE); arg->mask |= SCF_TIMEOUT; break;
444 P_FUTEX_OP(CMP_REQUEUE_PI); arg->mask |= SCF_TIMEOUT; break;
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -0300445 P_FUTEX_OP(WAKE_OP); break;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300446 P_FUTEX_OP(LOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
447 P_FUTEX_OP(UNLOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
448 P_FUTEX_OP(TRYLOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2; break;
449 P_FUTEX_OP(WAIT_BITSET); arg->mask |= SCF_UADDR2; break;
450 P_FUTEX_OP(WAKE_BITSET); arg->mask |= SCF_UADDR2; break;
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -0300451 P_FUTEX_OP(WAIT_REQUEUE_PI); break;
452 default: printed = scnprintf(bf, size, "%#x", cmd); break;
453 }
454
455 if (op & FUTEX_PRIVATE_FLAG)
456 printed += scnprintf(bf + printed, size - printed, "|PRIV");
457
458 if (op & FUTEX_CLOCK_REALTIME)
459 printed += scnprintf(bf + printed, size - printed, "|CLKRT");
460
461 return printed;
462}
463
Arnaldo Carvalho de Meloefe6b882013-09-03 16:15:12 -0300464#define SCA_FUTEX_OP syscall_arg__scnprintf_futex_op
465
Arnaldo Carvalho de Melo729a7842015-10-29 11:48:18 -0300466static const char *bpf_cmd[] = {
467 "MAP_CREATE", "MAP_LOOKUP_ELEM", "MAP_UPDATE_ELEM", "MAP_DELETE_ELEM",
468 "MAP_GET_NEXT_KEY", "PROG_LOAD",
469};
470static DEFINE_STRARRAY(bpf_cmd);
471
Arnaldo Carvalho de Melo03e3adc2013-10-08 16:00:21 -0300472static const char *epoll_ctl_ops[] = { "ADD", "DEL", "MOD", };
473static DEFINE_STRARRAY_OFFSET(epoll_ctl_ops, 1);
Arnaldo Carvalho de Meloeac032c2013-09-20 11:27:32 -0300474
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300475static const char *itimers[] = { "REAL", "VIRTUAL", "PROF", };
476static DEFINE_STRARRAY(itimers);
477
Arnaldo Carvalho de Melob62bee12015-08-11 11:05:36 -0300478static const char *keyctl_options[] = {
479 "GET_KEYRING_ID", "JOIN_SESSION_KEYRING", "UPDATE", "REVOKE", "CHOWN",
480 "SETPERM", "DESCRIBE", "CLEAR", "LINK", "UNLINK", "SEARCH", "READ",
481 "INSTANTIATE", "NEGATE", "SET_REQKEY_KEYRING", "SET_TIMEOUT",
482 "ASSUME_AUTHORITY", "GET_SECURITY", "SESSION_TO_PARENT", "REJECT",
483 "INSTANTIATE_IOV", "INVALIDATE", "GET_PERSISTENT",
484};
485static DEFINE_STRARRAY(keyctl_options);
486
Arnaldo Carvalho de Meloefe6b882013-09-03 16:15:12 -0300487static const char *whences[] = { "SET", "CUR", "END",
488#ifdef SEEK_DATA
489"DATA",
490#endif
491#ifdef SEEK_HOLE
492"HOLE",
493#endif
494};
495static DEFINE_STRARRAY(whences);
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -0300496
Arnaldo Carvalho de Melo80f587d2013-09-03 16:28:58 -0300497static const char *fcntl_cmds[] = {
498 "DUPFD", "GETFD", "SETFD", "GETFL", "SETFL", "GETLK", "SETLK",
499 "SETLKW", "SETOWN", "GETOWN", "SETSIG", "GETSIG", "F_GETLK64",
500 "F_SETLK64", "F_SETLKW64", "F_SETOWN_EX", "F_GETOWN_EX",
501 "F_GETOWNER_UIDS",
502};
503static DEFINE_STRARRAY(fcntl_cmds);
504
Arnaldo Carvalho de Meloc045bf02013-09-04 11:52:33 -0300505static const char *rlimit_resources[] = {
506 "CPU", "FSIZE", "DATA", "STACK", "CORE", "RSS", "NPROC", "NOFILE",
507 "MEMLOCK", "AS", "LOCKS", "SIGPENDING", "MSGQUEUE", "NICE", "RTPRIO",
508 "RTTIME",
509};
510static DEFINE_STRARRAY(rlimit_resources);
511
Arnaldo Carvalho de Meloeb5b1b12013-09-03 16:37:46 -0300512static const char *sighow[] = { "BLOCK", "UNBLOCK", "SETMASK", };
513static DEFINE_STRARRAY(sighow);
514
David Ahern4f8c1b72013-09-22 19:45:00 -0600515static const char *clockid[] = {
516 "REALTIME", "MONOTONIC", "PROCESS_CPUTIME_ID", "THREAD_CPUTIME_ID",
Arnaldo Carvalho de Melo28ebb872015-08-11 10:38:38 -0300517 "MONOTONIC_RAW", "REALTIME_COARSE", "MONOTONIC_COARSE", "BOOTTIME",
518 "REALTIME_ALARM", "BOOTTIME_ALARM", "SGI_CYCLE", "TAI"
David Ahern4f8c1b72013-09-22 19:45:00 -0600519};
520static DEFINE_STRARRAY(clockid);
521
Arnaldo Carvalho de Meloe10bce82013-09-04 10:27:41 -0300522static const char *socket_families[] = {
523 "UNSPEC", "LOCAL", "INET", "AX25", "IPX", "APPLETALK", "NETROM",
524 "BRIDGE", "ATMPVC", "X25", "INET6", "ROSE", "DECnet", "NETBEUI",
525 "SECURITY", "KEY", "NETLINK", "PACKET", "ASH", "ECONET", "ATMSVC",
526 "RDS", "SNA", "IRDA", "PPPOX", "WANPIPE", "LLC", "IB", "CAN", "TIPC",
527 "BLUETOOTH", "IUCV", "RXRPC", "ISDN", "PHONET", "IEEE802154", "CAIF",
528 "ALG", "NFC", "VSOCK",
529};
530static DEFINE_STRARRAY(socket_families);
531
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -0300532#ifndef MSG_PROBE
533#define MSG_PROBE 0x10
534#endif
David Ahernb6e8f8f2013-09-22 19:44:56 -0600535#ifndef MSG_WAITFORONE
536#define MSG_WAITFORONE 0x10000
537#endif
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -0300538#ifndef MSG_SENDPAGE_NOTLAST
539#define MSG_SENDPAGE_NOTLAST 0x20000
540#endif
541#ifndef MSG_FASTOPEN
542#define MSG_FASTOPEN 0x20000000
543#endif
544
545static size_t syscall_arg__scnprintf_msg_flags(char *bf, size_t size,
546 struct syscall_arg *arg)
547{
548 int printed = 0, flags = arg->val;
549
550 if (flags == 0)
551 return scnprintf(bf, size, "NONE");
552#define P_MSG_FLAG(n) \
553 if (flags & MSG_##n) { \
554 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
555 flags &= ~MSG_##n; \
556 }
557
558 P_MSG_FLAG(OOB);
559 P_MSG_FLAG(PEEK);
560 P_MSG_FLAG(DONTROUTE);
561 P_MSG_FLAG(TRYHARD);
562 P_MSG_FLAG(CTRUNC);
563 P_MSG_FLAG(PROBE);
564 P_MSG_FLAG(TRUNC);
565 P_MSG_FLAG(DONTWAIT);
566 P_MSG_FLAG(EOR);
567 P_MSG_FLAG(WAITALL);
568 P_MSG_FLAG(FIN);
569 P_MSG_FLAG(SYN);
570 P_MSG_FLAG(CONFIRM);
571 P_MSG_FLAG(RST);
572 P_MSG_FLAG(ERRQUEUE);
573 P_MSG_FLAG(NOSIGNAL);
574 P_MSG_FLAG(MORE);
575 P_MSG_FLAG(WAITFORONE);
576 P_MSG_FLAG(SENDPAGE_NOTLAST);
577 P_MSG_FLAG(FASTOPEN);
578 P_MSG_FLAG(CMSG_CLOEXEC);
579#undef P_MSG_FLAG
580
581 if (flags)
582 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
583
584 return printed;
585}
586
587#define SCA_MSG_FLAGS syscall_arg__scnprintf_msg_flags
588
Arnaldo Carvalho de Melo51108992013-09-04 11:42:27 -0300589static size_t syscall_arg__scnprintf_access_mode(char *bf, size_t size,
590 struct syscall_arg *arg)
591{
592 size_t printed = 0;
593 int mode = arg->val;
594
595 if (mode == F_OK) /* 0 */
596 return scnprintf(bf, size, "F");
597#define P_MODE(n) \
598 if (mode & n##_OK) { \
599 printed += scnprintf(bf + printed, size - printed, "%s", #n); \
600 mode &= ~n##_OK; \
601 }
602
603 P_MODE(R);
604 P_MODE(W);
605 P_MODE(X);
606#undef P_MODE
607
608 if (mode)
609 printed += scnprintf(bf + printed, size - printed, "|%#x", mode);
610
611 return printed;
612}
613
614#define SCA_ACCMODE syscall_arg__scnprintf_access_mode
615
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -0300616static size_t syscall_arg__scnprintf_filename(char *bf, size_t size,
617 struct syscall_arg *arg);
618
619#define SCA_FILENAME syscall_arg__scnprintf_filename
620
Arnaldo Carvalho de Melobe65a892013-09-02 16:22:31 -0300621static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300622 struct syscall_arg *arg)
Arnaldo Carvalho de Melobe65a892013-09-02 16:22:31 -0300623{
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300624 int printed = 0, flags = arg->val;
Arnaldo Carvalho de Melobe65a892013-09-02 16:22:31 -0300625
626 if (!(flags & O_CREAT))
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300627 arg->mask |= 1 << (arg->idx + 1); /* Mask the mode parm */
Arnaldo Carvalho de Melobe65a892013-09-02 16:22:31 -0300628
629 if (flags == 0)
630 return scnprintf(bf, size, "RDONLY");
631#define P_FLAG(n) \
632 if (flags & O_##n) { \
633 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
634 flags &= ~O_##n; \
635 }
636
637 P_FLAG(APPEND);
638 P_FLAG(ASYNC);
639 P_FLAG(CLOEXEC);
640 P_FLAG(CREAT);
641 P_FLAG(DIRECT);
642 P_FLAG(DIRECTORY);
643 P_FLAG(EXCL);
644 P_FLAG(LARGEFILE);
645 P_FLAG(NOATIME);
646 P_FLAG(NOCTTY);
647#ifdef O_NONBLOCK
648 P_FLAG(NONBLOCK);
649#elif O_NDELAY
650 P_FLAG(NDELAY);
651#endif
652#ifdef O_PATH
653 P_FLAG(PATH);
654#endif
655 P_FLAG(RDWR);
656#ifdef O_DSYNC
657 if ((flags & O_SYNC) == O_SYNC)
658 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", "SYNC");
659 else {
660 P_FLAG(DSYNC);
661 }
662#else
663 P_FLAG(SYNC);
664#endif
665 P_FLAG(TRUNC);
666 P_FLAG(WRONLY);
667#undef P_FLAG
668
669 if (flags)
670 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
671
672 return printed;
673}
674
675#define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags
676
Arnaldo Carvalho de Meloa1c25522015-06-11 22:47:54 -0300677static size_t syscall_arg__scnprintf_perf_flags(char *bf, size_t size,
678 struct syscall_arg *arg)
679{
680 int printed = 0, flags = arg->val;
681
682 if (flags == 0)
683 return 0;
684
685#define P_FLAG(n) \
686 if (flags & PERF_FLAG_##n) { \
687 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
688 flags &= ~PERF_FLAG_##n; \
689 }
690
691 P_FLAG(FD_NO_GROUP);
692 P_FLAG(FD_OUTPUT);
693 P_FLAG(PID_CGROUP);
694 P_FLAG(FD_CLOEXEC);
695#undef P_FLAG
696
697 if (flags)
698 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
699
700 return printed;
701}
702
703#define SCA_PERF_FLAGS syscall_arg__scnprintf_perf_flags
704
Arnaldo Carvalho de Melo46cce192013-09-23 12:52:04 -0300705static size_t syscall_arg__scnprintf_pipe_flags(char *bf, size_t size,
706 struct syscall_arg *arg)
707{
708 int printed = 0, flags = arg->val;
709
710#define P_FLAG(n) \
711 if (flags & O_##n) { \
712 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
713 flags &= ~O_##n; \
714 }
715
716 P_FLAG(CLOEXEC);
717 P_FLAG(NONBLOCK);
718#undef P_FLAG
719
720 if (flags)
721 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
722
723 return printed;
724}
725
726#define SCA_PIPE_FLAGS syscall_arg__scnprintf_pipe_flags
727
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -0300728static size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscall_arg *arg)
729{
730 int sig = arg->val;
731
732 switch (sig) {
733#define P_SIGNUM(n) case SIG##n: return scnprintf(bf, size, #n)
734 P_SIGNUM(HUP);
735 P_SIGNUM(INT);
736 P_SIGNUM(QUIT);
737 P_SIGNUM(ILL);
738 P_SIGNUM(TRAP);
739 P_SIGNUM(ABRT);
740 P_SIGNUM(BUS);
741 P_SIGNUM(FPE);
742 P_SIGNUM(KILL);
743 P_SIGNUM(USR1);
744 P_SIGNUM(SEGV);
745 P_SIGNUM(USR2);
746 P_SIGNUM(PIPE);
747 P_SIGNUM(ALRM);
748 P_SIGNUM(TERM);
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -0300749 P_SIGNUM(CHLD);
750 P_SIGNUM(CONT);
751 P_SIGNUM(STOP);
752 P_SIGNUM(TSTP);
753 P_SIGNUM(TTIN);
754 P_SIGNUM(TTOU);
755 P_SIGNUM(URG);
756 P_SIGNUM(XCPU);
757 P_SIGNUM(XFSZ);
758 P_SIGNUM(VTALRM);
759 P_SIGNUM(PROF);
760 P_SIGNUM(WINCH);
761 P_SIGNUM(IO);
762 P_SIGNUM(PWR);
763 P_SIGNUM(SYS);
Ben Hutchings02c5bb42014-02-06 01:00:41 +0000764#ifdef SIGEMT
765 P_SIGNUM(EMT);
766#endif
767#ifdef SIGSTKFLT
768 P_SIGNUM(STKFLT);
769#endif
770#ifdef SIGSWI
771 P_SIGNUM(SWI);
772#endif
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -0300773 default: break;
774 }
775
776 return scnprintf(bf, size, "%#x", sig);
777}
778
779#define SCA_SIGNUM syscall_arg__scnprintf_signum
780
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -0300781#if defined(__i386__) || defined(__x86_64__)
782/*
783 * FIXME: Make this available to all arches.
784 */
Arnaldo Carvalho de Melo78645cf2013-10-08 17:43:20 -0300785#define TCGETS 0x5401
786
787static const char *tioctls[] = {
788 "TCGETS", "TCSETS", "TCSETSW", "TCSETSF", "TCGETA", "TCSETA", "TCSETAW",
789 "TCSETAF", "TCSBRK", "TCXONC", "TCFLSH", "TIOCEXCL", "TIOCNXCL",
790 "TIOCSCTTY", "TIOCGPGRP", "TIOCSPGRP", "TIOCOUTQ", "TIOCSTI",
791 "TIOCGWINSZ", "TIOCSWINSZ", "TIOCMGET", "TIOCMBIS", "TIOCMBIC",
792 "TIOCMSET", "TIOCGSOFTCAR", "TIOCSSOFTCAR", "FIONREAD", "TIOCLINUX",
793 "TIOCCONS", "TIOCGSERIAL", "TIOCSSERIAL", "TIOCPKT", "FIONBIO",
794 "TIOCNOTTY", "TIOCSETD", "TIOCGETD", "TCSBRKP", [0x27] = "TIOCSBRK",
795 "TIOCCBRK", "TIOCGSID", "TCGETS2", "TCSETS2", "TCSETSW2", "TCSETSF2",
796 "TIOCGRS485", "TIOCSRS485", "TIOCGPTN", "TIOCSPTLCK",
797 "TIOCGDEV||TCGETX", "TCSETX", "TCSETXF", "TCSETXW", "TIOCSIG",
798 "TIOCVHANGUP", "TIOCGPKT", "TIOCGPTLCK", "TIOCGEXCL",
799 [0x50] = "FIONCLEX", "FIOCLEX", "FIOASYNC", "TIOCSERCONFIG",
800 "TIOCSERGWILD", "TIOCSERSWILD", "TIOCGLCKTRMIOS", "TIOCSLCKTRMIOS",
801 "TIOCSERGSTRUCT", "TIOCSERGETLSR", "TIOCSERGETMULTI", "TIOCSERSETMULTI",
802 "TIOCMIWAIT", "TIOCGICOUNT", [0x60] = "FIOQSIZE",
803};
804
805static DEFINE_STRARRAY_OFFSET(tioctls, 0x5401);
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -0300806#endif /* defined(__i386__) || defined(__x86_64__) */
Arnaldo Carvalho de Melo78645cf2013-10-08 17:43:20 -0300807
Arnaldo Carvalho de Melo6fb35b92016-04-13 11:50:23 -0300808#ifndef SECCOMP_SET_MODE_STRICT
809#define SECCOMP_SET_MODE_STRICT 0
810#endif
811#ifndef SECCOMP_SET_MODE_FILTER
812#define SECCOMP_SET_MODE_FILTER 1
813#endif
814
Arnaldo Carvalho de Melo997bba82016-03-30 19:43:32 -0300815static size_t syscall_arg__scnprintf_seccomp_op(char *bf, size_t size, struct syscall_arg *arg)
816{
817 int op = arg->val;
818 size_t printed = 0;
819
820 switch (op) {
821#define P_SECCOMP_SET_MODE_OP(n) case SECCOMP_SET_MODE_##n: printed = scnprintf(bf, size, #n); break
822 P_SECCOMP_SET_MODE_OP(STRICT);
823 P_SECCOMP_SET_MODE_OP(FILTER);
824#undef P_SECCOMP_SET_MODE_OP
825 default: printed = scnprintf(bf, size, "%#x", op); break;
826 }
827
828 return printed;
829}
830
831#define SCA_SECCOMP_OP syscall_arg__scnprintf_seccomp_op
832
Arnaldo Carvalho de Melo6fb35b92016-04-13 11:50:23 -0300833#ifndef SECCOMP_FILTER_FLAG_TSYNC
834#define SECCOMP_FILTER_FLAG_TSYNC 1
835#endif
836
Arnaldo Carvalho de Melo997bba82016-03-30 19:43:32 -0300837static size_t syscall_arg__scnprintf_seccomp_flags(char *bf, size_t size,
838 struct syscall_arg *arg)
839{
840 int printed = 0, flags = arg->val;
841
842#define P_FLAG(n) \
843 if (flags & SECCOMP_FILTER_FLAG_##n) { \
844 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
845 flags &= ~SECCOMP_FILTER_FLAG_##n; \
846 }
847
848 P_FLAG(TSYNC);
849#undef P_FLAG
850
851 if (flags)
852 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
853
854 return printed;
855}
856
857#define SCA_SECCOMP_FLAGS syscall_arg__scnprintf_seccomp_flags
858
Arnaldo Carvalho de Meloa355a612016-04-13 11:55:18 -0300859#ifndef GRND_NONBLOCK
860#define GRND_NONBLOCK 0x0001
861#endif
862#ifndef GRND_RANDOM
863#define GRND_RANDOM 0x0002
864#endif
865
Arnaldo Carvalho de Melo39878d42016-03-30 20:02:15 -0300866static size_t syscall_arg__scnprintf_getrandom_flags(char *bf, size_t size,
867 struct syscall_arg *arg)
868{
869 int printed = 0, flags = arg->val;
870
871#define P_FLAG(n) \
872 if (flags & GRND_##n) { \
873 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
874 flags &= ~GRND_##n; \
875 }
876
877 P_FLAG(RANDOM);
878 P_FLAG(NONBLOCK);
879#undef P_FLAG
880
881 if (flags)
882 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
883
884 return printed;
885}
886
887#define SCA_GETRANDOM_FLAGS syscall_arg__scnprintf_getrandom_flags
888
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300889#define STRARRAY(arg, name, array) \
890 .arg_scnprintf = { [arg] = SCA_STRARRAY, }, \
891 .arg_parm = { [arg] = &strarray__##array, }
892
Arnaldo Carvalho de Meloea8dc3c2016-04-13 12:10:19 -0300893#include "trace/beauty/eventfd.c"
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -0300894#include "trace/beauty/pid.c"
Arnaldo Carvalho de Melodf4cb162016-04-13 12:05:44 -0300895#include "trace/beauty/mmap.c"
Arnaldo Carvalho de Meloba2f22c2016-04-07 12:05:51 -0300896#include "trace/beauty/mode_t.c"
Arnaldo Carvalho de Meloa3bca912016-04-06 12:51:33 -0300897#include "trace/beauty/sched_policy.c"
Arnaldo Carvalho de Melobbf86c42016-04-14 13:53:10 -0300898#include "trace/beauty/socket_type.c"
Arnaldo Carvalho de Melo7206b902016-04-06 14:11:36 -0300899#include "trace/beauty/waitid_options.c"
Arnaldo Carvalho de Meloa3bca912016-04-06 12:51:33 -0300900
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300901static struct syscall_fmt {
902 const char *name;
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -0300903 const char *alias;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300904 size_t (*arg_scnprintf[6])(char *bf, size_t size, struct syscall_arg *arg);
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300905 void *arg_parm[6];
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300906 bool errmsg;
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -0300907 bool errpid;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300908 bool timeout;
Arnaldo Carvalho de Melo04b34722013-08-26 11:36:30 -0300909 bool hexret;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300910} syscall_fmts[] = {
Arnaldo Carvalho de Melo51108992013-09-04 11:42:27 -0300911 { .name = "access", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300912 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */
913 [1] = SCA_ACCMODE, /* mode */ }, },
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -0300914 { .name = "arch_prctl", .errmsg = true, .alias = "prctl", },
Arnaldo Carvalho de Melo729a7842015-10-29 11:48:18 -0300915 { .name = "bpf", .errmsg = true, STRARRAY(0, cmd, bpf_cmd), },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -0300916 { .name = "brk", .hexret = true,
917 .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300918 { .name = "chdir", .errmsg = true,
919 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
920 { .name = "chmod", .errmsg = true,
921 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
922 { .name = "chroot", .errmsg = true,
923 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
David Ahern4f8c1b72013-09-22 19:45:00 -0600924 { .name = "clock_gettime", .errmsg = true, STRARRAY(0, clk_id, clockid), },
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -0300925 { .name = "clone", .errpid = true, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300926 { .name = "close", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300927 .arg_scnprintf = { [0] = SCA_CLOSE_FD, /* fd */ }, },
Arnaldo Carvalho de Meloa14bb862013-07-30 16:38:23 -0300928 { .name = "connect", .errmsg = true, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300929 { .name = "creat", .errmsg = true,
930 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300931 { .name = "dup", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300932 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300933 { .name = "dup2", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300934 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300935 { .name = "dup3", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300936 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300937 { .name = "epoll_ctl", .errmsg = true, STRARRAY(1, op, epoll_ctl_ops), },
Arnaldo Carvalho de Melo49af9e92013-09-12 12:18:56 -0300938 { .name = "eventfd2", .errmsg = true,
939 .arg_scnprintf = { [1] = SCA_EFD_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300940 { .name = "faccessat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300941 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
942 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300943 { .name = "fadvise64", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300944 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300945 { .name = "fallocate", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300946 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300947 { .name = "fchdir", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300948 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300949 { .name = "fchmod", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300950 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300951 { .name = "fchmodat", .errmsg = true,
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -0300952 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */
953 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300954 { .name = "fchown", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300955 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300956 { .name = "fchownat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300957 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */
958 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300959 { .name = "fcntl", .errmsg = true,
960 .arg_scnprintf = { [0] = SCA_FD, /* fd */
961 [1] = SCA_STRARRAY, /* cmd */ },
962 .arg_parm = { [1] = &strarray__fcntl_cmds, /* cmd */ }, },
963 { .name = "fdatasync", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300964 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo5cea6ff2013-09-20 11:49:50 -0300965 { .name = "flock", .errmsg = true,
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300966 .arg_scnprintf = { [0] = SCA_FD, /* fd */
967 [1] = SCA_FLOCK, /* cmd */ }, },
968 { .name = "fsetxattr", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300969 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300970 { .name = "fstat", .errmsg = true, .alias = "newfstat",
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300971 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300972 { .name = "fstatat", .errmsg = true, .alias = "newfstatat",
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300973 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
974 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300975 { .name = "fstatfs", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300976 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300977 { .name = "fsync", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300978 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300979 { .name = "ftruncate", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300980 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -0300981 { .name = "futex", .errmsg = true,
982 .arg_scnprintf = { [1] = SCA_FUTEX_OP, /* op */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300983 { .name = "futimesat", .errmsg = true,
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -0300984 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */
985 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300986 { .name = "getdents", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300987 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300988 { .name = "getdents64", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300989 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300990 { .name = "getitimer", .errmsg = true, STRARRAY(0, which, itimers), },
Arnaldo Carvalho de Meloc65f1072016-04-06 14:55:18 -0300991 { .name = "getpid", .errpid = true, },
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -0300992 { .name = "getpgid", .errpid = true, },
Arnaldo Carvalho de Meloc65f1072016-04-06 14:55:18 -0300993 { .name = "getppid", .errpid = true, },
Arnaldo Carvalho de Melo39878d42016-03-30 20:02:15 -0300994 { .name = "getrandom", .errmsg = true,
995 .arg_scnprintf = { [2] = SCA_GETRANDOM_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300996 { .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300997 { .name = "getxattr", .errmsg = true,
998 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
999 { .name = "inotify_add_watch", .errmsg = true,
1000 .arg_scnprintf = { [1] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -03001001 { .name = "ioctl", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001002 .arg_scnprintf = { [0] = SCA_FD, /* fd */
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -03001003#if defined(__i386__) || defined(__x86_64__)
1004/*
1005 * FIXME: Make this available to all arches.
1006 */
Arnaldo Carvalho de Melo78645cf2013-10-08 17:43:20 -03001007 [1] = SCA_STRHEXARRAY, /* cmd */
1008 [2] = SCA_HEX, /* arg */ },
1009 .arg_parm = { [1] = &strarray__tioctls, /* cmd */ }, },
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -03001010#else
1011 [2] = SCA_HEX, /* arg */ }, },
1012#endif
Arnaldo Carvalho de Melob62bee12015-08-11 11:05:36 -03001013 { .name = "keyctl", .errmsg = true, STRARRAY(0, option, keyctl_options), },
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -03001014 { .name = "kill", .errmsg = true,
1015 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001016 { .name = "lchown", .errmsg = true,
1017 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
1018 { .name = "lgetxattr", .errmsg = true,
1019 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001020 { .name = "linkat", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001021 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001022 { .name = "listxattr", .errmsg = true,
1023 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -03001024 { .name = "llistxattr", .errmsg = true,
1025 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
1026 { .name = "lremovexattr", .errmsg = true,
1027 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001028 { .name = "lseek", .errmsg = true,
1029 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1030 [2] = SCA_STRARRAY, /* whence */ },
1031 .arg_parm = { [2] = &strarray__whences, /* whence */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001032 { .name = "lsetxattr", .errmsg = true,
1033 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -03001034 { .name = "lstat", .errmsg = true, .alias = "newlstat",
1035 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001036 { .name = "lsxattr", .errmsg = true,
1037 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo9e9716d2013-08-23 10:06:41 -03001038 { .name = "madvise", .errmsg = true,
1039 .arg_scnprintf = { [0] = SCA_HEX, /* start */
1040 [2] = SCA_MADV_BHV, /* behavior */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001041 { .name = "mkdir", .errmsg = true,
1042 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001043 { .name = "mkdirat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001044 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */
1045 [1] = SCA_FILENAME, /* pathname */ }, },
1046 { .name = "mknod", .errmsg = true,
1047 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001048 { .name = "mknodat", .errmsg = true,
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -03001049 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */
1050 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo3d903aa2013-09-24 00:09:38 -03001051 { .name = "mlock", .errmsg = true,
1052 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
1053 { .name = "mlockall", .errmsg = true,
1054 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -03001055 { .name = "mmap", .hexret = true,
Arnaldo Carvalho de Meloae685382013-08-20 17:44:42 -03001056 .arg_scnprintf = { [0] = SCA_HEX, /* addr */
Arnaldo Carvalho de Melo941557e2013-08-23 10:48:33 -03001057 [2] = SCA_MMAP_PROT, /* prot */
Namhyung Kim73faab32013-11-12 15:24:59 +09001058 [3] = SCA_MMAP_FLAGS, /* flags */
1059 [4] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -03001060 { .name = "mprotect", .errmsg = true,
Arnaldo Carvalho de Meloae685382013-08-20 17:44:42 -03001061 .arg_scnprintf = { [0] = SCA_HEX, /* start */
1062 [2] = SCA_MMAP_PROT, /* prot */ }, },
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -03001063 { .name = "mq_unlink", .errmsg = true,
1064 .arg_scnprintf = { [0] = SCA_FILENAME, /* u_name */ }, },
Arnaldo Carvalho de Meloae685382013-08-20 17:44:42 -03001065 { .name = "mremap", .hexret = true,
1066 .arg_scnprintf = { [0] = SCA_HEX, /* addr */
Alex Snast86998dd2014-08-13 18:42:40 +03001067 [3] = SCA_MREMAP_FLAGS, /* flags */
Arnaldo Carvalho de Meloae685382013-08-20 17:44:42 -03001068 [4] = SCA_HEX, /* new_addr */ }, },
Arnaldo Carvalho de Melo3d903aa2013-09-24 00:09:38 -03001069 { .name = "munlock", .errmsg = true,
1070 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -03001071 { .name = "munmap", .errmsg = true,
1072 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001073 { .name = "name_to_handle_at", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001074 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001075 { .name = "newfstatat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001076 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
1077 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melobe65a892013-09-02 16:22:31 -03001078 { .name = "open", .errmsg = true,
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001079 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */
1080 [1] = SCA_OPEN_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo31cd3852013-09-02 16:40:40 -03001081 { .name = "open_by_handle_at", .errmsg = true,
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001082 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
1083 [2] = SCA_OPEN_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo31cd3852013-09-02 16:40:40 -03001084 { .name = "openat", .errmsg = true,
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001085 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001086 [1] = SCA_FILENAME, /* filename */
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001087 [2] = SCA_OPEN_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Meloa1c25522015-06-11 22:47:54 -03001088 { .name = "perf_event_open", .errmsg = true,
1089 .arg_scnprintf = { [1] = SCA_INT, /* pid */
1090 [2] = SCA_INT, /* cpu */
1091 [3] = SCA_FD, /* group_fd */
1092 [4] = SCA_PERF_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo46cce192013-09-23 12:52:04 -03001093 { .name = "pipe2", .errmsg = true,
1094 .arg_scnprintf = { [1] = SCA_PIPE_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -03001095 { .name = "poll", .errmsg = true, .timeout = true, },
1096 { .name = "ppoll", .errmsg = true, .timeout = true, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001097 { .name = "pread", .errmsg = true, .alias = "pread64",
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 = "preadv", .errmsg = true, .alias = "pread",
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001100 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -03001101 { .name = "prlimit64", .errmsg = true, STRARRAY(1, resource, rlimit_resources), },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001102 { .name = "pwrite", .errmsg = true, .alias = "pwrite64",
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001103 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001104 { .name = "pwritev", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001105 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001106 { .name = "read", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001107 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001108 { .name = "readlink", .errmsg = true,
1109 .arg_scnprintf = { [0] = SCA_FILENAME, /* path */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001110 { .name = "readlinkat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001111 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
1112 [1] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001113 { .name = "readv", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001114 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -03001115 { .name = "recvfrom", .errmsg = true,
Arnaldo Carvalho de Melo8d8c66a2015-08-11 10:57:02 -03001116 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1117 [3] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -03001118 { .name = "recvmmsg", .errmsg = true,
Arnaldo Carvalho de Melo8d8c66a2015-08-11 10:57:02 -03001119 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1120 [3] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -03001121 { .name = "recvmsg", .errmsg = true,
Arnaldo Carvalho de Melo8d8c66a2015-08-11 10:57:02 -03001122 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1123 [2] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001124 { .name = "removexattr", .errmsg = true,
1125 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001126 { .name = "renameat", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001127 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001128 { .name = "rmdir", .errmsg = true,
1129 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -03001130 { .name = "rt_sigaction", .errmsg = true,
1131 .arg_scnprintf = { [0] = SCA_SIGNUM, /* sig */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -03001132 { .name = "rt_sigprocmask", .errmsg = true, STRARRAY(0, how, sighow), },
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -03001133 { .name = "rt_sigqueueinfo", .errmsg = true,
1134 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
1135 { .name = "rt_tgsigqueueinfo", .errmsg = true,
1136 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
Arnaldo Carvalho de Meloa3bca912016-04-06 12:51:33 -03001137 { .name = "sched_setscheduler", .errmsg = true,
1138 .arg_scnprintf = { [1] = SCA_SCHED_POLICY, /* policy */ }, },
Arnaldo Carvalho de Melo997bba82016-03-30 19:43:32 -03001139 { .name = "seccomp", .errmsg = true,
1140 .arg_scnprintf = { [0] = SCA_SECCOMP_OP, /* op */
1141 [1] = SCA_SECCOMP_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -03001142 { .name = "select", .errmsg = true, .timeout = true, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -03001143 { .name = "sendmmsg", .errmsg = true,
Arnaldo Carvalho de Melo8d8c66a2015-08-11 10:57:02 -03001144 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1145 [3] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -03001146 { .name = "sendmsg", .errmsg = true,
Arnaldo Carvalho de Melo8d8c66a2015-08-11 10:57:02 -03001147 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1148 [2] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -03001149 { .name = "sendto", .errmsg = true,
Arnaldo Carvalho de Melo8d8c66a2015-08-11 10:57:02 -03001150 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1151 [3] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Meloc65f1072016-04-06 14:55:18 -03001152 { .name = "set_tid_address", .errpid = true, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -03001153 { .name = "setitimer", .errmsg = true, STRARRAY(0, which, itimers), },
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -03001154 { .name = "setpgid", .errmsg = true, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -03001155 { .name = "setrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001156 { .name = "setxattr", .errmsg = true,
1157 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001158 { .name = "shutdown", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001159 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Meloe10bce82013-09-04 10:27:41 -03001160 { .name = "socket", .errmsg = true,
Arnaldo Carvalho de Meloa28b24b2013-09-04 11:00:44 -03001161 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
1162 [1] = SCA_SK_TYPE, /* type */ },
Arnaldo Carvalho de Meloe10bce82013-09-04 10:27:41 -03001163 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, },
Arnaldo Carvalho de Melo07120aa2013-09-20 12:24:20 -03001164 { .name = "socketpair", .errmsg = true,
1165 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
1166 [1] = SCA_SK_TYPE, /* type */ },
1167 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, },
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -03001168 { .name = "stat", .errmsg = true, .alias = "newstat",
1169 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001170 { .name = "statfs", .errmsg = true,
1171 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
1172 { .name = "swapoff", .errmsg = true,
1173 .arg_scnprintf = { [0] = SCA_FILENAME, /* specialfile */ }, },
1174 { .name = "swapon", .errmsg = true,
1175 .arg_scnprintf = { [0] = SCA_FILENAME, /* specialfile */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001176 { .name = "symlinkat", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001177 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -03001178 { .name = "tgkill", .errmsg = true,
1179 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
1180 { .name = "tkill", .errmsg = true,
1181 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001182 { .name = "truncate", .errmsg = true,
1183 .arg_scnprintf = { [0] = SCA_FILENAME, /* path */ }, },
Arnaldo Carvalho de Meloe5959682013-08-26 12:21:41 -03001184 { .name = "uname", .errmsg = true, .alias = "newuname", },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001185 { .name = "unlinkat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001186 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
1187 [1] = SCA_FILENAME, /* pathname */ }, },
1188 { .name = "utime", .errmsg = true,
1189 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001190 { .name = "utimensat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001191 .arg_scnprintf = { [0] = SCA_FDAT, /* dirfd */
1192 [1] = SCA_FILENAME, /* filename */ }, },
1193 { .name = "utimes", .errmsg = true,
1194 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -03001195 { .name = "vmsplice", .errmsg = true,
1196 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -03001197 { .name = "wait4", .errpid = true,
Arnaldo Carvalho de Melo7206b902016-04-06 14:11:36 -03001198 .arg_scnprintf = { [2] = SCA_WAITID_OPTIONS, /* options */ }, },
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -03001199 { .name = "waitid", .errpid = true,
Arnaldo Carvalho de Melo7206b902016-04-06 14:11:36 -03001200 .arg_scnprintf = { [3] = SCA_WAITID_OPTIONS, /* options */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001201 { .name = "write", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001202 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001203 { .name = "writev", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001204 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001205};
1206
1207static int syscall_fmt__cmp(const void *name, const void *fmtp)
1208{
1209 const struct syscall_fmt *fmt = fmtp;
1210 return strcmp(name, fmt->name);
1211}
1212
1213static struct syscall_fmt *syscall_fmt__find(const char *name)
1214{
1215 const int nmemb = ARRAY_SIZE(syscall_fmts);
1216 return bsearch(name, syscall_fmts, nmemb, sizeof(struct syscall_fmt), syscall_fmt__cmp);
1217}
1218
1219struct syscall {
1220 struct event_format *tp_format;
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001221 int nr_args;
1222 struct format_field *args;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001223 const char *name;
Arnaldo Carvalho de Melo5089f202014-06-17 14:29:24 -03001224 bool is_exit;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001225 struct syscall_fmt *fmt;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001226 size_t (**arg_scnprintf)(char *bf, size_t size, struct syscall_arg *arg);
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -03001227 void **arg_parm;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001228};
1229
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001230static size_t fprintf_duration(unsigned long t, FILE *fp)
1231{
1232 double duration = (double)t / NSEC_PER_MSEC;
1233 size_t printed = fprintf(fp, "(");
1234
1235 if (duration >= 1.0)
1236 printed += color_fprintf(fp, PERF_COLOR_RED, "%6.3f ms", duration);
1237 else if (duration >= 0.01)
1238 printed += color_fprintf(fp, PERF_COLOR_YELLOW, "%6.3f ms", duration);
1239 else
1240 printed += color_fprintf(fp, PERF_COLOR_NORMAL, "%6.3f ms", duration);
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001241 return printed + fprintf(fp, "): ");
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001242}
1243
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001244/**
1245 * filename.ptr: The filename char pointer that will be vfs_getname'd
1246 * filename.entry_str_pos: Where to insert the string translated from
1247 * filename.ptr by the vfs_getname tracepoint/kprobe.
1248 */
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001249struct thread_trace {
1250 u64 entry_time;
1251 u64 exit_time;
1252 bool entry_pending;
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03001253 unsigned long nr_events;
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04001254 unsigned long pfmaj, pfmin;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001255 char *entry_str;
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001256 double runtime_ms;
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001257 struct {
1258 unsigned long ptr;
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03001259 short int entry_str_pos;
1260 bool pending_open;
1261 unsigned int namelen;
1262 char *name;
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001263 } filename;
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001264 struct {
1265 int max;
1266 char **table;
1267 } paths;
David Ahernbf2575c2013-10-08 21:26:53 -06001268
1269 struct intlist *syscall_stats;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001270};
1271
1272static struct thread_trace *thread_trace__new(void)
1273{
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001274 struct thread_trace *ttrace = zalloc(sizeof(struct thread_trace));
1275
1276 if (ttrace)
1277 ttrace->paths.max = -1;
1278
David Ahernbf2575c2013-10-08 21:26:53 -06001279 ttrace->syscall_stats = intlist__new(NULL);
1280
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001281 return ttrace;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001282}
1283
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001284static struct thread_trace *thread__trace(struct thread *thread, FILE *fp)
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001285{
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03001286 struct thread_trace *ttrace;
1287
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001288 if (thread == NULL)
1289 goto fail;
1290
Namhyung Kim89dceb22014-10-06 09:46:03 +09001291 if (thread__priv(thread) == NULL)
1292 thread__set_priv(thread, thread_trace__new());
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001293
Namhyung Kim89dceb22014-10-06 09:46:03 +09001294 if (thread__priv(thread) == NULL)
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001295 goto fail;
1296
Namhyung Kim89dceb22014-10-06 09:46:03 +09001297 ttrace = thread__priv(thread);
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03001298 ++ttrace->nr_events;
1299
1300 return ttrace;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001301fail:
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001302 color_fprintf(fp, PERF_COLOR_RED,
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001303 "WARNING: not enough memory, dropping samples!\n");
1304 return NULL;
1305}
1306
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04001307#define TRACE_PFMAJ (1 << 0)
1308#define TRACE_PFMIN (1 << 1)
1309
Arnaldo Carvalho de Meloe4d44e82015-08-04 22:17:29 -03001310static const size_t trace__entry_str_size = 2048;
1311
Arnaldo Carvalho de Melo97119f32013-09-27 17:34:10 -03001312static int trace__set_fd_pathname(struct thread *thread, int fd, const char *pathname)
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001313{
Namhyung Kim89dceb22014-10-06 09:46:03 +09001314 struct thread_trace *ttrace = thread__priv(thread);
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001315
1316 if (fd > ttrace->paths.max) {
1317 char **npath = realloc(ttrace->paths.table, (fd + 1) * sizeof(char *));
1318
1319 if (npath == NULL)
1320 return -1;
1321
1322 if (ttrace->paths.max != -1) {
1323 memset(npath + ttrace->paths.max + 1, 0,
1324 (fd - ttrace->paths.max) * sizeof(char *));
1325 } else {
1326 memset(npath, 0, (fd + 1) * sizeof(char *));
1327 }
1328
1329 ttrace->paths.table = npath;
1330 ttrace->paths.max = fd;
1331 }
1332
1333 ttrace->paths.table[fd] = strdup(pathname);
1334
1335 return ttrace->paths.table[fd] != NULL ? 0 : -1;
1336}
1337
Arnaldo Carvalho de Melo97119f32013-09-27 17:34:10 -03001338static int thread__read_fd_path(struct thread *thread, int fd)
1339{
1340 char linkname[PATH_MAX], pathname[PATH_MAX];
1341 struct stat st;
1342 int ret;
1343
1344 if (thread->pid_ == thread->tid) {
1345 scnprintf(linkname, sizeof(linkname),
1346 "/proc/%d/fd/%d", thread->pid_, fd);
1347 } else {
1348 scnprintf(linkname, sizeof(linkname),
1349 "/proc/%d/task/%d/fd/%d", thread->pid_, thread->tid, fd);
1350 }
1351
1352 if (lstat(linkname, &st) < 0 || st.st_size + 1 > (off_t)sizeof(pathname))
1353 return -1;
1354
1355 ret = readlink(linkname, pathname, sizeof(pathname));
1356
1357 if (ret < 0 || ret > st.st_size)
1358 return -1;
1359
1360 pathname[ret] = '\0';
1361 return trace__set_fd_pathname(thread, fd, pathname);
1362}
1363
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001364static const char *thread__fd_path(struct thread *thread, int fd,
1365 struct trace *trace)
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001366{
Namhyung Kim89dceb22014-10-06 09:46:03 +09001367 struct thread_trace *ttrace = thread__priv(thread);
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001368
1369 if (ttrace == NULL)
1370 return NULL;
1371
1372 if (fd < 0)
1373 return NULL;
1374
Arnaldo Carvalho de Melocdcd1e62014-06-10 16:00:18 -03001375 if ((fd > ttrace->paths.max || ttrace->paths.table[fd] == NULL)) {
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001376 if (!trace->live)
1377 return NULL;
1378 ++trace->stats.proc_getname;
Arnaldo Carvalho de Melocdcd1e62014-06-10 16:00:18 -03001379 if (thread__read_fd_path(thread, fd))
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001380 return NULL;
1381 }
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001382
1383 return ttrace->paths.table[fd];
1384}
1385
1386static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
1387 struct syscall_arg *arg)
1388{
1389 int fd = arg->val;
1390 size_t printed = scnprintf(bf, size, "%d", fd);
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001391 const char *path = thread__fd_path(arg->thread, fd, arg->trace);
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001392
1393 if (path)
1394 printed += scnprintf(bf + printed, size - printed, "<%s>", path);
1395
1396 return printed;
1397}
1398
1399static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
1400 struct syscall_arg *arg)
1401{
1402 int fd = arg->val;
1403 size_t printed = syscall_arg__scnprintf_fd(bf, size, arg);
Namhyung Kim89dceb22014-10-06 09:46:03 +09001404 struct thread_trace *ttrace = thread__priv(arg->thread);
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001405
Arnaldo Carvalho de Melo04662522013-12-26 17:41:15 -03001406 if (ttrace && fd >= 0 && fd <= ttrace->paths.max)
1407 zfree(&ttrace->paths.table[fd]);
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001408
1409 return printed;
1410}
1411
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001412static void thread__set_filename_pos(struct thread *thread, const char *bf,
1413 unsigned long ptr)
1414{
1415 struct thread_trace *ttrace = thread__priv(thread);
1416
1417 ttrace->filename.ptr = ptr;
1418 ttrace->filename.entry_str_pos = bf - ttrace->entry_str;
1419}
1420
1421static size_t syscall_arg__scnprintf_filename(char *bf, size_t size,
1422 struct syscall_arg *arg)
1423{
1424 unsigned long ptr = arg->val;
1425
1426 if (!arg->trace->vfs_getname)
1427 return scnprintf(bf, size, "%#x", ptr);
1428
1429 thread__set_filename_pos(arg->thread, bf, ptr);
1430 return 0;
1431}
1432
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001433static bool trace__filter_duration(struct trace *trace, double t)
1434{
1435 return t < (trace->duration_filter * NSEC_PER_MSEC);
1436}
1437
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001438static size_t trace__fprintf_tstamp(struct trace *trace, u64 tstamp, FILE *fp)
1439{
1440 double ts = (double)(tstamp - trace->base_time) / NSEC_PER_MSEC;
1441
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001442 return fprintf(fp, "%10.3f ", ts);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001443}
1444
Namhyung Kimf15eb532012-10-05 14:02:16 +09001445static bool done = false;
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03001446static bool interrupted = false;
Namhyung Kimf15eb532012-10-05 14:02:16 +09001447
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03001448static void sig_handler(int sig)
Namhyung Kimf15eb532012-10-05 14:02:16 +09001449{
1450 done = true;
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03001451 interrupted = sig == SIGINT;
Namhyung Kimf15eb532012-10-05 14:02:16 +09001452}
1453
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001454static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thread,
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001455 u64 duration, u64 tstamp, FILE *fp)
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001456{
1457 size_t printed = trace__fprintf_tstamp(trace, tstamp, fp);
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001458 printed += fprintf_duration(duration, fp);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001459
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -03001460 if (trace->multiple_threads) {
1461 if (trace->show_comm)
Frederic Weisbecker1902efe2013-09-11 16:56:44 +02001462 printed += fprintf(fp, "%.14s/", thread__comm_str(thread));
Adrian Hunter38051232013-07-04 16:20:31 +03001463 printed += fprintf(fp, "%d ", thread->tid);
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -03001464 }
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001465
1466 return printed;
1467}
1468
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001469static int trace__process_event(struct trace *trace, struct machine *machine,
Frederic Weisbecker162f0be2013-09-11 16:18:24 +02001470 union perf_event *event, struct perf_sample *sample)
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001471{
1472 int ret = 0;
1473
1474 switch (event->header.type) {
1475 case PERF_RECORD_LOST:
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001476 color_fprintf(trace->output, PERF_COLOR_RED,
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001477 "LOST %" PRIu64 " events!\n", event->lost.lost);
Frederic Weisbecker162f0be2013-09-11 16:18:24 +02001478 ret = machine__process_lost_event(machine, event, sample);
Arnaldo Carvalho de Melo3ed5ca22016-03-30 16:51:17 -03001479 break;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001480 default:
Frederic Weisbecker162f0be2013-09-11 16:18:24 +02001481 ret = machine__process_event(machine, event, sample);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001482 break;
1483 }
1484
1485 return ret;
1486}
1487
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001488static int trace__tool_process(struct perf_tool *tool,
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001489 union perf_event *event,
Frederic Weisbecker162f0be2013-09-11 16:18:24 +02001490 struct perf_sample *sample,
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001491 struct machine *machine)
1492{
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001493 struct trace *trace = container_of(tool, struct trace, tool);
Frederic Weisbecker162f0be2013-09-11 16:18:24 +02001494 return trace__process_event(trace, machine, event, sample);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001495}
1496
1497static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
1498{
Namhyung Kim0a7e6d12014-08-12 15:40:45 +09001499 int err = symbol__init(NULL);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001500
1501 if (err)
1502 return err;
1503
David Ahern8fb598e2013-09-28 13:13:00 -06001504 trace->host = machine__new_host();
1505 if (trace->host == NULL)
1506 return -ENOMEM;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001507
Arnaldo Carvalho de Melo959c2192015-07-24 12:13:05 -03001508 if (trace_event__register_resolver(trace->host, machine__resolve_kernel_addr) < 0)
Arnaldo Carvalho de Melo706c3da2015-07-22 16:16:16 -03001509 return -errno;
1510
Arnaldo Carvalho de Meloa33fbd52013-11-11 11:36:12 -03001511 err = __machine__synthesize_threads(trace->host, &trace->tool, &trace->opts.target,
Kan Liang9d9cad72015-06-17 09:51:11 -04001512 evlist->threads, trace__tool_process, false,
1513 trace->opts.proc_map_timeout);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001514 if (err)
1515 symbol__exit();
1516
1517 return err;
1518}
1519
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001520static int syscall__set_arg_fmts(struct syscall *sc)
1521{
1522 struct format_field *field;
1523 int idx = 0;
1524
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001525 sc->arg_scnprintf = calloc(sc->nr_args, sizeof(void *));
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001526 if (sc->arg_scnprintf == NULL)
1527 return -1;
1528
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -03001529 if (sc->fmt)
1530 sc->arg_parm = sc->fmt->arg_parm;
1531
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001532 for (field = sc->args; field; field = field->next) {
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -03001533 if (sc->fmt && sc->fmt->arg_scnprintf[idx])
1534 sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx];
1535 else if (field->flags & FIELD_IS_POINTER)
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001536 sc->arg_scnprintf[idx] = syscall_arg__scnprintf_hex;
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -03001537 else if (strcmp(field->type, "pid_t") == 0)
1538 sc->arg_scnprintf[idx] = SCA_PID;
Arnaldo Carvalho de Meloba2f22c2016-04-07 12:05:51 -03001539 else if (strcmp(field->type, "umode_t") == 0)
1540 sc->arg_scnprintf[idx] = SCA_MODE_T;
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001541 ++idx;
1542 }
1543
1544 return 0;
1545}
1546
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001547static int trace__read_syscall_info(struct trace *trace, int id)
1548{
1549 char tp_name[128];
1550 struct syscall *sc;
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03001551 const char *name = syscalltbl__name(trace->sctbl, id);
Arnaldo Carvalho de Melo3a531262012-10-20 12:39:03 -03001552
1553 if (name == NULL)
1554 return -1;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001555
1556 if (id > trace->syscalls.max) {
1557 struct syscall *nsyscalls = realloc(trace->syscalls.table, (id + 1) * sizeof(*sc));
1558
1559 if (nsyscalls == NULL)
1560 return -1;
1561
1562 if (trace->syscalls.max != -1) {
1563 memset(nsyscalls + trace->syscalls.max + 1, 0,
1564 (id - trace->syscalls.max) * sizeof(*sc));
1565 } else {
1566 memset(nsyscalls, 0, (id + 1) * sizeof(*sc));
1567 }
1568
1569 trace->syscalls.table = nsyscalls;
1570 trace->syscalls.max = id;
1571 }
1572
1573 sc = trace->syscalls.table + id;
Arnaldo Carvalho de Melo3a531262012-10-20 12:39:03 -03001574 sc->name = name;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001575
Arnaldo Carvalho de Melo3a531262012-10-20 12:39:03 -03001576 sc->fmt = syscall_fmt__find(sc->name);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001577
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -03001578 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name);
Jiri Olsa97978b32013-12-03 14:09:24 +01001579 sc->tp_format = trace_event__tp_format("syscalls", tp_name);
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -03001580
Jiri Olsa8dd2a132015-09-07 10:38:06 +02001581 if (IS_ERR(sc->tp_format) && sc->fmt && sc->fmt->alias) {
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -03001582 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->fmt->alias);
Jiri Olsa97978b32013-12-03 14:09:24 +01001583 sc->tp_format = trace_event__tp_format("syscalls", tp_name);
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -03001584 }
1585
Jiri Olsa8dd2a132015-09-07 10:38:06 +02001586 if (IS_ERR(sc->tp_format))
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001587 return -1;
1588
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001589 sc->args = sc->tp_format->format.fields;
1590 sc->nr_args = sc->tp_format->format.nr_fields;
Taeung Songc42de702016-02-26 22:14:25 +09001591 /*
1592 * We need to check and discard the first variable '__syscall_nr'
1593 * or 'nr' that mean the syscall number. It is needless here.
1594 * So drop '__syscall_nr' or 'nr' field but does not exist on older kernels.
1595 */
1596 if (sc->args && (!strcmp(sc->args->name, "__syscall_nr") || !strcmp(sc->args->name, "nr"))) {
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001597 sc->args = sc->args->next;
1598 --sc->nr_args;
1599 }
1600
Arnaldo Carvalho de Melo5089f202014-06-17 14:29:24 -03001601 sc->is_exit = !strcmp(name, "exit_group") || !strcmp(name, "exit");
1602
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001603 return syscall__set_arg_fmts(sc);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001604}
1605
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001606static int trace__validate_ev_qualifier(struct trace *trace)
1607{
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001608 int err = 0, i;
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001609 struct str_node *pos;
1610
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001611 trace->ev_qualifier_ids.nr = strlist__nr_entries(trace->ev_qualifier);
1612 trace->ev_qualifier_ids.entries = malloc(trace->ev_qualifier_ids.nr *
1613 sizeof(trace->ev_qualifier_ids.entries[0]));
1614
1615 if (trace->ev_qualifier_ids.entries == NULL) {
1616 fputs("Error:\tNot enough memory for allocating events qualifier ids\n",
1617 trace->output);
1618 err = -EINVAL;
1619 goto out;
1620 }
1621
1622 i = 0;
1623
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001624 strlist__for_each(pos, trace->ev_qualifier) {
1625 const char *sc = pos->s;
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03001626 int id = syscalltbl__id(trace->sctbl, sc);
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001627
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001628 if (id < 0) {
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001629 if (err == 0) {
1630 fputs("Error:\tInvalid syscall ", trace->output);
1631 err = -EINVAL;
1632 } else {
1633 fputs(", ", trace->output);
1634 }
1635
1636 fputs(sc, trace->output);
1637 }
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001638
1639 trace->ev_qualifier_ids.entries[i++] = id;
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001640 }
1641
1642 if (err < 0) {
1643 fputs("\nHint:\ttry 'perf list syscalls:sys_enter_*'"
1644 "\nHint:\tand: 'man syscalls'\n", trace->output);
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001645 zfree(&trace->ev_qualifier_ids.entries);
1646 trace->ev_qualifier_ids.nr = 0;
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001647 }
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001648out:
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001649 return err;
1650}
1651
David Ahern55d43bca2015-02-19 15:00:22 -05001652/*
1653 * args is to be interpreted as a series of longs but we need to handle
1654 * 8-byte unaligned accesses. args points to raw_data within the event
1655 * and raw_data is guaranteed to be 8-byte unaligned because it is
1656 * preceded by raw_size which is a u32. So we need to copy args to a temp
1657 * variable to read it. Most notably this avoids extended load instructions
1658 * on unaligned addresses
1659 */
1660
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001661static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
David Ahern55d43bca2015-02-19 15:00:22 -05001662 unsigned char *args, struct trace *trace,
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001663 struct thread *thread)
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001664{
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001665 size_t printed = 0;
David Ahern55d43bca2015-02-19 15:00:22 -05001666 unsigned char *p;
1667 unsigned long val;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001668
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001669 if (sc->args != NULL) {
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001670 struct format_field *field;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001671 u8 bit = 1;
1672 struct syscall_arg arg = {
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001673 .idx = 0,
1674 .mask = 0,
1675 .trace = trace,
1676 .thread = thread,
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001677 };
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001678
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001679 for (field = sc->args; field;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001680 field = field->next, ++arg.idx, bit <<= 1) {
1681 if (arg.mask & bit)
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -03001682 continue;
David Ahern55d43bca2015-02-19 15:00:22 -05001683
1684 /* special care for unaligned accesses */
1685 p = args + sizeof(unsigned long) * arg.idx;
1686 memcpy(&val, p, sizeof(val));
1687
Arnaldo Carvalho de Melo4aa58232013-09-20 12:19:41 -03001688 /*
1689 * Suppress this argument if its value is zero and
1690 * and we don't have a string associated in an
1691 * strarray for it.
1692 */
David Ahern55d43bca2015-02-19 15:00:22 -05001693 if (val == 0 &&
Arnaldo Carvalho de Melo4aa58232013-09-20 12:19:41 -03001694 !(sc->arg_scnprintf &&
1695 sc->arg_scnprintf[arg.idx] == SCA_STRARRAY &&
1696 sc->arg_parm[arg.idx]))
Arnaldo Carvalho de Melo22ae5cf12013-09-12 11:27:34 -03001697 continue;
1698
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001699 printed += scnprintf(bf + printed, size - printed,
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001700 "%s%s: ", printed ? ", " : "", field->name);
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001701 if (sc->arg_scnprintf && sc->arg_scnprintf[arg.idx]) {
David Ahern55d43bca2015-02-19 15:00:22 -05001702 arg.val = val;
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -03001703 if (sc->arg_parm)
1704 arg.parm = sc->arg_parm[arg.idx];
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001705 printed += sc->arg_scnprintf[arg.idx](bf + printed,
1706 size - printed, &arg);
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -03001707 } else {
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001708 printed += scnprintf(bf + printed, size - printed,
David Ahern55d43bca2015-02-19 15:00:22 -05001709 "%ld", val);
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -03001710 }
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001711 }
1712 } else {
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001713 int i = 0;
1714
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001715 while (i < 6) {
David Ahern55d43bca2015-02-19 15:00:22 -05001716 /* special care for unaligned accesses */
1717 p = args + sizeof(unsigned long) * i;
1718 memcpy(&val, p, sizeof(val));
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001719 printed += scnprintf(bf + printed, size - printed,
1720 "%sarg%d: %ld",
David Ahern55d43bca2015-02-19 15:00:22 -05001721 printed ? ", " : "", i, val);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001722 ++i;
1723 }
1724 }
1725
1726 return printed;
1727}
1728
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001729typedef int (*tracepoint_handler)(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04001730 union perf_event *event,
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001731 struct perf_sample *sample);
1732
1733static struct syscall *trace__syscall_info(struct trace *trace,
David Ahernbf2575c2013-10-08 21:26:53 -06001734 struct perf_evsel *evsel, int id)
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001735{
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001736
1737 if (id < 0) {
Arnaldo Carvalho de Meloadaa18b2013-08-22 17:55:25 -03001738
1739 /*
1740 * XXX: Noticed on x86_64, reproduced as far back as 3.0.36, haven't tried
1741 * before that, leaving at a higher verbosity level till that is
1742 * explained. Reproduced with plain ftrace with:
1743 *
1744 * echo 1 > /t/events/raw_syscalls/sys_exit/enable
1745 * grep "NR -1 " /t/trace_pipe
1746 *
1747 * After generating some load on the machine.
1748 */
1749 if (verbose > 1) {
1750 static u64 n;
1751 fprintf(trace->output, "Invalid syscall %d id, skipping (%s, %" PRIu64 ") ...\n",
1752 id, perf_evsel__name(evsel), ++n);
1753 }
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001754 return NULL;
1755 }
1756
1757 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL) &&
1758 trace__read_syscall_info(trace, id))
1759 goto out_cant_read;
1760
1761 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL))
1762 goto out_cant_read;
1763
1764 return &trace->syscalls.table[id];
1765
1766out_cant_read:
Arnaldo Carvalho de Melo7c304ee02013-08-22 16:49:54 -03001767 if (verbose) {
1768 fprintf(trace->output, "Problems reading syscall %d", id);
1769 if (id <= trace->syscalls.max && trace->syscalls.table[id].name != NULL)
1770 fprintf(trace->output, "(%s)", trace->syscalls.table[id].name);
1771 fputs(" information\n", trace->output);
1772 }
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001773 return NULL;
1774}
1775
David Ahernbf2575c2013-10-08 21:26:53 -06001776static void thread__update_stats(struct thread_trace *ttrace,
1777 int id, struct perf_sample *sample)
1778{
1779 struct int_node *inode;
1780 struct stats *stats;
1781 u64 duration = 0;
1782
1783 inode = intlist__findnew(ttrace->syscall_stats, id);
1784 if (inode == NULL)
1785 return;
1786
1787 stats = inode->priv;
1788 if (stats == NULL) {
1789 stats = malloc(sizeof(struct stats));
1790 if (stats == NULL)
1791 return;
1792 init_stats(stats);
1793 inode->priv = stats;
1794 }
1795
1796 if (ttrace->entry_time && sample->time > ttrace->entry_time)
1797 duration = sample->time - ttrace->entry_time;
1798
1799 update_stats(stats, duration);
1800}
1801
Arnaldo Carvalho de Meloe5966632015-02-13 13:22:21 -03001802static int trace__printf_interrupted_entry(struct trace *trace, struct perf_sample *sample)
1803{
1804 struct thread_trace *ttrace;
1805 u64 duration;
1806 size_t printed;
1807
1808 if (trace->current == NULL)
1809 return 0;
1810
1811 ttrace = thread__priv(trace->current);
1812
1813 if (!ttrace->entry_pending)
1814 return 0;
1815
1816 duration = sample->time - ttrace->entry_time;
1817
1818 printed = trace__fprintf_entry_head(trace, trace->current, duration, sample->time, trace->output);
1819 printed += fprintf(trace->output, "%-70s) ...\n", ttrace->entry_str);
1820 ttrace->entry_pending = false;
1821
1822 return printed;
1823}
1824
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001825static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04001826 union perf_event *event __maybe_unused,
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001827 struct perf_sample *sample)
1828{
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001829 char *msg;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001830 void *args;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001831 size_t printed = 0;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001832 struct thread *thread;
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001833 int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
David Ahernbf2575c2013-10-08 21:26:53 -06001834 struct syscall *sc = trace__syscall_info(trace, evsel, id);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001835 struct thread_trace *ttrace;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001836
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001837 if (sc == NULL)
1838 return -1;
1839
David Ahern8fb598e2013-09-28 13:13:00 -06001840 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001841 ttrace = thread__trace(thread, trace->output);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001842 if (ttrace == NULL)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001843 goto out_put;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001844
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -03001845 args = perf_evsel__sc_tp_ptr(evsel, args, sample);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001846
1847 if (ttrace->entry_str == NULL) {
Arnaldo Carvalho de Meloe4d44e82015-08-04 22:17:29 -03001848 ttrace->entry_str = malloc(trace__entry_str_size);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001849 if (!ttrace->entry_str)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001850 goto out_put;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001851 }
1852
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -03001853 if (!(trace->duration_filter || trace->summary_only || trace->min_stack))
Arnaldo Carvalho de Melo6ebad5c2015-03-25 18:01:15 -03001854 trace__printf_interrupted_entry(trace, sample);
Arnaldo Carvalho de Meloe5966632015-02-13 13:22:21 -03001855
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001856 ttrace->entry_time = sample->time;
1857 msg = ttrace->entry_str;
Arnaldo Carvalho de Meloe4d44e82015-08-04 22:17:29 -03001858 printed += scnprintf(msg + printed, trace__entry_str_size - printed, "%s(", sc->name);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001859
Arnaldo Carvalho de Meloe4d44e82015-08-04 22:17:29 -03001860 printed += syscall__scnprintf_args(sc, msg + printed, trace__entry_str_size - printed,
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001861 args, trace, thread);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001862
Arnaldo Carvalho de Melo5089f202014-06-17 14:29:24 -03001863 if (sc->is_exit) {
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -03001864 if (!(trace->duration_filter || trace->summary_only || trace->min_stack)) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001865 trace__fprintf_entry_head(trace, thread, 1, sample->time, trace->output);
1866 fprintf(trace->output, "%-70s\n", ttrace->entry_str);
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001867 }
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03001868 } else {
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001869 ttrace->entry_pending = true;
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03001870 /* See trace__vfs_getname & trace__sys_exit */
1871 ttrace->filename.pending_open = false;
1872 }
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001873
Arnaldo Carvalho de Melof3b623b2015-03-02 22:21:35 -03001874 if (trace->current != thread) {
1875 thread__put(trace->current);
1876 trace->current = thread__get(thread);
1877 }
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001878 err = 0;
1879out_put:
1880 thread__put(thread);
1881 return err;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001882}
1883
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -03001884static int trace__resolve_callchain(struct trace *trace, struct perf_evsel *evsel,
1885 struct perf_sample *sample,
1886 struct callchain_cursor *cursor)
Arnaldo Carvalho de Melo202ff962016-04-12 10:11:07 -03001887{
1888 struct addr_location al;
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -03001889
1890 if (machine__resolve(trace->host, &al, sample) < 0 ||
1891 thread__resolve_callchain(al.thread, cursor, evsel, sample, NULL, NULL, trace->max_stack))
1892 return -1;
1893
1894 return 0;
1895}
1896
1897static int trace__fprintf_callchain(struct trace *trace, struct perf_sample *sample)
1898{
Arnaldo Carvalho de Melo202ff962016-04-12 10:11:07 -03001899 /* TODO: user-configurable print_opts */
Arnaldo Carvalho de Meloe20ab862016-04-12 15:16:15 -03001900 const unsigned int print_opts = EVSEL__PRINT_SYM |
1901 EVSEL__PRINT_DSO |
1902 EVSEL__PRINT_UNKNOWN_AS_ADDR;
Arnaldo Carvalho de Melo202ff962016-04-12 10:11:07 -03001903
Arnaldo Carvalho de Melod327e602016-04-14 17:53:49 -03001904 return sample__fprintf_callchain(sample, 38, print_opts, &callchain_cursor, trace->output);
Arnaldo Carvalho de Melo202ff962016-04-12 10:11:07 -03001905}
1906
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001907static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04001908 union perf_event *event __maybe_unused,
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001909 struct perf_sample *sample)
1910{
Chang Hyun Park2c82c3a2014-09-26 21:54:01 +09001911 long ret;
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001912 u64 duration = 0;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001913 struct thread *thread;
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -03001914 int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1, callchain_ret = 0;
David Ahernbf2575c2013-10-08 21:26:53 -06001915 struct syscall *sc = trace__syscall_info(trace, evsel, id);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001916 struct thread_trace *ttrace;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001917
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001918 if (sc == NULL)
1919 return -1;
1920
David Ahern8fb598e2013-09-28 13:13:00 -06001921 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001922 ttrace = thread__trace(thread, trace->output);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001923 if (ttrace == NULL)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001924 goto out_put;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001925
David Ahernbf2575c2013-10-08 21:26:53 -06001926 if (trace->summary)
1927 thread__update_stats(ttrace, id, sample);
1928
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -03001929 ret = perf_evsel__sc_tp_uint(evsel, ret, sample);
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001930
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03001931 if (id == trace->open_id && ret >= 0 && ttrace->filename.pending_open) {
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03001932 trace__set_fd_pathname(thread, ret, ttrace->filename.name);
1933 ttrace->filename.pending_open = false;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001934 ++trace->stats.vfs_getname;
1935 }
1936
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001937 ttrace->exit_time = sample->time;
1938
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001939 if (ttrace->entry_time) {
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001940 duration = sample->time - ttrace->entry_time;
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001941 if (trace__filter_duration(trace, duration))
1942 goto out;
1943 } else if (trace->duration_filter)
1944 goto out;
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001945
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -03001946 if (sample->callchain) {
1947 callchain_ret = trace__resolve_callchain(trace, evsel, sample, &callchain_cursor);
1948 if (callchain_ret == 0) {
1949 if (callchain_cursor.nr < trace->min_stack)
1950 goto out;
1951 callchain_ret = 1;
1952 }
1953 }
1954
David Ahernfd2eaba2013-11-12 09:31:15 -07001955 if (trace->summary_only)
1956 goto out;
1957
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001958 trace__fprintf_entry_head(trace, thread, duration, sample->time, trace->output);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001959
1960 if (ttrace->entry_pending) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001961 fprintf(trace->output, "%-70s", ttrace->entry_str);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001962 } else {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001963 fprintf(trace->output, " ... [");
1964 color_fprintf(trace->output, PERF_COLOR_YELLOW, "continued");
1965 fprintf(trace->output, "]: %s()", sc->name);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001966 }
1967
Arnaldo Carvalho de Meloda3c9a42013-08-26 11:28:34 -03001968 if (sc->fmt == NULL) {
1969signed_print:
Chang Hyun Park2c82c3a2014-09-26 21:54:01 +09001970 fprintf(trace->output, ") = %ld", ret);
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -03001971 } else if (ret < 0 && (sc->fmt->errmsg || sc->fmt->errpid)) {
Masami Hiramatsu942a91e2014-08-14 02:22:41 +00001972 char bf[STRERR_BUFSIZE];
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001973 const char *emsg = strerror_r(-ret, bf, sizeof(bf)),
1974 *e = audit_errno_to_name(-ret);
1975
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001976 fprintf(trace->output, ") = -1 %s %s", e, emsg);
Arnaldo Carvalho de Meloda3c9a42013-08-26 11:28:34 -03001977 } else if (ret == 0 && sc->fmt->timeout)
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001978 fprintf(trace->output, ") = 0 Timeout");
Arnaldo Carvalho de Melo04b34722013-08-26 11:36:30 -03001979 else if (sc->fmt->hexret)
Chang Hyun Park2c82c3a2014-09-26 21:54:01 +09001980 fprintf(trace->output, ") = %#lx", ret);
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -03001981 else if (sc->fmt->errpid) {
1982 struct thread *child = machine__find_thread(trace->host, ret, ret);
1983
1984 if (child != NULL) {
1985 fprintf(trace->output, ") = %ld", ret);
1986 if (child->comm_set)
1987 fprintf(trace->output, " (%s)", thread__comm_str(child));
1988 thread__put(child);
1989 }
1990 } else
Arnaldo Carvalho de Meloda3c9a42013-08-26 11:28:34 -03001991 goto signed_print;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001992
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001993 fputc('\n', trace->output);
Milian Wolff566a0882016-04-08 13:34:15 +02001994
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -03001995 if (callchain_ret > 0)
1996 trace__fprintf_callchain(trace, sample);
1997 else if (callchain_ret < 0)
1998 pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel));
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001999out:
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03002000 ttrace->entry_pending = false;
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002001 err = 0;
2002out_put:
2003 thread__put(thread);
2004 return err;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03002005}
2006
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002007static int trace__vfs_getname(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04002008 union perf_event *event __maybe_unused,
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002009 struct perf_sample *sample)
2010{
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03002011 struct thread *thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
2012 struct thread_trace *ttrace;
2013 size_t filename_len, entry_str_len, to_move;
2014 ssize_t remaining_space;
2015 char *pos;
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03002016 const char *filename = perf_evsel__rawptr(evsel, sample, "pathname");
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03002017
2018 if (!thread)
2019 goto out;
2020
2021 ttrace = thread__priv(thread);
2022 if (!ttrace)
2023 goto out;
2024
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03002025 filename_len = strlen(filename);
2026
2027 if (ttrace->filename.namelen < filename_len) {
2028 char *f = realloc(ttrace->filename.name, filename_len + 1);
2029
2030 if (f == NULL)
2031 goto out;
2032
2033 ttrace->filename.namelen = filename_len;
2034 ttrace->filename.name = f;
2035 }
2036
2037 strcpy(ttrace->filename.name, filename);
2038 ttrace->filename.pending_open = true;
2039
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03002040 if (!ttrace->filename.ptr)
2041 goto out;
2042
2043 entry_str_len = strlen(ttrace->entry_str);
2044 remaining_space = trace__entry_str_size - entry_str_len - 1; /* \0 */
2045 if (remaining_space <= 0)
2046 goto out;
2047
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03002048 if (filename_len > (size_t)remaining_space) {
2049 filename += filename_len - remaining_space;
2050 filename_len = remaining_space;
2051 }
2052
2053 to_move = entry_str_len - ttrace->filename.entry_str_pos + 1; /* \0 */
2054 pos = ttrace->entry_str + ttrace->filename.entry_str_pos;
2055 memmove(pos + filename_len, pos, to_move);
2056 memcpy(pos, filename, filename_len);
2057
2058 ttrace->filename.ptr = 0;
2059 ttrace->filename.entry_str_pos = 0;
2060out:
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002061 return 0;
2062}
2063
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002064static int trace__sched_stat_runtime(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04002065 union perf_event *event __maybe_unused,
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002066 struct perf_sample *sample)
2067{
2068 u64 runtime = perf_evsel__intval(evsel, sample, "runtime");
2069 double runtime_ms = (double)runtime / NSEC_PER_MSEC;
David Ahern8fb598e2013-09-28 13:13:00 -06002070 struct thread *thread = machine__findnew_thread(trace->host,
Adrian Hunter314add62013-08-27 11:23:03 +03002071 sample->pid,
2072 sample->tid);
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002073 struct thread_trace *ttrace = thread__trace(thread, trace->output);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002074
2075 if (ttrace == NULL)
2076 goto out_dump;
2077
2078 ttrace->runtime_ms += runtime_ms;
2079 trace->runtime_ms += runtime_ms;
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002080 thread__put(thread);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002081 return 0;
2082
2083out_dump:
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002084 fprintf(trace->output, "%s: comm=%s,pid=%u,runtime=%" PRIu64 ",vruntime=%" PRIu64 ")\n",
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002085 evsel->name,
2086 perf_evsel__strval(evsel, sample, "comm"),
2087 (pid_t)perf_evsel__intval(evsel, sample, "pid"),
2088 runtime,
2089 perf_evsel__intval(evsel, sample, "vruntime"));
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002090 thread__put(thread);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002091 return 0;
2092}
2093
Wang Nan1d6c9402016-02-26 09:31:55 +00002094static void bpf_output__printer(enum binary_printer_ops op,
2095 unsigned int val, void *extra)
2096{
2097 FILE *output = extra;
2098 unsigned char ch = (unsigned char)val;
2099
2100 switch (op) {
2101 case BINARY_PRINT_CHAR_DATA:
2102 fprintf(output, "%c", isprint(ch) ? ch : '.');
2103 break;
2104 case BINARY_PRINT_DATA_BEGIN:
2105 case BINARY_PRINT_LINE_BEGIN:
2106 case BINARY_PRINT_ADDR:
2107 case BINARY_PRINT_NUM_DATA:
2108 case BINARY_PRINT_NUM_PAD:
2109 case BINARY_PRINT_SEP:
2110 case BINARY_PRINT_CHAR_PAD:
2111 case BINARY_PRINT_LINE_END:
2112 case BINARY_PRINT_DATA_END:
2113 default:
2114 break;
2115 }
2116}
2117
2118static void bpf_output__fprintf(struct trace *trace,
2119 struct perf_sample *sample)
2120{
2121 print_binary(sample->raw_data, sample->raw_size, 8,
2122 bpf_output__printer, trace->output);
2123}
2124
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002125static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
2126 union perf_event *event __maybe_unused,
2127 struct perf_sample *sample)
2128{
2129 trace__printf_interrupted_entry(trace, sample);
2130 trace__fprintf_tstamp(trace, sample->time, trace->output);
Arnaldo Carvalho de Melo08089212015-02-19 21:51:50 -08002131
2132 if (trace->trace_syscalls)
2133 fprintf(trace->output, "( ): ");
2134
2135 fprintf(trace->output, "%s:", evsel->name);
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002136
Wang Nan1d6c9402016-02-26 09:31:55 +00002137 if (perf_evsel__is_bpf_output(evsel)) {
2138 bpf_output__fprintf(trace, sample);
2139 } else if (evsel->tp_format) {
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002140 event_format__fprintf(evsel->tp_format, sample->cpu,
2141 sample->raw_data, sample->raw_size,
2142 trace->output);
2143 }
2144
2145 fprintf(trace->output, ")\n");
Arnaldo Carvalho de Melo202ff962016-04-12 10:11:07 -03002146
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -03002147 if (sample->callchain) {
2148 if (trace__resolve_callchain(trace, evsel, sample, &callchain_cursor) == 0)
2149 trace__fprintf_callchain(trace, sample);
2150 }
Arnaldo Carvalho de Melo202ff962016-04-12 10:11:07 -03002151
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002152 return 0;
2153}
2154
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002155static void print_location(FILE *f, struct perf_sample *sample,
2156 struct addr_location *al,
2157 bool print_dso, bool print_sym)
2158{
2159
2160 if ((verbose || print_dso) && al->map)
2161 fprintf(f, "%s@", al->map->dso->long_name);
2162
2163 if ((verbose || print_sym) && al->sym)
Arnaldo Carvalho de Melo4414a3c2014-07-08 15:39:21 -03002164 fprintf(f, "%s+0x%" PRIx64, al->sym->name,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002165 al->addr - al->sym->start);
2166 else if (al->map)
Arnaldo Carvalho de Melo4414a3c2014-07-08 15:39:21 -03002167 fprintf(f, "0x%" PRIx64, al->addr);
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002168 else
Arnaldo Carvalho de Melo4414a3c2014-07-08 15:39:21 -03002169 fprintf(f, "0x%" PRIx64, sample->addr);
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002170}
2171
2172static int trace__pgfault(struct trace *trace,
2173 struct perf_evsel *evsel,
Arnaldo Carvalho de Melo473398a2016-03-22 18:23:43 -03002174 union perf_event *event __maybe_unused,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002175 struct perf_sample *sample)
2176{
2177 struct thread *thread;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002178 struct addr_location al;
2179 char map_type = 'd';
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04002180 struct thread_trace *ttrace;
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002181 int err = -1;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002182
2183 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04002184 ttrace = thread__trace(thread, trace->output);
2185 if (ttrace == NULL)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002186 goto out_put;
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04002187
2188 if (evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ)
2189 ttrace->pfmaj++;
2190 else
2191 ttrace->pfmin++;
2192
2193 if (trace->summary_only)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002194 goto out;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002195
Arnaldo Carvalho de Melo473398a2016-03-22 18:23:43 -03002196 thread__find_addr_location(thread, sample->cpumode, MAP__FUNCTION,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002197 sample->ip, &al);
2198
2199 trace__fprintf_entry_head(trace, thread, 0, sample->time, trace->output);
2200
2201 fprintf(trace->output, "%sfault [",
2202 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ?
2203 "maj" : "min");
2204
2205 print_location(trace->output, sample, &al, false, true);
2206
2207 fprintf(trace->output, "] => ");
2208
Arnaldo Carvalho de Melo473398a2016-03-22 18:23:43 -03002209 thread__find_addr_location(thread, sample->cpumode, MAP__VARIABLE,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002210 sample->addr, &al);
2211
2212 if (!al.map) {
Arnaldo Carvalho de Melo473398a2016-03-22 18:23:43 -03002213 thread__find_addr_location(thread, sample->cpumode,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002214 MAP__FUNCTION, sample->addr, &al);
2215
2216 if (al.map)
2217 map_type = 'x';
2218 else
2219 map_type = '?';
2220 }
2221
2222 print_location(trace->output, sample, &al, true, false);
2223
2224 fprintf(trace->output, " (%c%c)\n", map_type, al.level);
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002225out:
2226 err = 0;
2227out_put:
2228 thread__put(thread);
2229 return err;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002230}
2231
David Ahernbdc89662013-08-28 22:29:53 -06002232static bool skip_sample(struct trace *trace, struct perf_sample *sample)
2233{
2234 if ((trace->pid_list && intlist__find(trace->pid_list, sample->pid)) ||
2235 (trace->tid_list && intlist__find(trace->tid_list, sample->tid)))
2236 return false;
2237
2238 if (trace->pid_list || trace->tid_list)
2239 return true;
2240
2241 return false;
2242}
2243
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03002244static void trace__set_base_time(struct trace *trace,
Arnaldo Carvalho de Melo8a07a802016-03-31 15:19:39 -03002245 struct perf_evsel *evsel,
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03002246 struct perf_sample *sample)
2247{
Arnaldo Carvalho de Melo8a07a802016-03-31 15:19:39 -03002248 /*
2249 * BPF events were not setting PERF_SAMPLE_TIME, so be more robust
2250 * and don't use sample->time unconditionally, we may end up having
2251 * some other event in the future without PERF_SAMPLE_TIME for good
2252 * reason, i.e. we may not be interested in its timestamps, just in
2253 * it taking place, picking some piece of information when it
2254 * appears in our event stream (vfs_getname comes to mind).
2255 */
2256 if (trace->base_time == 0 && !trace->full_time &&
2257 (evsel->attr.sample_type & PERF_SAMPLE_TIME))
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03002258 trace->base_time = sample->time;
2259}
2260
David Ahern6810fc92013-08-28 22:29:52 -06002261static int trace__process_sample(struct perf_tool *tool,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04002262 union perf_event *event,
David Ahern6810fc92013-08-28 22:29:52 -06002263 struct perf_sample *sample,
2264 struct perf_evsel *evsel,
2265 struct machine *machine __maybe_unused)
2266{
2267 struct trace *trace = container_of(tool, struct trace, tool);
2268 int err = 0;
2269
Arnaldo Carvalho de Melo744a9712013-11-06 10:17:38 -03002270 tracepoint_handler handler = evsel->handler;
David Ahern6810fc92013-08-28 22:29:52 -06002271
David Ahernbdc89662013-08-28 22:29:53 -06002272 if (skip_sample(trace, sample))
2273 return 0;
2274
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03002275 trace__set_base_time(trace, evsel, sample);
David Ahern6810fc92013-08-28 22:29:52 -06002276
David Ahern31605652013-12-04 19:41:41 -07002277 if (handler) {
2278 ++trace->nr_events;
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04002279 handler(trace, evsel, event, sample);
David Ahern31605652013-12-04 19:41:41 -07002280 }
David Ahern6810fc92013-08-28 22:29:52 -06002281
2282 return err;
2283}
2284
David Ahernbdc89662013-08-28 22:29:53 -06002285static int parse_target_str(struct trace *trace)
2286{
2287 if (trace->opts.target.pid) {
2288 trace->pid_list = intlist__new(trace->opts.target.pid);
2289 if (trace->pid_list == NULL) {
2290 pr_err("Error parsing process id string\n");
2291 return -EINVAL;
2292 }
2293 }
2294
2295 if (trace->opts.target.tid) {
2296 trace->tid_list = intlist__new(trace->opts.target.tid);
2297 if (trace->tid_list == NULL) {
2298 pr_err("Error parsing thread id string\n");
2299 return -EINVAL;
2300 }
2301 }
2302
2303 return 0;
2304}
2305
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002306static int trace__record(struct trace *trace, int argc, const char **argv)
David Ahern5e2485b2013-09-28 13:13:01 -06002307{
2308 unsigned int rec_argc, i, j;
2309 const char **rec_argv;
2310 const char * const record_args[] = {
2311 "record",
2312 "-R",
2313 "-m", "1024",
2314 "-c", "1",
David Ahern5e2485b2013-09-28 13:13:01 -06002315 };
2316
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002317 const char * const sc_args[] = { "-e", };
2318 unsigned int sc_args_nr = ARRAY_SIZE(sc_args);
2319 const char * const majpf_args[] = { "-e", "major-faults" };
2320 unsigned int majpf_args_nr = ARRAY_SIZE(majpf_args);
2321 const char * const minpf_args[] = { "-e", "minor-faults" };
2322 unsigned int minpf_args_nr = ARRAY_SIZE(minpf_args);
2323
David Ahern9aca7f12013-12-04 19:41:39 -07002324 /* +1 is for the event string below */
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002325 rec_argc = ARRAY_SIZE(record_args) + sc_args_nr + 1 +
2326 majpf_args_nr + minpf_args_nr + argc;
David Ahern5e2485b2013-09-28 13:13:01 -06002327 rec_argv = calloc(rec_argc + 1, sizeof(char *));
2328
2329 if (rec_argv == NULL)
2330 return -ENOMEM;
2331
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002332 j = 0;
David Ahern5e2485b2013-09-28 13:13:01 -06002333 for (i = 0; i < ARRAY_SIZE(record_args); i++)
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002334 rec_argv[j++] = record_args[i];
2335
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002336 if (trace->trace_syscalls) {
2337 for (i = 0; i < sc_args_nr; i++)
2338 rec_argv[j++] = sc_args[i];
David Ahern5e2485b2013-09-28 13:13:01 -06002339
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002340 /* event string may be different for older kernels - e.g., RHEL6 */
2341 if (is_valid_tracepoint("raw_syscalls:sys_enter"))
2342 rec_argv[j++] = "raw_syscalls:sys_enter,raw_syscalls:sys_exit";
2343 else if (is_valid_tracepoint("syscalls:sys_enter"))
2344 rec_argv[j++] = "syscalls:sys_enter,syscalls:sys_exit";
2345 else {
2346 pr_err("Neither raw_syscalls nor syscalls events exist.\n");
2347 return -1;
2348 }
David Ahern9aca7f12013-12-04 19:41:39 -07002349 }
David Ahern9aca7f12013-12-04 19:41:39 -07002350
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002351 if (trace->trace_pgfaults & TRACE_PFMAJ)
2352 for (i = 0; i < majpf_args_nr; i++)
2353 rec_argv[j++] = majpf_args[i];
David Ahern5e2485b2013-09-28 13:13:01 -06002354
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002355 if (trace->trace_pgfaults & TRACE_PFMIN)
2356 for (i = 0; i < minpf_args_nr; i++)
2357 rec_argv[j++] = minpf_args[i];
2358
2359 for (i = 0; i < (unsigned int)argc; i++)
2360 rec_argv[j++] = argv[i];
2361
2362 return cmd_record(j, rec_argv, NULL);
David Ahern5e2485b2013-09-28 13:13:01 -06002363}
2364
David Ahernbf2575c2013-10-08 21:26:53 -06002365static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp);
2366
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002367static bool perf_evlist__add_vfs_getname(struct perf_evlist *evlist)
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002368{
Arnaldo Carvalho de Meloef503832013-11-07 16:41:19 -03002369 struct perf_evsel *evsel = perf_evsel__newtp("probe", "vfs_getname");
Jiri Olsa8dd2a132015-09-07 10:38:06 +02002370
2371 if (IS_ERR(evsel))
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002372 return false;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002373
2374 if (perf_evsel__field(evsel, "pathname") == NULL) {
2375 perf_evsel__delete(evsel);
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002376 return false;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002377 }
2378
Arnaldo Carvalho de Melo744a9712013-11-06 10:17:38 -03002379 evsel->handler = trace__vfs_getname;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002380 perf_evlist__add(evlist, evsel);
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002381 return true;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002382}
2383
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002384static int perf_evlist__add_pgfault(struct perf_evlist *evlist,
2385 u64 config)
2386{
2387 struct perf_evsel *evsel;
2388 struct perf_event_attr attr = {
2389 .type = PERF_TYPE_SOFTWARE,
2390 .mmap_data = 1,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002391 };
2392
2393 attr.config = config;
Arnaldo Carvalho de Melo05247982014-07-23 18:15:09 -03002394 attr.sample_period = 1;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002395
2396 event_attr_init(&attr);
2397
2398 evsel = perf_evsel__new(&attr);
2399 if (!evsel)
2400 return -ENOMEM;
2401
2402 evsel->handler = trace__pgfault;
2403 perf_evlist__add(evlist, evsel);
2404
2405 return 0;
2406}
2407
Arnaldo Carvalho de Meloddbb1b12015-02-21 12:10:29 -08002408static void trace__handle_event(struct trace *trace, union perf_event *event, struct perf_sample *sample)
2409{
2410 const u32 type = event->header.type;
2411 struct perf_evsel *evsel;
2412
Arnaldo Carvalho de Meloddbb1b12015-02-21 12:10:29 -08002413 if (type != PERF_RECORD_SAMPLE) {
2414 trace__process_event(trace, trace->host, event, sample);
2415 return;
2416 }
2417
2418 evsel = perf_evlist__id2evsel(trace->evlist, sample->id);
2419 if (evsel == NULL) {
2420 fprintf(trace->output, "Unknown tp ID %" PRIu64 ", skipping...\n", sample->id);
2421 return;
2422 }
2423
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03002424 trace__set_base_time(trace, evsel, sample);
2425
Arnaldo Carvalho de Meloddbb1b12015-02-21 12:10:29 -08002426 if (evsel->attr.type == PERF_TYPE_TRACEPOINT &&
2427 sample->raw_data == NULL) {
2428 fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n",
2429 perf_evsel__name(evsel), sample->tid,
2430 sample->cpu, sample->raw_size);
2431 } else {
2432 tracepoint_handler handler = evsel->handler;
2433 handler(trace, evsel, event, sample);
2434 }
2435}
2436
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03002437static int trace__add_syscall_newtp(struct trace *trace)
2438{
2439 int ret = -1;
2440 struct perf_evlist *evlist = trace->evlist;
2441 struct perf_evsel *sys_enter, *sys_exit;
2442
2443 sys_enter = perf_evsel__syscall_newtp("sys_enter", trace__sys_enter);
2444 if (sys_enter == NULL)
2445 goto out;
2446
2447 if (perf_evsel__init_sc_tp_ptr_field(sys_enter, args))
2448 goto out_delete_sys_enter;
2449
2450 sys_exit = perf_evsel__syscall_newtp("sys_exit", trace__sys_exit);
2451 if (sys_exit == NULL)
2452 goto out_delete_sys_enter;
2453
2454 if (perf_evsel__init_sc_tp_uint_field(sys_exit, ret))
2455 goto out_delete_sys_exit;
2456
2457 perf_evlist__add(evlist, sys_enter);
2458 perf_evlist__add(evlist, sys_exit);
2459
Arnaldo Carvalho de Melo44621812016-04-11 15:49:11 -03002460 if (trace->opts.callgraph_set && !trace->kernel_syscallchains) {
2461 /*
2462 * We're interested only in the user space callchain
2463 * leading to the syscall, allow overriding that for
2464 * debugging reasons using --kernel_syscall_callchains
2465 */
2466 sys_exit->attr.exclude_callchain_kernel = 1;
2467 }
2468
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03002469 trace->syscalls.events.sys_enter = sys_enter;
2470 trace->syscalls.events.sys_exit = sys_exit;
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03002471
2472 ret = 0;
2473out:
2474 return ret;
2475
2476out_delete_sys_exit:
2477 perf_evsel__delete_priv(sys_exit);
2478out_delete_sys_enter:
2479 perf_evsel__delete_priv(sys_enter);
2480 goto out;
2481}
2482
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002483static int trace__set_ev_qualifier_filter(struct trace *trace)
2484{
2485 int err = -1;
2486 char *filter = asprintf_expr_inout_ints("id", !trace->not_ev_qualifier,
2487 trace->ev_qualifier_ids.nr,
2488 trace->ev_qualifier_ids.entries);
2489
2490 if (filter == NULL)
2491 goto out_enomem;
2492
2493 if (!perf_evsel__append_filter(trace->syscalls.events.sys_enter, "&&", filter))
2494 err = perf_evsel__append_filter(trace->syscalls.events.sys_exit, "&&", filter);
2495
2496 free(filter);
2497out:
2498 return err;
2499out_enomem:
2500 errno = ENOMEM;
2501 goto out;
2502}
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03002503
Namhyung Kimf15eb532012-10-05 14:02:16 +09002504static int trace__run(struct trace *trace, int argc, const char **argv)
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002505{
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002506 struct perf_evlist *evlist = trace->evlist;
Arnaldo Carvalho de Melo94ad89b2015-07-03 17:42:03 -03002507 struct perf_evsel *evsel;
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03002508 int err = -1, i;
2509 unsigned long before;
Namhyung Kimf15eb532012-10-05 14:02:16 +09002510 const bool forks = argc > 0;
Arnaldo Carvalho de Melo46fb3c22014-09-22 14:39:48 -03002511 bool draining = false;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002512
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03002513 trace->live = true;
2514
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03002515 if (trace->trace_syscalls && trace__add_syscall_newtp(trace))
Arnaldo Carvalho de Melo801c67b2015-01-22 10:52:55 -03002516 goto out_error_raw_syscalls;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002517
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002518 if (trace->trace_syscalls)
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002519 trace->vfs_getname = perf_evlist__add_vfs_getname(evlist);
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002520
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002521 if ((trace->trace_pgfaults & TRACE_PFMAJ) &&
Arnaldo Carvalho de Meloe2726d92015-01-22 10:34:22 -03002522 perf_evlist__add_pgfault(evlist, PERF_COUNT_SW_PAGE_FAULTS_MAJ)) {
Arnaldo Carvalho de Melo5ed08da2015-01-22 11:08:04 -03002523 goto out_error_mem;
Arnaldo Carvalho de Meloe2726d92015-01-22 10:34:22 -03002524 }
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002525
2526 if ((trace->trace_pgfaults & TRACE_PFMIN) &&
2527 perf_evlist__add_pgfault(evlist, PERF_COUNT_SW_PAGE_FAULTS_MIN))
Arnaldo Carvalho de Melo5ed08da2015-01-22 11:08:04 -03002528 goto out_error_mem;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002529
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002530 if (trace->sched &&
Arnaldo Carvalho de Melo2cc990b2015-01-22 11:13:43 -03002531 perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime",
2532 trace__sched_stat_runtime))
2533 goto out_error_sched_stat_runtime;
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002534
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002535 err = perf_evlist__create_maps(evlist, &trace->opts.target);
2536 if (err < 0) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002537 fprintf(trace->output, "Problems parsing the target to trace, check your options!\n");
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002538 goto out_delete_evlist;
2539 }
2540
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03002541 err = trace__symbols_init(trace, evlist);
2542 if (err < 0) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002543 fprintf(trace->output, "Problems initializing symbol libraries!\n");
Arnaldo Carvalho de Melo03ad9742014-01-03 15:56:06 -03002544 goto out_delete_evlist;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03002545 }
2546
Arnaldo Carvalho de Melofde54b72016-04-11 18:42:37 -03002547 perf_evlist__config(evlist, &trace->opts, NULL);
2548
2549 if (trace->opts.callgraph_set && trace->syscalls.events.sys_exit) {
2550 perf_evsel__config_callchain(trace->syscalls.events.sys_exit,
2551 &trace->opts, &callchain_param);
2552 /*
2553 * Now we have evsels with different sample_ids, use
2554 * PERF_SAMPLE_IDENTIFIER to map from sample to evsel
2555 * from a fixed position in each ring buffer record.
2556 *
2557 * As of this the changeset introducing this comment, this
2558 * isn't strictly needed, as the fields that can come before
2559 * PERF_SAMPLE_ID are all used, but we'll probably disable
2560 * some of those for things like copying the payload of
2561 * pointer syscall arguments, and for vfs_getname we don't
2562 * need PERF_SAMPLE_ADDR and PERF_SAMPLE_IP, so do this
2563 * here as a warning we need to use PERF_SAMPLE_IDENTIFIER.
2564 */
2565 perf_evlist__set_sample_bit(evlist, IDENTIFIER);
2566 perf_evlist__reset_sample_bit(evlist, ID);
2567 }
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002568
Namhyung Kimf15eb532012-10-05 14:02:16 +09002569 signal(SIGCHLD, sig_handler);
2570 signal(SIGINT, sig_handler);
2571
2572 if (forks) {
Namhyung Kim6ef73ec2013-03-11 16:43:15 +09002573 err = perf_evlist__prepare_workload(evlist, &trace->opts.target,
Arnaldo Carvalho de Melo735f7e02014-01-03 14:56:49 -03002574 argv, false, NULL);
Namhyung Kimf15eb532012-10-05 14:02:16 +09002575 if (err < 0) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002576 fprintf(trace->output, "Couldn't run the workload!\n");
Arnaldo Carvalho de Melo03ad9742014-01-03 15:56:06 -03002577 goto out_delete_evlist;
Namhyung Kimf15eb532012-10-05 14:02:16 +09002578 }
2579 }
2580
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002581 err = perf_evlist__open(evlist);
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002582 if (err < 0)
2583 goto out_error_open;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002584
Wang Nanba504232016-02-26 09:31:54 +00002585 err = bpf__apply_obj_config();
2586 if (err) {
2587 char errbuf[BUFSIZ];
2588
2589 bpf__strerror_apply_obj_config(err, errbuf, sizeof(errbuf));
2590 pr_err("ERROR: Apply config to BPF failed: %s\n",
2591 errbuf);
2592 goto out_error_open;
2593 }
2594
Arnaldo Carvalho de Melo241b0572015-02-21 10:15:21 -08002595 /*
2596 * Better not use !target__has_task() here because we need to cover the
2597 * case where no threads were specified in the command line, but a
2598 * workload was, and in that case we will fill in the thread_map when
2599 * we fork the workload in perf_evlist__prepare_workload.
2600 */
Arnaldo Carvalho de Melof078c382015-02-21 11:36:52 -08002601 if (trace->filter_pids.nr > 0)
2602 err = perf_evlist__set_filter_pids(evlist, trace->filter_pids.nr, trace->filter_pids.entries);
Jiri Olsae13798c2015-06-23 00:36:02 +02002603 else if (thread_map__pid(evlist->threads, 0) == -1)
Arnaldo Carvalho de Melof078c382015-02-21 11:36:52 -08002604 err = perf_evlist__set_filter_pid(evlist, getpid());
2605
Arnaldo Carvalho de Melo94ad89b2015-07-03 17:42:03 -03002606 if (err < 0)
2607 goto out_error_mem;
2608
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002609 if (trace->ev_qualifier_ids.nr > 0) {
2610 err = trace__set_ev_qualifier_filter(trace);
2611 if (err < 0)
2612 goto out_errno;
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002613
Arnaldo Carvalho de Melo2e5e5f82015-08-03 17:12:29 -03002614 pr_debug("event qualifier tracepoint filter: %s\n",
2615 trace->syscalls.events.sys_exit->filter);
2616 }
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002617
Arnaldo Carvalho de Melo94ad89b2015-07-03 17:42:03 -03002618 err = perf_evlist__apply_filters(evlist, &evsel);
2619 if (err < 0)
2620 goto out_error_apply_filters;
Arnaldo Carvalho de Melo241b0572015-02-21 10:15:21 -08002621
Jiri Olsaf8850372013-11-28 17:57:22 +01002622 err = perf_evlist__mmap(evlist, trace->opts.mmap_pages, false);
Arnaldo Carvalho de Meloe09b18d2014-12-11 18:04:10 -03002623 if (err < 0)
2624 goto out_error_mmap;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002625
Arnaldo Carvalho de Melocb24d012015-04-22 10:04:23 -03002626 if (!target__none(&trace->opts.target))
2627 perf_evlist__enable(evlist);
2628
Namhyung Kimf15eb532012-10-05 14:02:16 +09002629 if (forks)
2630 perf_evlist__start_workload(evlist);
2631
Jiri Olsae13798c2015-06-23 00:36:02 +02002632 trace->multiple_threads = thread_map__pid(evlist->threads, 0) == -1 ||
Arnaldo Carvalho de Melo42052be2015-02-13 12:32:45 -03002633 evlist->threads->nr > 1 ||
2634 perf_evlist__first(evlist)->attr.inherit;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002635again:
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03002636 before = trace->nr_events;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002637
2638 for (i = 0; i < evlist->nr_mmaps; i++) {
2639 union perf_event *event;
2640
2641 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002642 struct perf_sample sample;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002643
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03002644 ++trace->nr_events;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002645
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002646 err = perf_evlist__parse_sample(evlist, event, &sample);
2647 if (err) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002648 fprintf(trace->output, "Can't parse sample, err = %d, skipping...\n", err);
Zhouyi Zhou8e50d382013-10-24 15:43:33 +08002649 goto next_event;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002650 }
2651
Arnaldo Carvalho de Meloddbb1b12015-02-21 12:10:29 -08002652 trace__handle_event(trace, event, &sample);
Zhouyi Zhou8e50d382013-10-24 15:43:33 +08002653next_event:
2654 perf_evlist__mmap_consume(evlist, i);
Arnaldo Carvalho de Melo20c5f102013-09-03 11:55:07 -03002655
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002656 if (interrupted)
2657 goto out_disable;
Arnaldo Carvalho de Melo02ac5422015-04-22 11:11:57 -03002658
2659 if (done && !draining) {
2660 perf_evlist__disable(evlist);
2661 draining = true;
2662 }
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002663 }
2664 }
2665
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03002666 if (trace->nr_events == before) {
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002667 int timeout = done ? 100 : -1;
Namhyung Kimf15eb532012-10-05 14:02:16 +09002668
Arnaldo Carvalho de Melo46fb3c22014-09-22 14:39:48 -03002669 if (!draining && perf_evlist__poll(evlist, timeout) > 0) {
2670 if (perf_evlist__filter_pollfd(evlist, POLLERR | POLLHUP) == 0)
2671 draining = true;
2672
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002673 goto again;
Arnaldo Carvalho de Melo46fb3c22014-09-22 14:39:48 -03002674 }
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002675 } else {
2676 goto again;
Namhyung Kimf15eb532012-10-05 14:02:16 +09002677 }
2678
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002679out_disable:
Arnaldo Carvalho de Melof3b623b2015-03-02 22:21:35 -03002680 thread__zput(trace->current);
2681
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002682 perf_evlist__disable(evlist);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002683
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002684 if (!err) {
2685 if (trace->summary)
2686 trace__fprintf_thread_summary(trace, trace->output);
2687
2688 if (trace->show_tool_stats) {
2689 fprintf(trace->output, "Stats:\n "
2690 " vfs_getname : %" PRIu64 "\n"
2691 " proc_getname: %" PRIu64 "\n",
2692 trace->stats.vfs_getname,
2693 trace->stats.proc_getname);
2694 }
2695 }
David Ahernbf2575c2013-10-08 21:26:53 -06002696
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002697out_delete_evlist:
2698 perf_evlist__delete(evlist);
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002699 trace->evlist = NULL;
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03002700 trace->live = false;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002701 return err;
Arnaldo Carvalho de Melo6ef068c2013-10-17 12:07:58 -03002702{
2703 char errbuf[BUFSIZ];
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002704
Arnaldo Carvalho de Melo2cc990b2015-01-22 11:13:43 -03002705out_error_sched_stat_runtime:
Jiri Olsa988bdb32015-09-02 09:56:35 +02002706 tracing_path__strerror_open_tp(errno, errbuf, sizeof(errbuf), "sched", "sched_stat_runtime");
Arnaldo Carvalho de Melo2cc990b2015-01-22 11:13:43 -03002707 goto out_error;
2708
Arnaldo Carvalho de Melo801c67b2015-01-22 10:52:55 -03002709out_error_raw_syscalls:
Jiri Olsa988bdb32015-09-02 09:56:35 +02002710 tracing_path__strerror_open_tp(errno, errbuf, sizeof(errbuf), "raw_syscalls", "sys_(enter|exit)");
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002711 goto out_error;
2712
Arnaldo Carvalho de Meloe09b18d2014-12-11 18:04:10 -03002713out_error_mmap:
2714 perf_evlist__strerror_mmap(evlist, errno, errbuf, sizeof(errbuf));
2715 goto out_error;
2716
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002717out_error_open:
2718 perf_evlist__strerror_open(evlist, errno, errbuf, sizeof(errbuf));
2719
2720out_error:
Arnaldo Carvalho de Melo6ef068c2013-10-17 12:07:58 -03002721 fprintf(trace->output, "%s\n", errbuf);
Ramkumar Ramachandra87f91862013-10-04 10:47:31 +05302722 goto out_delete_evlist;
Arnaldo Carvalho de Melo94ad89b2015-07-03 17:42:03 -03002723
2724out_error_apply_filters:
2725 fprintf(trace->output,
2726 "Failed to set filter \"%s\" on event %s with %d (%s)\n",
2727 evsel->filter, perf_evsel__name(evsel), errno,
2728 strerror_r(errno, errbuf, sizeof(errbuf)));
2729 goto out_delete_evlist;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002730}
Arnaldo Carvalho de Melo5ed08da2015-01-22 11:08:04 -03002731out_error_mem:
2732 fprintf(trace->output, "Not enough memory to run!\n");
2733 goto out_delete_evlist;
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002734
2735out_errno:
2736 fprintf(trace->output, "errno=%d,%s\n", errno, strerror(errno));
2737 goto out_delete_evlist;
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002738}
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002739
David Ahern6810fc92013-08-28 22:29:52 -06002740static int trace__replay(struct trace *trace)
2741{
2742 const struct perf_evsel_str_handler handlers[] = {
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002743 { "probe:vfs_getname", trace__vfs_getname, },
David Ahern6810fc92013-08-28 22:29:52 -06002744 };
Jiri Olsaf5fc14122013-10-15 16:27:32 +02002745 struct perf_data_file file = {
2746 .path = input_name,
2747 .mode = PERF_DATA_MODE_READ,
Yunlong Songe366a6d2015-04-02 21:47:18 +08002748 .force = trace->force,
Jiri Olsaf5fc14122013-10-15 16:27:32 +02002749 };
David Ahern6810fc92013-08-28 22:29:52 -06002750 struct perf_session *session;
Namhyung Kim003824e2013-11-12 15:25:00 +09002751 struct perf_evsel *evsel;
David Ahern6810fc92013-08-28 22:29:52 -06002752 int err = -1;
2753
2754 trace->tool.sample = trace__process_sample;
2755 trace->tool.mmap = perf_event__process_mmap;
David Ahern384c6712013-09-22 19:44:58 -06002756 trace->tool.mmap2 = perf_event__process_mmap2;
David Ahern6810fc92013-08-28 22:29:52 -06002757 trace->tool.comm = perf_event__process_comm;
2758 trace->tool.exit = perf_event__process_exit;
2759 trace->tool.fork = perf_event__process_fork;
2760 trace->tool.attr = perf_event__process_attr;
2761 trace->tool.tracing_data = perf_event__process_tracing_data;
2762 trace->tool.build_id = perf_event__process_build_id;
2763
Jiri Olsa0a8cb852014-07-06 14:18:21 +02002764 trace->tool.ordered_events = true;
David Ahern6810fc92013-08-28 22:29:52 -06002765 trace->tool.ordering_requires_timestamps = true;
2766
2767 /* add tid to output */
2768 trace->multiple_threads = true;
2769
Jiri Olsaf5fc14122013-10-15 16:27:32 +02002770 session = perf_session__new(&file, false, &trace->tool);
David Ahern6810fc92013-08-28 22:29:52 -06002771 if (session == NULL)
Taeung Song52e028342014-09-24 10:33:37 +09002772 return -1;
David Ahern6810fc92013-08-28 22:29:52 -06002773
Namhyung Kim0a7e6d12014-08-12 15:40:45 +09002774 if (symbol__init(&session->header.env) < 0)
Namhyung Kimcb2ffae2014-08-12 15:40:44 +09002775 goto out;
2776
David Ahern8fb598e2013-09-28 13:13:00 -06002777 trace->host = &session->machines.host;
2778
David Ahern6810fc92013-08-28 22:29:52 -06002779 err = perf_session__set_tracepoints_handlers(session, handlers);
2780 if (err)
2781 goto out;
2782
Namhyung Kim003824e2013-11-12 15:25:00 +09002783 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2784 "raw_syscalls:sys_enter");
David Ahern9aca7f12013-12-04 19:41:39 -07002785 /* older kernels have syscalls tp versus raw_syscalls */
2786 if (evsel == NULL)
2787 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2788 "syscalls:sys_enter");
David Ahern6810fc92013-08-28 22:29:52 -06002789
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002790 if (evsel &&
2791 (perf_evsel__init_syscall_tp(evsel, trace__sys_enter) < 0 ||
2792 perf_evsel__init_sc_tp_ptr_field(evsel, args))) {
Namhyung Kim003824e2013-11-12 15:25:00 +09002793 pr_err("Error during initialize raw_syscalls:sys_enter event\n");
2794 goto out;
2795 }
2796
2797 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2798 "raw_syscalls:sys_exit");
David Ahern9aca7f12013-12-04 19:41:39 -07002799 if (evsel == NULL)
2800 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2801 "syscalls:sys_exit");
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002802 if (evsel &&
2803 (perf_evsel__init_syscall_tp(evsel, trace__sys_exit) < 0 ||
2804 perf_evsel__init_sc_tp_uint_field(evsel, ret))) {
Namhyung Kim003824e2013-11-12 15:25:00 +09002805 pr_err("Error during initialize raw_syscalls:sys_exit event\n");
David Ahern6810fc92013-08-28 22:29:52 -06002806 goto out;
2807 }
2808
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002809 evlist__for_each(session->evlist, evsel) {
2810 if (evsel->attr.type == PERF_TYPE_SOFTWARE &&
2811 (evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ||
2812 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MIN ||
2813 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS))
2814 evsel->handler = trace__pgfault;
2815 }
2816
David Ahernbdc89662013-08-28 22:29:53 -06002817 err = parse_target_str(trace);
2818 if (err != 0)
2819 goto out;
2820
David Ahern6810fc92013-08-28 22:29:52 -06002821 setup_pager();
2822
Arnaldo Carvalho de Melob7b61cb2015-03-03 11:58:45 -03002823 err = perf_session__process_events(session);
David Ahern6810fc92013-08-28 22:29:52 -06002824 if (err)
2825 pr_err("Failed to process events, error %d", err);
2826
David Ahernbf2575c2013-10-08 21:26:53 -06002827 else if (trace->summary)
2828 trace__fprintf_thread_summary(trace, trace->output);
2829
David Ahern6810fc92013-08-28 22:29:52 -06002830out:
2831 perf_session__delete(session);
2832
2833 return err;
2834}
2835
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002836static size_t trace__fprintf_threads_header(FILE *fp)
2837{
2838 size_t printed;
2839
Pekka Enberg99ff7152013-11-12 16:42:14 +02002840 printed = fprintf(fp, "\n Summary of events:\n\n");
David Ahernbf2575c2013-10-08 21:26:53 -06002841
2842 return printed;
2843}
2844
2845static size_t thread__dump_stats(struct thread_trace *ttrace,
2846 struct trace *trace, FILE *fp)
2847{
2848 struct stats *stats;
2849 size_t printed = 0;
2850 struct syscall *sc;
2851 struct int_node *inode = intlist__first(ttrace->syscall_stats);
2852
2853 if (inode == NULL)
2854 return 0;
2855
2856 printed += fprintf(fp, "\n");
2857
Milian Wolff834fd462015-08-06 11:24:29 +02002858 printed += fprintf(fp, " syscall calls total min avg max stddev\n");
2859 printed += fprintf(fp, " (msec) (msec) (msec) (msec) (%%)\n");
2860 printed += fprintf(fp, " --------------- -------- --------- --------- --------- --------- ------\n");
Pekka Enberg99ff7152013-11-12 16:42:14 +02002861
David Ahernbf2575c2013-10-08 21:26:53 -06002862 /* each int_node is a syscall */
2863 while (inode) {
2864 stats = inode->priv;
2865 if (stats) {
2866 double min = (double)(stats->min) / NSEC_PER_MSEC;
2867 double max = (double)(stats->max) / NSEC_PER_MSEC;
2868 double avg = avg_stats(stats);
2869 double pct;
2870 u64 n = (u64) stats->n;
2871
2872 pct = avg ? 100.0 * stddev_stats(stats)/avg : 0.0;
2873 avg /= NSEC_PER_MSEC;
2874
2875 sc = &trace->syscalls.table[inode->i];
Pekka Enberg99ff7152013-11-12 16:42:14 +02002876 printed += fprintf(fp, " %-15s", sc->name);
Milian Wolff834fd462015-08-06 11:24:29 +02002877 printed += fprintf(fp, " %8" PRIu64 " %9.3f %9.3f %9.3f",
2878 n, avg * n, min, avg);
Pekka Enberg27a778b2013-11-13 14:21:48 +02002879 printed += fprintf(fp, " %9.3f %9.2f%%\n", max, pct);
David Ahernbf2575c2013-10-08 21:26:53 -06002880 }
2881
2882 inode = intlist__next(inode);
2883 }
2884
2885 printed += fprintf(fp, "\n\n");
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002886
2887 return printed;
2888}
2889
David Ahern896cbb52013-09-28 13:12:59 -06002890/* struct used to pass data to per-thread function */
2891struct summary_data {
2892 FILE *fp;
2893 struct trace *trace;
2894 size_t printed;
2895};
2896
2897static int trace__fprintf_one_thread(struct thread *thread, void *priv)
2898{
2899 struct summary_data *data = priv;
2900 FILE *fp = data->fp;
2901 size_t printed = data->printed;
2902 struct trace *trace = data->trace;
Namhyung Kim89dceb22014-10-06 09:46:03 +09002903 struct thread_trace *ttrace = thread__priv(thread);
David Ahern896cbb52013-09-28 13:12:59 -06002904 double ratio;
2905
2906 if (ttrace == NULL)
2907 return 0;
2908
2909 ratio = (double)ttrace->nr_events / trace->nr_events * 100.0;
2910
Pekka Enberg15e65c62013-11-14 18:43:30 +02002911 printed += fprintf(fp, " %s (%d), ", thread__comm_str(thread), thread->tid);
Pekka Enberg99ff7152013-11-12 16:42:14 +02002912 printed += fprintf(fp, "%lu events, ", ttrace->nr_events);
Pekka Enberg15e65c62013-11-14 18:43:30 +02002913 printed += fprintf(fp, "%.1f%%", ratio);
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04002914 if (ttrace->pfmaj)
2915 printed += fprintf(fp, ", %lu majfaults", ttrace->pfmaj);
2916 if (ttrace->pfmin)
2917 printed += fprintf(fp, ", %lu minfaults", ttrace->pfmin);
Pekka Enberg99ff7152013-11-12 16:42:14 +02002918 printed += fprintf(fp, ", %.3f msec\n", ttrace->runtime_ms);
David Ahernbf2575c2013-10-08 21:26:53 -06002919 printed += thread__dump_stats(ttrace, trace, fp);
David Ahern896cbb52013-09-28 13:12:59 -06002920
2921 data->printed += printed;
2922
2923 return 0;
2924}
2925
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002926static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp)
2927{
David Ahern896cbb52013-09-28 13:12:59 -06002928 struct summary_data data = {
2929 .fp = fp,
2930 .trace = trace
2931 };
2932 data.printed = trace__fprintf_threads_header(fp);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002933
David Ahern896cbb52013-09-28 13:12:59 -06002934 machine__for_each_thread(trace->host, trace__fprintf_one_thread, &data);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002935
David Ahern896cbb52013-09-28 13:12:59 -06002936 return data.printed;
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002937}
2938
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03002939static int trace__set_duration(const struct option *opt, const char *str,
2940 int unset __maybe_unused)
2941{
2942 struct trace *trace = opt->value;
2943
2944 trace->duration_filter = atof(str);
2945 return 0;
2946}
2947
Arnaldo Carvalho de Melof078c382015-02-21 11:36:52 -08002948static int trace__set_filter_pids(const struct option *opt, const char *str,
2949 int unset __maybe_unused)
2950{
2951 int ret = -1;
2952 size_t i;
2953 struct trace *trace = opt->value;
2954 /*
2955 * FIXME: introduce a intarray class, plain parse csv and create a
2956 * { int nr, int entries[] } struct...
2957 */
2958 struct intlist *list = intlist__new(str);
2959
2960 if (list == NULL)
2961 return -1;
2962
2963 i = trace->filter_pids.nr = intlist__nr_entries(list) + 1;
2964 trace->filter_pids.entries = calloc(i, sizeof(pid_t));
2965
2966 if (trace->filter_pids.entries == NULL)
2967 goto out;
2968
2969 trace->filter_pids.entries[0] = getpid();
2970
2971 for (i = 1; i < trace->filter_pids.nr; ++i)
2972 trace->filter_pids.entries[i] = intlist__entry(list, i - 1)->i;
2973
2974 intlist__delete(list);
2975 ret = 0;
2976out:
2977 return ret;
2978}
2979
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002980static int trace__open_output(struct trace *trace, const char *filename)
2981{
2982 struct stat st;
2983
2984 if (!stat(filename, &st) && st.st_size) {
2985 char oldname[PATH_MAX];
2986
2987 scnprintf(oldname, sizeof(oldname), "%s.old", filename);
2988 unlink(oldname);
2989 rename(filename, oldname);
2990 }
2991
2992 trace->output = fopen(filename, "w");
2993
2994 return trace->output == NULL ? -errno : 0;
2995}
2996
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002997static int parse_pagefaults(const struct option *opt, const char *str,
2998 int unset __maybe_unused)
2999{
3000 int *trace_pgfaults = opt->value;
3001
3002 if (strcmp(str, "all") == 0)
3003 *trace_pgfaults |= TRACE_PFMAJ | TRACE_PFMIN;
3004 else if (strcmp(str, "maj") == 0)
3005 *trace_pgfaults |= TRACE_PFMAJ;
3006 else if (strcmp(str, "min") == 0)
3007 *trace_pgfaults |= TRACE_PFMIN;
3008 else
3009 return -1;
3010
3011 return 0;
3012}
3013
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003014static void evlist__set_evsel_handler(struct perf_evlist *evlist, void *handler)
3015{
3016 struct perf_evsel *evsel;
3017
3018 evlist__for_each(evlist, evsel)
3019 evsel->handler = handler;
3020}
3021
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003022int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
3023{
Yunlong Song6fdd9cb2015-03-18 21:35:57 +08003024 const char *trace_usage[] = {
Namhyung Kimf15eb532012-10-05 14:02:16 +09003025 "perf trace [<options>] [<command>]",
3026 "perf trace [<options>] -- <command> [<options>]",
David Ahern5e2485b2013-09-28 13:13:01 -06003027 "perf trace record [<options>] [<command>]",
3028 "perf trace record [<options>] -- <command> [<options>]",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003029 NULL
3030 };
3031 struct trace trace = {
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003032 .syscalls = {
3033 . max = -1,
3034 },
3035 .opts = {
3036 .target = {
3037 .uid = UINT_MAX,
3038 .uses_mmap = true,
3039 },
3040 .user_freq = UINT_MAX,
3041 .user_interval = ULLONG_MAX,
Arnaldo Carvalho de Melo509051e2014-01-14 17:52:14 -03003042 .no_buffering = true,
Arnaldo Carvalho de Melo38d54472014-12-12 17:28:32 -03003043 .mmap_pages = UINT_MAX,
Kan Liang9d9cad72015-06-17 09:51:11 -04003044 .proc_map_timeout = 500,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003045 },
Milian Wolff007d66a2015-08-05 16:52:23 -03003046 .output = stderr,
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -03003047 .show_comm = true,
Stanislav Fomicheve281a962014-06-26 20:14:28 +04003048 .trace_syscalls = true,
Arnaldo Carvalho de Melo44621812016-04-11 15:49:11 -03003049 .kernel_syscallchains = false,
Arnaldo Carvalho de Meloc6d4a492016-04-14 18:29:08 -03003050 .max_stack = PERF_MAX_STACK_DEPTH,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003051 };
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003052 const char *output_name = NULL;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03003053 const char *ev_qualifier_str = NULL;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003054 const struct option trace_options[] = {
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003055 OPT_CALLBACK(0, "event", &trace.evlist, "event",
3056 "event selector. use 'perf list' to list available events",
3057 parse_events_option),
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -03003058 OPT_BOOLEAN(0, "comm", &trace.show_comm,
3059 "show the thread COMM next to its id"),
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03003060 OPT_BOOLEAN(0, "tool_stats", &trace.show_tool_stats, "show tool stats"),
Arnaldo Carvalho de Melod303e852015-04-23 12:02:07 -03003061 OPT_STRING('e', "expr", &ev_qualifier_str, "expr", "list of syscalls to trace"),
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003062 OPT_STRING('o', "output", &output_name, "file", "output file name"),
David Ahern6810fc92013-08-28 22:29:52 -06003063 OPT_STRING('i', "input", &input_name, "file", "Analyze events in file"),
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003064 OPT_STRING('p', "pid", &trace.opts.target.pid, "pid",
3065 "trace events on existing process id"),
David Ahernac9be8e2013-08-20 11:15:45 -06003066 OPT_STRING('t', "tid", &trace.opts.target.tid, "tid",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003067 "trace events on existing thread id"),
Arnaldo Carvalho de Melofa0e4ff2015-04-23 11:59:20 -03003068 OPT_CALLBACK(0, "filter-pids", &trace, "CSV list of pids",
3069 "pids to filter (by the kernel)", trace__set_filter_pids),
David Ahernac9be8e2013-08-20 11:15:45 -06003070 OPT_BOOLEAN('a', "all-cpus", &trace.opts.target.system_wide,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003071 "system-wide collection from all CPUs"),
David Ahernac9be8e2013-08-20 11:15:45 -06003072 OPT_STRING('C', "cpu", &trace.opts.target.cpu_list, "cpu",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003073 "list of cpus to monitor"),
David Ahern6810fc92013-08-28 22:29:52 -06003074 OPT_BOOLEAN(0, "no-inherit", &trace.opts.no_inherit,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003075 "child tasks do not inherit counters"),
Jiri Olsa994a1f72013-09-01 12:36:12 +02003076 OPT_CALLBACK('m', "mmap-pages", &trace.opts.mmap_pages, "pages",
3077 "number of mmap data pages",
3078 perf_evlist__parse_mmap_pages),
David Ahernac9be8e2013-08-20 11:15:45 -06003079 OPT_STRING('u', "uid", &trace.opts.target.uid_str, "user",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003080 "user to profile"),
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03003081 OPT_CALLBACK(0, "duration", &trace, "float",
3082 "show only events with duration > N.M ms",
3083 trace__set_duration),
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03003084 OPT_BOOLEAN(0, "sched", &trace.sched, "show blocking scheduler events"),
Arnaldo Carvalho de Melo7c304ee02013-08-22 16:49:54 -03003085 OPT_INCR('v', "verbose", &verbose, "be more verbose"),
David Ahern4bb09192013-09-04 12:37:43 -06003086 OPT_BOOLEAN('T', "time", &trace.full_time,
3087 "Show full timestamp, not time relative to first start"),
David Ahernfd2eaba2013-11-12 09:31:15 -07003088 OPT_BOOLEAN('s', "summary", &trace.summary_only,
3089 "Show only syscall summary with statistics"),
3090 OPT_BOOLEAN('S', "with-summary", &trace.summary,
3091 "Show all syscalls and summary with statistics"),
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04003092 OPT_CALLBACK_DEFAULT('F', "pf", &trace.trace_pgfaults, "all|maj|min",
3093 "Trace pagefaults", parse_pagefaults, "maj"),
Stanislav Fomicheve281a962014-06-26 20:14:28 +04003094 OPT_BOOLEAN(0, "syscalls", &trace.trace_syscalls, "Trace syscalls"),
Yunlong Songe366a6d2015-04-02 21:47:18 +08003095 OPT_BOOLEAN('f', "force", &trace.force, "don't complain, do it"),
Milian Wolff566a0882016-04-08 13:34:15 +02003096 OPT_CALLBACK(0, "call-graph", &trace.opts,
3097 "record_mode[,record_size]", record_callchain_help,
3098 &record_parse_callchain_opt),
Arnaldo Carvalho de Melo44621812016-04-11 15:49:11 -03003099 OPT_BOOLEAN(0, "kernel-syscall-graph", &trace.kernel_syscallchains,
3100 "Show the kernel callchains on the syscall exit path"),
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -03003101 OPT_UINTEGER(0, "min-stack", &trace.min_stack,
3102 "Set the minimum stack depth when parsing the callchain, "
3103 "anything below the specified depth will be ignored."),
Arnaldo Carvalho de Meloc6d4a492016-04-14 18:29:08 -03003104 OPT_UINTEGER(0, "max-stack", &trace.max_stack,
3105 "Set the maximum stack depth when parsing the callchain, "
3106 "anything beyond the specified depth will be ignored. "
3107 "Default: " __stringify(PERF_MAX_STACK_DEPTH)),
Kan Liang9d9cad72015-06-17 09:51:11 -04003108 OPT_UINTEGER(0, "proc-map-timeout", &trace.opts.proc_map_timeout,
3109 "per thread proc mmap processing timeout in ms"),
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003110 OPT_END()
3111 };
Yunlong Song6fdd9cb2015-03-18 21:35:57 +08003112 const char * const trace_subcommands[] = { "record", NULL };
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003113 int err;
Namhyung Kim32caf0d2012-10-05 14:02:13 +09003114 char bf[BUFSIZ];
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003115
Arnaldo Carvalho de Melo4d08cb82015-02-24 15:35:55 -03003116 signal(SIGSEGV, sighandler_dump_stack);
3117 signal(SIGFPE, sighandler_dump_stack);
3118
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003119 trace.evlist = perf_evlist__new();
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03003120 trace.sctbl = syscalltbl__new();
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003121
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03003122 if (trace.evlist == NULL || trace.sctbl == NULL) {
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003123 pr_err("Not enough memory to run!\n");
He Kuangff8f6952015-05-11 12:28:36 +00003124 err = -ENOMEM;
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003125 goto out;
3126 }
3127
Yunlong Song6fdd9cb2015-03-18 21:35:57 +08003128 argc = parse_options_subcommand(argc, argv, trace_options, trace_subcommands,
3129 trace_usage, PARSE_OPT_STOP_AT_NON_OPTION);
David Ahernfd2eaba2013-11-12 09:31:15 -07003130
Wang Nand7888572016-04-08 15:07:24 +00003131 err = bpf__setup_stdout(trace.evlist);
3132 if (err) {
3133 bpf__strerror_setup_stdout(trace.evlist, err, bf, sizeof(bf));
3134 pr_err("ERROR: Setup BPF stdout failed: %s\n", bf);
3135 goto out;
3136 }
3137
Arnaldo Carvalho de Melo59247e32016-04-12 16:05:02 -03003138 err = -1;
3139
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04003140 if (trace.trace_pgfaults) {
3141 trace.opts.sample_address = true;
3142 trace.opts.sample_time = true;
3143 }
3144
Milian Wolff566a0882016-04-08 13:34:15 +02003145 if (trace.opts.callgraph_set)
3146 symbol_conf.use_callchain = true;
3147
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003148 if (trace.evlist->nr_entries > 0)
3149 evlist__set_evsel_handler(trace.evlist, trace__event_handler);
3150
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04003151 if ((argc >= 1) && (strcmp(argv[0], "record") == 0))
3152 return trace__record(&trace, argc-1, &argv[1]);
3153
3154 /* summary_only implies summary option, but don't overwrite summary if set */
3155 if (trace.summary_only)
3156 trace.summary = trace.summary_only;
3157
Arnaldo Carvalho de Melo726f3232015-02-06 10:16:45 +01003158 if (!trace.trace_syscalls && !trace.trace_pgfaults &&
3159 trace.evlist->nr_entries == 0 /* Was --events used? */) {
Stanislav Fomicheve281a962014-06-26 20:14:28 +04003160 pr_err("Please specify something to trace.\n");
3161 return -1;
3162 }
3163
Arnaldo Carvalho de Melo59247e32016-04-12 16:05:02 -03003164 if (!trace.trace_syscalls && ev_qualifier_str) {
3165 pr_err("The -e option can't be used with --no-syscalls.\n");
3166 goto out;
3167 }
3168
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003169 if (output_name != NULL) {
3170 err = trace__open_output(&trace, output_name);
3171 if (err < 0) {
3172 perror("failed to create output file");
3173 goto out;
3174 }
3175 }
3176
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03003177 trace.open_id = syscalltbl__id(trace.sctbl, "open");
3178
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03003179 if (ev_qualifier_str != NULL) {
Arnaldo Carvalho de Melob059efd2013-08-21 12:56:21 -03003180 const char *s = ev_qualifier_str;
Arnaldo Carvalho de Melo005438a82015-07-20 12:02:09 -03003181 struct strlist_config slist_config = {
3182 .dirname = system_path(STRACE_GROUPS_DIR),
3183 };
Arnaldo Carvalho de Melob059efd2013-08-21 12:56:21 -03003184
3185 trace.not_ev_qualifier = *s == '!';
3186 if (trace.not_ev_qualifier)
3187 ++s;
Arnaldo Carvalho de Melo005438a82015-07-20 12:02:09 -03003188 trace.ev_qualifier = strlist__new(s, &slist_config);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03003189 if (trace.ev_qualifier == NULL) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003190 fputs("Not enough memory to parse event qualifier",
3191 trace.output);
3192 err = -ENOMEM;
3193 goto out_close;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03003194 }
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03003195
3196 err = trace__validate_ev_qualifier(&trace);
3197 if (err)
3198 goto out_close;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03003199 }
3200
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003201 err = target__validate(&trace.opts.target);
Namhyung Kim32caf0d2012-10-05 14:02:13 +09003202 if (err) {
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003203 target__strerror(&trace.opts.target, err, bf, sizeof(bf));
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003204 fprintf(trace.output, "%s", bf);
3205 goto out_close;
Namhyung Kim32caf0d2012-10-05 14:02:13 +09003206 }
3207
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003208 err = target__parse_uid(&trace.opts.target);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003209 if (err) {
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003210 target__strerror(&trace.opts.target, err, bf, sizeof(bf));
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003211 fprintf(trace.output, "%s", bf);
3212 goto out_close;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003213 }
3214
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003215 if (!argc && target__none(&trace.opts.target))
Namhyung Kimee761202012-10-05 14:02:14 +09003216 trace.opts.target.system_wide = true;
3217
David Ahern6810fc92013-08-28 22:29:52 -06003218 if (input_name)
3219 err = trace__replay(&trace);
3220 else
3221 err = trace__run(&trace, argc, argv);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03003222
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003223out_close:
3224 if (output_name != NULL)
3225 fclose(trace.output);
3226out:
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03003227 return err;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003228}