blob: a4b133fac82bae09a9ce1eee2bf8112ea0294f6f [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{
Arnaldo Carvalho de Melo7ad35612016-04-20 19:55:48 -03002129 int callchain_ret = 0;
2130
2131 if (sample->callchain) {
2132 callchain_ret = trace__resolve_callchain(trace, evsel, sample, &callchain_cursor);
2133 if (callchain_ret == 0) {
2134 if (callchain_cursor.nr < trace->min_stack)
2135 goto out;
2136 callchain_ret = 1;
2137 }
2138 }
2139
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002140 trace__printf_interrupted_entry(trace, sample);
2141 trace__fprintf_tstamp(trace, sample->time, trace->output);
Arnaldo Carvalho de Melo08089212015-02-19 21:51:50 -08002142
2143 if (trace->trace_syscalls)
2144 fprintf(trace->output, "( ): ");
2145
2146 fprintf(trace->output, "%s:", evsel->name);
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002147
Wang Nan1d6c9402016-02-26 09:31:55 +00002148 if (perf_evsel__is_bpf_output(evsel)) {
2149 bpf_output__fprintf(trace, sample);
2150 } else if (evsel->tp_format) {
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002151 event_format__fprintf(evsel->tp_format, sample->cpu,
2152 sample->raw_data, sample->raw_size,
2153 trace->output);
2154 }
2155
2156 fprintf(trace->output, ")\n");
Arnaldo Carvalho de Melo202ff962016-04-12 10:11:07 -03002157
Arnaldo Carvalho de Melo7ad35612016-04-20 19:55:48 -03002158 if (callchain_ret > 0)
2159 trace__fprintf_callchain(trace, sample);
2160 else if (callchain_ret < 0)
2161 pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel));
2162out:
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002163 return 0;
2164}
2165
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002166static void print_location(FILE *f, struct perf_sample *sample,
2167 struct addr_location *al,
2168 bool print_dso, bool print_sym)
2169{
2170
2171 if ((verbose || print_dso) && al->map)
2172 fprintf(f, "%s@", al->map->dso->long_name);
2173
2174 if ((verbose || print_sym) && al->sym)
Arnaldo Carvalho de Melo4414a3c2014-07-08 15:39:21 -03002175 fprintf(f, "%s+0x%" PRIx64, al->sym->name,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002176 al->addr - al->sym->start);
2177 else if (al->map)
Arnaldo Carvalho de Melo4414a3c2014-07-08 15:39:21 -03002178 fprintf(f, "0x%" PRIx64, al->addr);
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002179 else
Arnaldo Carvalho de Melo4414a3c2014-07-08 15:39:21 -03002180 fprintf(f, "0x%" PRIx64, sample->addr);
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002181}
2182
2183static int trace__pgfault(struct trace *trace,
2184 struct perf_evsel *evsel,
Arnaldo Carvalho de Melo473398a2016-03-22 18:23:43 -03002185 union perf_event *event __maybe_unused,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002186 struct perf_sample *sample)
2187{
2188 struct thread *thread;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002189 struct addr_location al;
2190 char map_type = 'd';
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04002191 struct thread_trace *ttrace;
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002192 int err = -1;
Arnaldo Carvalho de Melo1df54292016-04-20 20:06:02 -03002193 int callchain_ret = 0;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002194
2195 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
Arnaldo Carvalho de Melo1df54292016-04-20 20:06:02 -03002196
2197 if (sample->callchain) {
2198 callchain_ret = trace__resolve_callchain(trace, evsel, sample, &callchain_cursor);
2199 if (callchain_ret == 0) {
2200 if (callchain_cursor.nr < trace->min_stack)
2201 goto out_put;
2202 callchain_ret = 1;
2203 }
2204 }
2205
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04002206 ttrace = thread__trace(thread, trace->output);
2207 if (ttrace == NULL)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002208 goto out_put;
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04002209
2210 if (evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ)
2211 ttrace->pfmaj++;
2212 else
2213 ttrace->pfmin++;
2214
2215 if (trace->summary_only)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002216 goto out;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002217
Arnaldo Carvalho de Melo473398a2016-03-22 18:23:43 -03002218 thread__find_addr_location(thread, sample->cpumode, MAP__FUNCTION,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002219 sample->ip, &al);
2220
2221 trace__fprintf_entry_head(trace, thread, 0, sample->time, trace->output);
2222
2223 fprintf(trace->output, "%sfault [",
2224 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ?
2225 "maj" : "min");
2226
2227 print_location(trace->output, sample, &al, false, true);
2228
2229 fprintf(trace->output, "] => ");
2230
Arnaldo Carvalho de Melo473398a2016-03-22 18:23:43 -03002231 thread__find_addr_location(thread, sample->cpumode, MAP__VARIABLE,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002232 sample->addr, &al);
2233
2234 if (!al.map) {
Arnaldo Carvalho de Melo473398a2016-03-22 18:23:43 -03002235 thread__find_addr_location(thread, sample->cpumode,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002236 MAP__FUNCTION, sample->addr, &al);
2237
2238 if (al.map)
2239 map_type = 'x';
2240 else
2241 map_type = '?';
2242 }
2243
2244 print_location(trace->output, sample, &al, true, false);
2245
2246 fprintf(trace->output, " (%c%c)\n", map_type, al.level);
Arnaldo Carvalho de Melo0c3a6ef2016-04-19 16:31:12 -03002247
Arnaldo Carvalho de Melo1df54292016-04-20 20:06:02 -03002248 if (callchain_ret > 0)
2249 trace__fprintf_callchain(trace, sample);
2250 else if (callchain_ret < 0)
2251 pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel));
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002252out:
2253 err = 0;
2254out_put:
2255 thread__put(thread);
2256 return err;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002257}
2258
David Ahernbdc89662013-08-28 22:29:53 -06002259static bool skip_sample(struct trace *trace, struct perf_sample *sample)
2260{
2261 if ((trace->pid_list && intlist__find(trace->pid_list, sample->pid)) ||
2262 (trace->tid_list && intlist__find(trace->tid_list, sample->tid)))
2263 return false;
2264
2265 if (trace->pid_list || trace->tid_list)
2266 return true;
2267
2268 return false;
2269}
2270
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03002271static void trace__set_base_time(struct trace *trace,
Arnaldo Carvalho de Melo8a07a802016-03-31 15:19:39 -03002272 struct perf_evsel *evsel,
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03002273 struct perf_sample *sample)
2274{
Arnaldo Carvalho de Melo8a07a802016-03-31 15:19:39 -03002275 /*
2276 * BPF events were not setting PERF_SAMPLE_TIME, so be more robust
2277 * and don't use sample->time unconditionally, we may end up having
2278 * some other event in the future without PERF_SAMPLE_TIME for good
2279 * reason, i.e. we may not be interested in its timestamps, just in
2280 * it taking place, picking some piece of information when it
2281 * appears in our event stream (vfs_getname comes to mind).
2282 */
2283 if (trace->base_time == 0 && !trace->full_time &&
2284 (evsel->attr.sample_type & PERF_SAMPLE_TIME))
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03002285 trace->base_time = sample->time;
2286}
2287
David Ahern6810fc92013-08-28 22:29:52 -06002288static int trace__process_sample(struct perf_tool *tool,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04002289 union perf_event *event,
David Ahern6810fc92013-08-28 22:29:52 -06002290 struct perf_sample *sample,
2291 struct perf_evsel *evsel,
2292 struct machine *machine __maybe_unused)
2293{
2294 struct trace *trace = container_of(tool, struct trace, tool);
2295 int err = 0;
2296
Arnaldo Carvalho de Melo744a9712013-11-06 10:17:38 -03002297 tracepoint_handler handler = evsel->handler;
David Ahern6810fc92013-08-28 22:29:52 -06002298
David Ahernbdc89662013-08-28 22:29:53 -06002299 if (skip_sample(trace, sample))
2300 return 0;
2301
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03002302 trace__set_base_time(trace, evsel, sample);
David Ahern6810fc92013-08-28 22:29:52 -06002303
David Ahern31605652013-12-04 19:41:41 -07002304 if (handler) {
2305 ++trace->nr_events;
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04002306 handler(trace, evsel, event, sample);
David Ahern31605652013-12-04 19:41:41 -07002307 }
David Ahern6810fc92013-08-28 22:29:52 -06002308
2309 return err;
2310}
2311
David Ahernbdc89662013-08-28 22:29:53 -06002312static int parse_target_str(struct trace *trace)
2313{
2314 if (trace->opts.target.pid) {
2315 trace->pid_list = intlist__new(trace->opts.target.pid);
2316 if (trace->pid_list == NULL) {
2317 pr_err("Error parsing process id string\n");
2318 return -EINVAL;
2319 }
2320 }
2321
2322 if (trace->opts.target.tid) {
2323 trace->tid_list = intlist__new(trace->opts.target.tid);
2324 if (trace->tid_list == NULL) {
2325 pr_err("Error parsing thread id string\n");
2326 return -EINVAL;
2327 }
2328 }
2329
2330 return 0;
2331}
2332
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002333static int trace__record(struct trace *trace, int argc, const char **argv)
David Ahern5e2485b2013-09-28 13:13:01 -06002334{
2335 unsigned int rec_argc, i, j;
2336 const char **rec_argv;
2337 const char * const record_args[] = {
2338 "record",
2339 "-R",
2340 "-m", "1024",
2341 "-c", "1",
David Ahern5e2485b2013-09-28 13:13:01 -06002342 };
2343
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002344 const char * const sc_args[] = { "-e", };
2345 unsigned int sc_args_nr = ARRAY_SIZE(sc_args);
2346 const char * const majpf_args[] = { "-e", "major-faults" };
2347 unsigned int majpf_args_nr = ARRAY_SIZE(majpf_args);
2348 const char * const minpf_args[] = { "-e", "minor-faults" };
2349 unsigned int minpf_args_nr = ARRAY_SIZE(minpf_args);
2350
David Ahern9aca7f12013-12-04 19:41:39 -07002351 /* +1 is for the event string below */
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002352 rec_argc = ARRAY_SIZE(record_args) + sc_args_nr + 1 +
2353 majpf_args_nr + minpf_args_nr + argc;
David Ahern5e2485b2013-09-28 13:13:01 -06002354 rec_argv = calloc(rec_argc + 1, sizeof(char *));
2355
2356 if (rec_argv == NULL)
2357 return -ENOMEM;
2358
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002359 j = 0;
David Ahern5e2485b2013-09-28 13:13:01 -06002360 for (i = 0; i < ARRAY_SIZE(record_args); i++)
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002361 rec_argv[j++] = record_args[i];
2362
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002363 if (trace->trace_syscalls) {
2364 for (i = 0; i < sc_args_nr; i++)
2365 rec_argv[j++] = sc_args[i];
David Ahern5e2485b2013-09-28 13:13:01 -06002366
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002367 /* event string may be different for older kernels - e.g., RHEL6 */
2368 if (is_valid_tracepoint("raw_syscalls:sys_enter"))
2369 rec_argv[j++] = "raw_syscalls:sys_enter,raw_syscalls:sys_exit";
2370 else if (is_valid_tracepoint("syscalls:sys_enter"))
2371 rec_argv[j++] = "syscalls:sys_enter,syscalls:sys_exit";
2372 else {
2373 pr_err("Neither raw_syscalls nor syscalls events exist.\n");
2374 return -1;
2375 }
David Ahern9aca7f12013-12-04 19:41:39 -07002376 }
David Ahern9aca7f12013-12-04 19:41:39 -07002377
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002378 if (trace->trace_pgfaults & TRACE_PFMAJ)
2379 for (i = 0; i < majpf_args_nr; i++)
2380 rec_argv[j++] = majpf_args[i];
David Ahern5e2485b2013-09-28 13:13:01 -06002381
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002382 if (trace->trace_pgfaults & TRACE_PFMIN)
2383 for (i = 0; i < minpf_args_nr; i++)
2384 rec_argv[j++] = minpf_args[i];
2385
2386 for (i = 0; i < (unsigned int)argc; i++)
2387 rec_argv[j++] = argv[i];
2388
2389 return cmd_record(j, rec_argv, NULL);
David Ahern5e2485b2013-09-28 13:13:01 -06002390}
2391
David Ahernbf2575c2013-10-08 21:26:53 -06002392static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp);
2393
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002394static bool perf_evlist__add_vfs_getname(struct perf_evlist *evlist)
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002395{
Arnaldo Carvalho de Meloef503832013-11-07 16:41:19 -03002396 struct perf_evsel *evsel = perf_evsel__newtp("probe", "vfs_getname");
Jiri Olsa8dd2a132015-09-07 10:38:06 +02002397
2398 if (IS_ERR(evsel))
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002399 return false;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002400
2401 if (perf_evsel__field(evsel, "pathname") == NULL) {
2402 perf_evsel__delete(evsel);
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002403 return false;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002404 }
2405
Arnaldo Carvalho de Melo744a9712013-11-06 10:17:38 -03002406 evsel->handler = trace__vfs_getname;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002407 perf_evlist__add(evlist, evsel);
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002408 return true;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002409}
2410
Arnaldo Carvalho de Melo0ae537c2016-04-19 16:00:01 -03002411static struct perf_evsel *perf_evsel__new_pgfault(u64 config)
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002412{
2413 struct perf_evsel *evsel;
2414 struct perf_event_attr attr = {
2415 .type = PERF_TYPE_SOFTWARE,
2416 .mmap_data = 1,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002417 };
2418
2419 attr.config = config;
Arnaldo Carvalho de Melo05247982014-07-23 18:15:09 -03002420 attr.sample_period = 1;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002421
2422 event_attr_init(&attr);
2423
2424 evsel = perf_evsel__new(&attr);
Arnaldo Carvalho de Melo0ae537c2016-04-19 16:00:01 -03002425 if (evsel)
2426 evsel->handler = trace__pgfault;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002427
Arnaldo Carvalho de Melo0ae537c2016-04-19 16:00:01 -03002428 return evsel;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002429}
2430
Arnaldo Carvalho de Meloddbb1b12015-02-21 12:10:29 -08002431static void trace__handle_event(struct trace *trace, union perf_event *event, struct perf_sample *sample)
2432{
2433 const u32 type = event->header.type;
2434 struct perf_evsel *evsel;
2435
Arnaldo Carvalho de Meloddbb1b12015-02-21 12:10:29 -08002436 if (type != PERF_RECORD_SAMPLE) {
2437 trace__process_event(trace, trace->host, event, sample);
2438 return;
2439 }
2440
2441 evsel = perf_evlist__id2evsel(trace->evlist, sample->id);
2442 if (evsel == NULL) {
2443 fprintf(trace->output, "Unknown tp ID %" PRIu64 ", skipping...\n", sample->id);
2444 return;
2445 }
2446
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03002447 trace__set_base_time(trace, evsel, sample);
2448
Arnaldo Carvalho de Meloddbb1b12015-02-21 12:10:29 -08002449 if (evsel->attr.type == PERF_TYPE_TRACEPOINT &&
2450 sample->raw_data == NULL) {
2451 fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n",
2452 perf_evsel__name(evsel), sample->tid,
2453 sample->cpu, sample->raw_size);
2454 } else {
2455 tracepoint_handler handler = evsel->handler;
2456 handler(trace, evsel, event, sample);
2457 }
2458}
2459
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03002460static int trace__add_syscall_newtp(struct trace *trace)
2461{
2462 int ret = -1;
2463 struct perf_evlist *evlist = trace->evlist;
2464 struct perf_evsel *sys_enter, *sys_exit;
2465
2466 sys_enter = perf_evsel__syscall_newtp("sys_enter", trace__sys_enter);
2467 if (sys_enter == NULL)
2468 goto out;
2469
2470 if (perf_evsel__init_sc_tp_ptr_field(sys_enter, args))
2471 goto out_delete_sys_enter;
2472
2473 sys_exit = perf_evsel__syscall_newtp("sys_exit", trace__sys_exit);
2474 if (sys_exit == NULL)
2475 goto out_delete_sys_enter;
2476
2477 if (perf_evsel__init_sc_tp_uint_field(sys_exit, ret))
2478 goto out_delete_sys_exit;
2479
2480 perf_evlist__add(evlist, sys_enter);
2481 perf_evlist__add(evlist, sys_exit);
2482
Arnaldo Carvalho de Melo2ddd5c02016-04-18 12:09:08 -03002483 if (callchain_param.enabled && !trace->kernel_syscallchains) {
Arnaldo Carvalho de Melo44621812016-04-11 15:49:11 -03002484 /*
2485 * We're interested only in the user space callchain
2486 * leading to the syscall, allow overriding that for
2487 * debugging reasons using --kernel_syscall_callchains
2488 */
2489 sys_exit->attr.exclude_callchain_kernel = 1;
2490 }
2491
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03002492 trace->syscalls.events.sys_enter = sys_enter;
2493 trace->syscalls.events.sys_exit = sys_exit;
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03002494
2495 ret = 0;
2496out:
2497 return ret;
2498
2499out_delete_sys_exit:
2500 perf_evsel__delete_priv(sys_exit);
2501out_delete_sys_enter:
2502 perf_evsel__delete_priv(sys_enter);
2503 goto out;
2504}
2505
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002506static int trace__set_ev_qualifier_filter(struct trace *trace)
2507{
2508 int err = -1;
2509 char *filter = asprintf_expr_inout_ints("id", !trace->not_ev_qualifier,
2510 trace->ev_qualifier_ids.nr,
2511 trace->ev_qualifier_ids.entries);
2512
2513 if (filter == NULL)
2514 goto out_enomem;
2515
2516 if (!perf_evsel__append_filter(trace->syscalls.events.sys_enter, "&&", filter))
2517 err = perf_evsel__append_filter(trace->syscalls.events.sys_exit, "&&", filter);
2518
2519 free(filter);
2520out:
2521 return err;
2522out_enomem:
2523 errno = ENOMEM;
2524 goto out;
2525}
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03002526
Namhyung Kimf15eb532012-10-05 14:02:16 +09002527static int trace__run(struct trace *trace, int argc, const char **argv)
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002528{
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002529 struct perf_evlist *evlist = trace->evlist;
Arnaldo Carvalho de Melo0ae537c2016-04-19 16:00:01 -03002530 struct perf_evsel *evsel, *pgfault_maj = NULL, *pgfault_min = NULL;
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03002531 int err = -1, i;
2532 unsigned long before;
Namhyung Kimf15eb532012-10-05 14:02:16 +09002533 const bool forks = argc > 0;
Arnaldo Carvalho de Melo46fb3c22014-09-22 14:39:48 -03002534 bool draining = false;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002535
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03002536 trace->live = true;
2537
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03002538 if (trace->trace_syscalls && trace__add_syscall_newtp(trace))
Arnaldo Carvalho de Melo801c67b2015-01-22 10:52:55 -03002539 goto out_error_raw_syscalls;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002540
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002541 if (trace->trace_syscalls)
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002542 trace->vfs_getname = perf_evlist__add_vfs_getname(evlist);
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002543
Arnaldo Carvalho de Melo0ae537c2016-04-19 16:00:01 -03002544 if ((trace->trace_pgfaults & TRACE_PFMAJ)) {
2545 pgfault_maj = perf_evsel__new_pgfault(PERF_COUNT_SW_PAGE_FAULTS_MAJ);
2546 if (pgfault_maj == NULL)
2547 goto out_error_mem;
2548 perf_evlist__add(evlist, pgfault_maj);
Arnaldo Carvalho de Meloe2726d92015-01-22 10:34:22 -03002549 }
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002550
Arnaldo Carvalho de Melo0ae537c2016-04-19 16:00:01 -03002551 if ((trace->trace_pgfaults & TRACE_PFMIN)) {
2552 pgfault_min = perf_evsel__new_pgfault(PERF_COUNT_SW_PAGE_FAULTS_MIN);
2553 if (pgfault_min == NULL)
2554 goto out_error_mem;
2555 perf_evlist__add(evlist, pgfault_min);
2556 }
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002557
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002558 if (trace->sched &&
Arnaldo Carvalho de Melo2cc990b2015-01-22 11:13:43 -03002559 perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime",
2560 trace__sched_stat_runtime))
2561 goto out_error_sched_stat_runtime;
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002562
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002563 err = perf_evlist__create_maps(evlist, &trace->opts.target);
2564 if (err < 0) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002565 fprintf(trace->output, "Problems parsing the target to trace, check your options!\n");
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002566 goto out_delete_evlist;
2567 }
2568
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03002569 err = trace__symbols_init(trace, evlist);
2570 if (err < 0) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002571 fprintf(trace->output, "Problems initializing symbol libraries!\n");
Arnaldo Carvalho de Melo03ad9742014-01-03 15:56:06 -03002572 goto out_delete_evlist;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03002573 }
2574
Arnaldo Carvalho de Melofde54b72016-04-11 18:42:37 -03002575 perf_evlist__config(evlist, &trace->opts, NULL);
2576
Arnaldo Carvalho de Melo0c3a6ef2016-04-19 16:31:12 -03002577 if (callchain_param.enabled) {
2578 bool use_identifier = false;
2579
2580 if (trace->syscalls.events.sys_exit) {
2581 perf_evsel__config_callchain(trace->syscalls.events.sys_exit,
2582 &trace->opts, &callchain_param);
2583 use_identifier = true;
2584 }
2585
2586 if (pgfault_maj) {
2587 perf_evsel__config_callchain(pgfault_maj, &trace->opts, &callchain_param);
2588 use_identifier = true;
2589 }
2590
2591 if (pgfault_min) {
2592 perf_evsel__config_callchain(pgfault_min, &trace->opts, &callchain_param);
2593 use_identifier = true;
2594 }
2595
2596 if (use_identifier) {
2597 /*
2598 * Now we have evsels with different sample_ids, use
2599 * PERF_SAMPLE_IDENTIFIER to map from sample to evsel
2600 * from a fixed position in each ring buffer record.
2601 *
2602 * As of this the changeset introducing this comment, this
2603 * isn't strictly needed, as the fields that can come before
2604 * PERF_SAMPLE_ID are all used, but we'll probably disable
2605 * some of those for things like copying the payload of
2606 * pointer syscall arguments, and for vfs_getname we don't
2607 * need PERF_SAMPLE_ADDR and PERF_SAMPLE_IP, so do this
2608 * here as a warning we need to use PERF_SAMPLE_IDENTIFIER.
2609 */
2610 perf_evlist__set_sample_bit(evlist, IDENTIFIER);
2611 perf_evlist__reset_sample_bit(evlist, ID);
2612 }
Arnaldo Carvalho de Melofde54b72016-04-11 18:42:37 -03002613 }
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002614
Namhyung Kimf15eb532012-10-05 14:02:16 +09002615 signal(SIGCHLD, sig_handler);
2616 signal(SIGINT, sig_handler);
2617
2618 if (forks) {
Namhyung Kim6ef73ec2013-03-11 16:43:15 +09002619 err = perf_evlist__prepare_workload(evlist, &trace->opts.target,
Arnaldo Carvalho de Melo735f7e02014-01-03 14:56:49 -03002620 argv, false, NULL);
Namhyung Kimf15eb532012-10-05 14:02:16 +09002621 if (err < 0) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002622 fprintf(trace->output, "Couldn't run the workload!\n");
Arnaldo Carvalho de Melo03ad9742014-01-03 15:56:06 -03002623 goto out_delete_evlist;
Namhyung Kimf15eb532012-10-05 14:02:16 +09002624 }
2625 }
2626
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002627 err = perf_evlist__open(evlist);
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002628 if (err < 0)
2629 goto out_error_open;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002630
Wang Nanba504232016-02-26 09:31:54 +00002631 err = bpf__apply_obj_config();
2632 if (err) {
2633 char errbuf[BUFSIZ];
2634
2635 bpf__strerror_apply_obj_config(err, errbuf, sizeof(errbuf));
2636 pr_err("ERROR: Apply config to BPF failed: %s\n",
2637 errbuf);
2638 goto out_error_open;
2639 }
2640
Arnaldo Carvalho de Melo241b0572015-02-21 10:15:21 -08002641 /*
2642 * Better not use !target__has_task() here because we need to cover the
2643 * case where no threads were specified in the command line, but a
2644 * workload was, and in that case we will fill in the thread_map when
2645 * we fork the workload in perf_evlist__prepare_workload.
2646 */
Arnaldo Carvalho de Melof078c382015-02-21 11:36:52 -08002647 if (trace->filter_pids.nr > 0)
2648 err = perf_evlist__set_filter_pids(evlist, trace->filter_pids.nr, trace->filter_pids.entries);
Jiri Olsae13798c2015-06-23 00:36:02 +02002649 else if (thread_map__pid(evlist->threads, 0) == -1)
Arnaldo Carvalho de Melof078c382015-02-21 11:36:52 -08002650 err = perf_evlist__set_filter_pid(evlist, getpid());
2651
Arnaldo Carvalho de Melo94ad89b2015-07-03 17:42:03 -03002652 if (err < 0)
2653 goto out_error_mem;
2654
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002655 if (trace->ev_qualifier_ids.nr > 0) {
2656 err = trace__set_ev_qualifier_filter(trace);
2657 if (err < 0)
2658 goto out_errno;
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002659
Arnaldo Carvalho de Melo2e5e5f82015-08-03 17:12:29 -03002660 pr_debug("event qualifier tracepoint filter: %s\n",
2661 trace->syscalls.events.sys_exit->filter);
2662 }
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002663
Arnaldo Carvalho de Melo94ad89b2015-07-03 17:42:03 -03002664 err = perf_evlist__apply_filters(evlist, &evsel);
2665 if (err < 0)
2666 goto out_error_apply_filters;
Arnaldo Carvalho de Melo241b0572015-02-21 10:15:21 -08002667
Jiri Olsaf8850372013-11-28 17:57:22 +01002668 err = perf_evlist__mmap(evlist, trace->opts.mmap_pages, false);
Arnaldo Carvalho de Meloe09b18d2014-12-11 18:04:10 -03002669 if (err < 0)
2670 goto out_error_mmap;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002671
Arnaldo Carvalho de Melocb24d012015-04-22 10:04:23 -03002672 if (!target__none(&trace->opts.target))
2673 perf_evlist__enable(evlist);
2674
Namhyung Kimf15eb532012-10-05 14:02:16 +09002675 if (forks)
2676 perf_evlist__start_workload(evlist);
2677
Jiri Olsae13798c2015-06-23 00:36:02 +02002678 trace->multiple_threads = thread_map__pid(evlist->threads, 0) == -1 ||
Arnaldo Carvalho de Melo42052be2015-02-13 12:32:45 -03002679 evlist->threads->nr > 1 ||
2680 perf_evlist__first(evlist)->attr.inherit;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002681again:
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03002682 before = trace->nr_events;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002683
2684 for (i = 0; i < evlist->nr_mmaps; i++) {
2685 union perf_event *event;
2686
2687 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002688 struct perf_sample sample;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002689
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03002690 ++trace->nr_events;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002691
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002692 err = perf_evlist__parse_sample(evlist, event, &sample);
2693 if (err) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002694 fprintf(trace->output, "Can't parse sample, err = %d, skipping...\n", err);
Zhouyi Zhou8e50d382013-10-24 15:43:33 +08002695 goto next_event;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002696 }
2697
Arnaldo Carvalho de Meloddbb1b12015-02-21 12:10:29 -08002698 trace__handle_event(trace, event, &sample);
Zhouyi Zhou8e50d382013-10-24 15:43:33 +08002699next_event:
2700 perf_evlist__mmap_consume(evlist, i);
Arnaldo Carvalho de Melo20c5f102013-09-03 11:55:07 -03002701
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002702 if (interrupted)
2703 goto out_disable;
Arnaldo Carvalho de Melo02ac5422015-04-22 11:11:57 -03002704
2705 if (done && !draining) {
2706 perf_evlist__disable(evlist);
2707 draining = true;
2708 }
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002709 }
2710 }
2711
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03002712 if (trace->nr_events == before) {
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002713 int timeout = done ? 100 : -1;
Namhyung Kimf15eb532012-10-05 14:02:16 +09002714
Arnaldo Carvalho de Melo46fb3c22014-09-22 14:39:48 -03002715 if (!draining && perf_evlist__poll(evlist, timeout) > 0) {
2716 if (perf_evlist__filter_pollfd(evlist, POLLERR | POLLHUP) == 0)
2717 draining = true;
2718
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002719 goto again;
Arnaldo Carvalho de Melo46fb3c22014-09-22 14:39:48 -03002720 }
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002721 } else {
2722 goto again;
Namhyung Kimf15eb532012-10-05 14:02:16 +09002723 }
2724
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002725out_disable:
Arnaldo Carvalho de Melof3b623b2015-03-02 22:21:35 -03002726 thread__zput(trace->current);
2727
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002728 perf_evlist__disable(evlist);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002729
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002730 if (!err) {
2731 if (trace->summary)
2732 trace__fprintf_thread_summary(trace, trace->output);
2733
2734 if (trace->show_tool_stats) {
2735 fprintf(trace->output, "Stats:\n "
2736 " vfs_getname : %" PRIu64 "\n"
2737 " proc_getname: %" PRIu64 "\n",
2738 trace->stats.vfs_getname,
2739 trace->stats.proc_getname);
2740 }
2741 }
David Ahernbf2575c2013-10-08 21:26:53 -06002742
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002743out_delete_evlist:
2744 perf_evlist__delete(evlist);
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002745 trace->evlist = NULL;
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03002746 trace->live = false;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002747 return err;
Arnaldo Carvalho de Melo6ef068c2013-10-17 12:07:58 -03002748{
2749 char errbuf[BUFSIZ];
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002750
Arnaldo Carvalho de Melo2cc990b2015-01-22 11:13:43 -03002751out_error_sched_stat_runtime:
Jiri Olsa988bdb32015-09-02 09:56:35 +02002752 tracing_path__strerror_open_tp(errno, errbuf, sizeof(errbuf), "sched", "sched_stat_runtime");
Arnaldo Carvalho de Melo2cc990b2015-01-22 11:13:43 -03002753 goto out_error;
2754
Arnaldo Carvalho de Melo801c67b2015-01-22 10:52:55 -03002755out_error_raw_syscalls:
Jiri Olsa988bdb32015-09-02 09:56:35 +02002756 tracing_path__strerror_open_tp(errno, errbuf, sizeof(errbuf), "raw_syscalls", "sys_(enter|exit)");
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002757 goto out_error;
2758
Arnaldo Carvalho de Meloe09b18d2014-12-11 18:04:10 -03002759out_error_mmap:
2760 perf_evlist__strerror_mmap(evlist, errno, errbuf, sizeof(errbuf));
2761 goto out_error;
2762
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002763out_error_open:
2764 perf_evlist__strerror_open(evlist, errno, errbuf, sizeof(errbuf));
2765
2766out_error:
Arnaldo Carvalho de Melo6ef068c2013-10-17 12:07:58 -03002767 fprintf(trace->output, "%s\n", errbuf);
Ramkumar Ramachandra87f91862013-10-04 10:47:31 +05302768 goto out_delete_evlist;
Arnaldo Carvalho de Melo94ad89b2015-07-03 17:42:03 -03002769
2770out_error_apply_filters:
2771 fprintf(trace->output,
2772 "Failed to set filter \"%s\" on event %s with %d (%s)\n",
2773 evsel->filter, perf_evsel__name(evsel), errno,
2774 strerror_r(errno, errbuf, sizeof(errbuf)));
2775 goto out_delete_evlist;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002776}
Arnaldo Carvalho de Melo5ed08da2015-01-22 11:08:04 -03002777out_error_mem:
2778 fprintf(trace->output, "Not enough memory to run!\n");
2779 goto out_delete_evlist;
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002780
2781out_errno:
2782 fprintf(trace->output, "errno=%d,%s\n", errno, strerror(errno));
2783 goto out_delete_evlist;
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002784}
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002785
David Ahern6810fc92013-08-28 22:29:52 -06002786static int trace__replay(struct trace *trace)
2787{
2788 const struct perf_evsel_str_handler handlers[] = {
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002789 { "probe:vfs_getname", trace__vfs_getname, },
David Ahern6810fc92013-08-28 22:29:52 -06002790 };
Jiri Olsaf5fc14122013-10-15 16:27:32 +02002791 struct perf_data_file file = {
2792 .path = input_name,
2793 .mode = PERF_DATA_MODE_READ,
Yunlong Songe366a6d2015-04-02 21:47:18 +08002794 .force = trace->force,
Jiri Olsaf5fc14122013-10-15 16:27:32 +02002795 };
David Ahern6810fc92013-08-28 22:29:52 -06002796 struct perf_session *session;
Namhyung Kim003824e2013-11-12 15:25:00 +09002797 struct perf_evsel *evsel;
David Ahern6810fc92013-08-28 22:29:52 -06002798 int err = -1;
2799
2800 trace->tool.sample = trace__process_sample;
2801 trace->tool.mmap = perf_event__process_mmap;
David Ahern384c6712013-09-22 19:44:58 -06002802 trace->tool.mmap2 = perf_event__process_mmap2;
David Ahern6810fc92013-08-28 22:29:52 -06002803 trace->tool.comm = perf_event__process_comm;
2804 trace->tool.exit = perf_event__process_exit;
2805 trace->tool.fork = perf_event__process_fork;
2806 trace->tool.attr = perf_event__process_attr;
2807 trace->tool.tracing_data = perf_event__process_tracing_data;
2808 trace->tool.build_id = perf_event__process_build_id;
2809
Jiri Olsa0a8cb852014-07-06 14:18:21 +02002810 trace->tool.ordered_events = true;
David Ahern6810fc92013-08-28 22:29:52 -06002811 trace->tool.ordering_requires_timestamps = true;
2812
2813 /* add tid to output */
2814 trace->multiple_threads = true;
2815
Jiri Olsaf5fc14122013-10-15 16:27:32 +02002816 session = perf_session__new(&file, false, &trace->tool);
David Ahern6810fc92013-08-28 22:29:52 -06002817 if (session == NULL)
Taeung Song52e028342014-09-24 10:33:37 +09002818 return -1;
David Ahern6810fc92013-08-28 22:29:52 -06002819
Namhyung Kim0a7e6d12014-08-12 15:40:45 +09002820 if (symbol__init(&session->header.env) < 0)
Namhyung Kimcb2ffae2014-08-12 15:40:44 +09002821 goto out;
2822
David Ahern8fb598e2013-09-28 13:13:00 -06002823 trace->host = &session->machines.host;
2824
David Ahern6810fc92013-08-28 22:29:52 -06002825 err = perf_session__set_tracepoints_handlers(session, handlers);
2826 if (err)
2827 goto out;
2828
Namhyung Kim003824e2013-11-12 15:25:00 +09002829 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2830 "raw_syscalls:sys_enter");
David Ahern9aca7f12013-12-04 19:41:39 -07002831 /* older kernels have syscalls tp versus raw_syscalls */
2832 if (evsel == NULL)
2833 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2834 "syscalls:sys_enter");
David Ahern6810fc92013-08-28 22:29:52 -06002835
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002836 if (evsel &&
2837 (perf_evsel__init_syscall_tp(evsel, trace__sys_enter) < 0 ||
2838 perf_evsel__init_sc_tp_ptr_field(evsel, args))) {
Namhyung Kim003824e2013-11-12 15:25:00 +09002839 pr_err("Error during initialize raw_syscalls:sys_enter event\n");
2840 goto out;
2841 }
2842
2843 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2844 "raw_syscalls:sys_exit");
David Ahern9aca7f12013-12-04 19:41:39 -07002845 if (evsel == NULL)
2846 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2847 "syscalls:sys_exit");
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002848 if (evsel &&
2849 (perf_evsel__init_syscall_tp(evsel, trace__sys_exit) < 0 ||
2850 perf_evsel__init_sc_tp_uint_field(evsel, ret))) {
Namhyung Kim003824e2013-11-12 15:25:00 +09002851 pr_err("Error during initialize raw_syscalls:sys_exit event\n");
David Ahern6810fc92013-08-28 22:29:52 -06002852 goto out;
2853 }
2854
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002855 evlist__for_each(session->evlist, evsel) {
2856 if (evsel->attr.type == PERF_TYPE_SOFTWARE &&
2857 (evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ||
2858 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MIN ||
2859 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS))
2860 evsel->handler = trace__pgfault;
2861 }
2862
David Ahernbdc89662013-08-28 22:29:53 -06002863 err = parse_target_str(trace);
2864 if (err != 0)
2865 goto out;
2866
David Ahern6810fc92013-08-28 22:29:52 -06002867 setup_pager();
2868
Arnaldo Carvalho de Melob7b61cb2015-03-03 11:58:45 -03002869 err = perf_session__process_events(session);
David Ahern6810fc92013-08-28 22:29:52 -06002870 if (err)
2871 pr_err("Failed to process events, error %d", err);
2872
David Ahernbf2575c2013-10-08 21:26:53 -06002873 else if (trace->summary)
2874 trace__fprintf_thread_summary(trace, trace->output);
2875
David Ahern6810fc92013-08-28 22:29:52 -06002876out:
2877 perf_session__delete(session);
2878
2879 return err;
2880}
2881
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002882static size_t trace__fprintf_threads_header(FILE *fp)
2883{
2884 size_t printed;
2885
Pekka Enberg99ff7152013-11-12 16:42:14 +02002886 printed = fprintf(fp, "\n Summary of events:\n\n");
David Ahernbf2575c2013-10-08 21:26:53 -06002887
2888 return printed;
2889}
2890
2891static size_t thread__dump_stats(struct thread_trace *ttrace,
2892 struct trace *trace, FILE *fp)
2893{
2894 struct stats *stats;
2895 size_t printed = 0;
2896 struct syscall *sc;
2897 struct int_node *inode = intlist__first(ttrace->syscall_stats);
2898
2899 if (inode == NULL)
2900 return 0;
2901
2902 printed += fprintf(fp, "\n");
2903
Milian Wolff834fd462015-08-06 11:24:29 +02002904 printed += fprintf(fp, " syscall calls total min avg max stddev\n");
2905 printed += fprintf(fp, " (msec) (msec) (msec) (msec) (%%)\n");
2906 printed += fprintf(fp, " --------------- -------- --------- --------- --------- --------- ------\n");
Pekka Enberg99ff7152013-11-12 16:42:14 +02002907
David Ahernbf2575c2013-10-08 21:26:53 -06002908 /* each int_node is a syscall */
2909 while (inode) {
2910 stats = inode->priv;
2911 if (stats) {
2912 double min = (double)(stats->min) / NSEC_PER_MSEC;
2913 double max = (double)(stats->max) / NSEC_PER_MSEC;
2914 double avg = avg_stats(stats);
2915 double pct;
2916 u64 n = (u64) stats->n;
2917
2918 pct = avg ? 100.0 * stddev_stats(stats)/avg : 0.0;
2919 avg /= NSEC_PER_MSEC;
2920
2921 sc = &trace->syscalls.table[inode->i];
Pekka Enberg99ff7152013-11-12 16:42:14 +02002922 printed += fprintf(fp, " %-15s", sc->name);
Milian Wolff834fd462015-08-06 11:24:29 +02002923 printed += fprintf(fp, " %8" PRIu64 " %9.3f %9.3f %9.3f",
2924 n, avg * n, min, avg);
Pekka Enberg27a778b2013-11-13 14:21:48 +02002925 printed += fprintf(fp, " %9.3f %9.2f%%\n", max, pct);
David Ahernbf2575c2013-10-08 21:26:53 -06002926 }
2927
2928 inode = intlist__next(inode);
2929 }
2930
2931 printed += fprintf(fp, "\n\n");
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002932
2933 return printed;
2934}
2935
David Ahern896cbb52013-09-28 13:12:59 -06002936/* struct used to pass data to per-thread function */
2937struct summary_data {
2938 FILE *fp;
2939 struct trace *trace;
2940 size_t printed;
2941};
2942
2943static int trace__fprintf_one_thread(struct thread *thread, void *priv)
2944{
2945 struct summary_data *data = priv;
2946 FILE *fp = data->fp;
2947 size_t printed = data->printed;
2948 struct trace *trace = data->trace;
Namhyung Kim89dceb22014-10-06 09:46:03 +09002949 struct thread_trace *ttrace = thread__priv(thread);
David Ahern896cbb52013-09-28 13:12:59 -06002950 double ratio;
2951
2952 if (ttrace == NULL)
2953 return 0;
2954
2955 ratio = (double)ttrace->nr_events / trace->nr_events * 100.0;
2956
Pekka Enberg15e65c62013-11-14 18:43:30 +02002957 printed += fprintf(fp, " %s (%d), ", thread__comm_str(thread), thread->tid);
Pekka Enberg99ff7152013-11-12 16:42:14 +02002958 printed += fprintf(fp, "%lu events, ", ttrace->nr_events);
Pekka Enberg15e65c62013-11-14 18:43:30 +02002959 printed += fprintf(fp, "%.1f%%", ratio);
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04002960 if (ttrace->pfmaj)
2961 printed += fprintf(fp, ", %lu majfaults", ttrace->pfmaj);
2962 if (ttrace->pfmin)
2963 printed += fprintf(fp, ", %lu minfaults", ttrace->pfmin);
Pekka Enberg99ff7152013-11-12 16:42:14 +02002964 printed += fprintf(fp, ", %.3f msec\n", ttrace->runtime_ms);
David Ahernbf2575c2013-10-08 21:26:53 -06002965 printed += thread__dump_stats(ttrace, trace, fp);
David Ahern896cbb52013-09-28 13:12:59 -06002966
2967 data->printed += printed;
2968
2969 return 0;
2970}
2971
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002972static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp)
2973{
David Ahern896cbb52013-09-28 13:12:59 -06002974 struct summary_data data = {
2975 .fp = fp,
2976 .trace = trace
2977 };
2978 data.printed = trace__fprintf_threads_header(fp);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002979
David Ahern896cbb52013-09-28 13:12:59 -06002980 machine__for_each_thread(trace->host, trace__fprintf_one_thread, &data);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002981
David Ahern896cbb52013-09-28 13:12:59 -06002982 return data.printed;
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002983}
2984
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03002985static int trace__set_duration(const struct option *opt, const char *str,
2986 int unset __maybe_unused)
2987{
2988 struct trace *trace = opt->value;
2989
2990 trace->duration_filter = atof(str);
2991 return 0;
2992}
2993
Arnaldo Carvalho de Melof078c382015-02-21 11:36:52 -08002994static int trace__set_filter_pids(const struct option *opt, const char *str,
2995 int unset __maybe_unused)
2996{
2997 int ret = -1;
2998 size_t i;
2999 struct trace *trace = opt->value;
3000 /*
3001 * FIXME: introduce a intarray class, plain parse csv and create a
3002 * { int nr, int entries[] } struct...
3003 */
3004 struct intlist *list = intlist__new(str);
3005
3006 if (list == NULL)
3007 return -1;
3008
3009 i = trace->filter_pids.nr = intlist__nr_entries(list) + 1;
3010 trace->filter_pids.entries = calloc(i, sizeof(pid_t));
3011
3012 if (trace->filter_pids.entries == NULL)
3013 goto out;
3014
3015 trace->filter_pids.entries[0] = getpid();
3016
3017 for (i = 1; i < trace->filter_pids.nr; ++i)
3018 trace->filter_pids.entries[i] = intlist__entry(list, i - 1)->i;
3019
3020 intlist__delete(list);
3021 ret = 0;
3022out:
3023 return ret;
3024}
3025
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003026static int trace__open_output(struct trace *trace, const char *filename)
3027{
3028 struct stat st;
3029
3030 if (!stat(filename, &st) && st.st_size) {
3031 char oldname[PATH_MAX];
3032
3033 scnprintf(oldname, sizeof(oldname), "%s.old", filename);
3034 unlink(oldname);
3035 rename(filename, oldname);
3036 }
3037
3038 trace->output = fopen(filename, "w");
3039
3040 return trace->output == NULL ? -errno : 0;
3041}
3042
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04003043static int parse_pagefaults(const struct option *opt, const char *str,
3044 int unset __maybe_unused)
3045{
3046 int *trace_pgfaults = opt->value;
3047
3048 if (strcmp(str, "all") == 0)
3049 *trace_pgfaults |= TRACE_PFMAJ | TRACE_PFMIN;
3050 else if (strcmp(str, "maj") == 0)
3051 *trace_pgfaults |= TRACE_PFMAJ;
3052 else if (strcmp(str, "min") == 0)
3053 *trace_pgfaults |= TRACE_PFMIN;
3054 else
3055 return -1;
3056
3057 return 0;
3058}
3059
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003060static void evlist__set_evsel_handler(struct perf_evlist *evlist, void *handler)
3061{
3062 struct perf_evsel *evsel;
3063
3064 evlist__for_each(evlist, evsel)
3065 evsel->handler = handler;
3066}
3067
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003068int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
3069{
Yunlong Song6fdd9cb2015-03-18 21:35:57 +08003070 const char *trace_usage[] = {
Namhyung Kimf15eb532012-10-05 14:02:16 +09003071 "perf trace [<options>] [<command>]",
3072 "perf trace [<options>] -- <command> [<options>]",
David Ahern5e2485b2013-09-28 13:13:01 -06003073 "perf trace record [<options>] [<command>]",
3074 "perf trace record [<options>] -- <command> [<options>]",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003075 NULL
3076 };
3077 struct trace trace = {
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003078 .syscalls = {
3079 . max = -1,
3080 },
3081 .opts = {
3082 .target = {
3083 .uid = UINT_MAX,
3084 .uses_mmap = true,
3085 },
3086 .user_freq = UINT_MAX,
3087 .user_interval = ULLONG_MAX,
Arnaldo Carvalho de Melo509051e2014-01-14 17:52:14 -03003088 .no_buffering = true,
Arnaldo Carvalho de Melo38d54472014-12-12 17:28:32 -03003089 .mmap_pages = UINT_MAX,
Kan Liang9d9cad72015-06-17 09:51:11 -04003090 .proc_map_timeout = 500,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003091 },
Milian Wolff007d66a2015-08-05 16:52:23 -03003092 .output = stderr,
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -03003093 .show_comm = true,
Stanislav Fomicheve281a962014-06-26 20:14:28 +04003094 .trace_syscalls = true,
Arnaldo Carvalho de Melo44621812016-04-11 15:49:11 -03003095 .kernel_syscallchains = false,
Arnaldo Carvalho de Melo05614992016-04-15 16:41:19 -03003096 .max_stack = UINT_MAX,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003097 };
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003098 const char *output_name = NULL;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03003099 const char *ev_qualifier_str = NULL;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003100 const struct option trace_options[] = {
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003101 OPT_CALLBACK(0, "event", &trace.evlist, "event",
3102 "event selector. use 'perf list' to list available events",
3103 parse_events_option),
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -03003104 OPT_BOOLEAN(0, "comm", &trace.show_comm,
3105 "show the thread COMM next to its id"),
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03003106 OPT_BOOLEAN(0, "tool_stats", &trace.show_tool_stats, "show tool stats"),
Arnaldo Carvalho de Melod303e852015-04-23 12:02:07 -03003107 OPT_STRING('e', "expr", &ev_qualifier_str, "expr", "list of syscalls to trace"),
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003108 OPT_STRING('o', "output", &output_name, "file", "output file name"),
David Ahern6810fc92013-08-28 22:29:52 -06003109 OPT_STRING('i', "input", &input_name, "file", "Analyze events in file"),
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003110 OPT_STRING('p', "pid", &trace.opts.target.pid, "pid",
3111 "trace events on existing process id"),
David Ahernac9be8e2013-08-20 11:15:45 -06003112 OPT_STRING('t', "tid", &trace.opts.target.tid, "tid",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003113 "trace events on existing thread id"),
Arnaldo Carvalho de Melofa0e4ff2015-04-23 11:59:20 -03003114 OPT_CALLBACK(0, "filter-pids", &trace, "CSV list of pids",
3115 "pids to filter (by the kernel)", trace__set_filter_pids),
David Ahernac9be8e2013-08-20 11:15:45 -06003116 OPT_BOOLEAN('a', "all-cpus", &trace.opts.target.system_wide,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003117 "system-wide collection from all CPUs"),
David Ahernac9be8e2013-08-20 11:15:45 -06003118 OPT_STRING('C', "cpu", &trace.opts.target.cpu_list, "cpu",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003119 "list of cpus to monitor"),
David Ahern6810fc92013-08-28 22:29:52 -06003120 OPT_BOOLEAN(0, "no-inherit", &trace.opts.no_inherit,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003121 "child tasks do not inherit counters"),
Jiri Olsa994a1f72013-09-01 12:36:12 +02003122 OPT_CALLBACK('m', "mmap-pages", &trace.opts.mmap_pages, "pages",
3123 "number of mmap data pages",
3124 perf_evlist__parse_mmap_pages),
David Ahernac9be8e2013-08-20 11:15:45 -06003125 OPT_STRING('u', "uid", &trace.opts.target.uid_str, "user",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003126 "user to profile"),
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03003127 OPT_CALLBACK(0, "duration", &trace, "float",
3128 "show only events with duration > N.M ms",
3129 trace__set_duration),
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03003130 OPT_BOOLEAN(0, "sched", &trace.sched, "show blocking scheduler events"),
Arnaldo Carvalho de Melo7c304ee02013-08-22 16:49:54 -03003131 OPT_INCR('v', "verbose", &verbose, "be more verbose"),
David Ahern4bb09192013-09-04 12:37:43 -06003132 OPT_BOOLEAN('T', "time", &trace.full_time,
3133 "Show full timestamp, not time relative to first start"),
David Ahernfd2eaba2013-11-12 09:31:15 -07003134 OPT_BOOLEAN('s', "summary", &trace.summary_only,
3135 "Show only syscall summary with statistics"),
3136 OPT_BOOLEAN('S', "with-summary", &trace.summary,
3137 "Show all syscalls and summary with statistics"),
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04003138 OPT_CALLBACK_DEFAULT('F', "pf", &trace.trace_pgfaults, "all|maj|min",
3139 "Trace pagefaults", parse_pagefaults, "maj"),
Stanislav Fomicheve281a962014-06-26 20:14:28 +04003140 OPT_BOOLEAN(0, "syscalls", &trace.trace_syscalls, "Trace syscalls"),
Yunlong Songe366a6d2015-04-02 21:47:18 +08003141 OPT_BOOLEAN('f', "force", &trace.force, "don't complain, do it"),
Milian Wolff566a0882016-04-08 13:34:15 +02003142 OPT_CALLBACK(0, "call-graph", &trace.opts,
3143 "record_mode[,record_size]", record_callchain_help,
3144 &record_parse_callchain_opt),
Arnaldo Carvalho de Melo44621812016-04-11 15:49:11 -03003145 OPT_BOOLEAN(0, "kernel-syscall-graph", &trace.kernel_syscallchains,
3146 "Show the kernel callchains on the syscall exit path"),
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -03003147 OPT_UINTEGER(0, "min-stack", &trace.min_stack,
3148 "Set the minimum stack depth when parsing the callchain, "
3149 "anything below the specified depth will be ignored."),
Arnaldo Carvalho de Meloc6d4a492016-04-14 18:29:08 -03003150 OPT_UINTEGER(0, "max-stack", &trace.max_stack,
3151 "Set the maximum stack depth when parsing the callchain, "
3152 "anything beyond the specified depth will be ignored. "
3153 "Default: " __stringify(PERF_MAX_STACK_DEPTH)),
Kan Liang9d9cad72015-06-17 09:51:11 -04003154 OPT_UINTEGER(0, "proc-map-timeout", &trace.opts.proc_map_timeout,
3155 "per thread proc mmap processing timeout in ms"),
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003156 OPT_END()
3157 };
Arnaldo Carvalho de Meloccd62a82016-04-16 09:36:32 -03003158 bool __maybe_unused max_stack_user_set = true;
Arnaldo Carvalho de Melof3e459d2016-04-15 17:52:34 -03003159 bool mmap_pages_user_set = true;
Yunlong Song6fdd9cb2015-03-18 21:35:57 +08003160 const char * const trace_subcommands[] = { "record", NULL };
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003161 int err;
Namhyung Kim32caf0d2012-10-05 14:02:13 +09003162 char bf[BUFSIZ];
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003163
Arnaldo Carvalho de Melo4d08cb82015-02-24 15:35:55 -03003164 signal(SIGSEGV, sighandler_dump_stack);
3165 signal(SIGFPE, sighandler_dump_stack);
3166
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003167 trace.evlist = perf_evlist__new();
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03003168 trace.sctbl = syscalltbl__new();
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003169
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03003170 if (trace.evlist == NULL || trace.sctbl == NULL) {
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003171 pr_err("Not enough memory to run!\n");
He Kuangff8f6952015-05-11 12:28:36 +00003172 err = -ENOMEM;
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003173 goto out;
3174 }
3175
Yunlong Song6fdd9cb2015-03-18 21:35:57 +08003176 argc = parse_options_subcommand(argc, argv, trace_options, trace_subcommands,
3177 trace_usage, PARSE_OPT_STOP_AT_NON_OPTION);
David Ahernfd2eaba2013-11-12 09:31:15 -07003178
Wang Nand7888572016-04-08 15:07:24 +00003179 err = bpf__setup_stdout(trace.evlist);
3180 if (err) {
3181 bpf__strerror_setup_stdout(trace.evlist, err, bf, sizeof(bf));
3182 pr_err("ERROR: Setup BPF stdout failed: %s\n", bf);
3183 goto out;
3184 }
3185
Arnaldo Carvalho de Melo59247e32016-04-12 16:05:02 -03003186 err = -1;
3187
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04003188 if (trace.trace_pgfaults) {
3189 trace.opts.sample_address = true;
3190 trace.opts.sample_time = true;
3191 }
3192
Arnaldo Carvalho de Melof3e459d2016-04-15 17:52:34 -03003193 if (trace.opts.mmap_pages == UINT_MAX)
3194 mmap_pages_user_set = false;
3195
Arnaldo Carvalho de Melo05614992016-04-15 16:41:19 -03003196 if (trace.max_stack == UINT_MAX) {
3197 trace.max_stack = PERF_MAX_STACK_DEPTH;
3198 max_stack_user_set = false;
3199 }
3200
3201#ifdef HAVE_DWARF_UNWIND_SUPPORT
Arnaldo Carvalho de Melo2ddd5c02016-04-18 12:09:08 -03003202 if ((trace.min_stack || max_stack_user_set) && !callchain_param.enabled)
Arnaldo Carvalho de Melo05614992016-04-15 16:41:19 -03003203 record_opts__parse_callchain(&trace.opts, &callchain_param, "dwarf", false);
3204#endif
3205
Arnaldo Carvalho de Melo2ddd5c02016-04-18 12:09:08 -03003206 if (callchain_param.enabled) {
Arnaldo Carvalho de Melof3e459d2016-04-15 17:52:34 -03003207 if (!mmap_pages_user_set && geteuid() == 0)
3208 trace.opts.mmap_pages = perf_event_mlock_kb_in_pages() * 4;
3209
Milian Wolff566a0882016-04-08 13:34:15 +02003210 symbol_conf.use_callchain = true;
Arnaldo Carvalho de Melof3e459d2016-04-15 17:52:34 -03003211 }
Milian Wolff566a0882016-04-08 13:34:15 +02003212
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003213 if (trace.evlist->nr_entries > 0)
3214 evlist__set_evsel_handler(trace.evlist, trace__event_handler);
3215
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04003216 if ((argc >= 1) && (strcmp(argv[0], "record") == 0))
3217 return trace__record(&trace, argc-1, &argv[1]);
3218
3219 /* summary_only implies summary option, but don't overwrite summary if set */
3220 if (trace.summary_only)
3221 trace.summary = trace.summary_only;
3222
Arnaldo Carvalho de Melo726f3232015-02-06 10:16:45 +01003223 if (!trace.trace_syscalls && !trace.trace_pgfaults &&
3224 trace.evlist->nr_entries == 0 /* Was --events used? */) {
Stanislav Fomicheve281a962014-06-26 20:14:28 +04003225 pr_err("Please specify something to trace.\n");
3226 return -1;
3227 }
3228
Arnaldo Carvalho de Melo59247e32016-04-12 16:05:02 -03003229 if (!trace.trace_syscalls && ev_qualifier_str) {
3230 pr_err("The -e option can't be used with --no-syscalls.\n");
3231 goto out;
3232 }
3233
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003234 if (output_name != NULL) {
3235 err = trace__open_output(&trace, output_name);
3236 if (err < 0) {
3237 perror("failed to create output file");
3238 goto out;
3239 }
3240 }
3241
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03003242 trace.open_id = syscalltbl__id(trace.sctbl, "open");
3243
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03003244 if (ev_qualifier_str != NULL) {
Arnaldo Carvalho de Melob059efd2013-08-21 12:56:21 -03003245 const char *s = ev_qualifier_str;
Arnaldo Carvalho de Melo005438a82015-07-20 12:02:09 -03003246 struct strlist_config slist_config = {
3247 .dirname = system_path(STRACE_GROUPS_DIR),
3248 };
Arnaldo Carvalho de Melob059efd2013-08-21 12:56:21 -03003249
3250 trace.not_ev_qualifier = *s == '!';
3251 if (trace.not_ev_qualifier)
3252 ++s;
Arnaldo Carvalho de Melo005438a82015-07-20 12:02:09 -03003253 trace.ev_qualifier = strlist__new(s, &slist_config);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03003254 if (trace.ev_qualifier == NULL) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003255 fputs("Not enough memory to parse event qualifier",
3256 trace.output);
3257 err = -ENOMEM;
3258 goto out_close;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03003259 }
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03003260
3261 err = trace__validate_ev_qualifier(&trace);
3262 if (err)
3263 goto out_close;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03003264 }
3265
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003266 err = target__validate(&trace.opts.target);
Namhyung Kim32caf0d2012-10-05 14:02:13 +09003267 if (err) {
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003268 target__strerror(&trace.opts.target, err, bf, sizeof(bf));
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003269 fprintf(trace.output, "%s", bf);
3270 goto out_close;
Namhyung Kim32caf0d2012-10-05 14:02:13 +09003271 }
3272
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003273 err = target__parse_uid(&trace.opts.target);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003274 if (err) {
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003275 target__strerror(&trace.opts.target, err, bf, sizeof(bf));
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003276 fprintf(trace.output, "%s", bf);
3277 goto out_close;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003278 }
3279
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003280 if (!argc && target__none(&trace.opts.target))
Namhyung Kimee761202012-10-05 14:02:14 +09003281 trace.opts.target.system_wide = true;
3282
David Ahern6810fc92013-08-28 22:29:52 -06003283 if (input_name)
3284 err = trace__replay(&trace);
3285 else
3286 err = trace__run(&trace, argc, argv);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03003287
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003288out_close:
3289 if (output_name != NULL)
3290 fclose(trace.output);
3291out:
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03003292 return err;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003293}