]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - tools/perf/builtin-trace.c
perf trace: Move mmap beautifiers to trace/beauty/ directory
[mirror_ubuntu-bionic-kernel.git] / tools / perf / builtin-trace.c
CommitLineData
a598bb5e
ACM
1/*
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
4e319027 19#include <traceevent/event-parse.h>
988bdb31 20#include <api/fs/tracing_path.h>
514f1c67 21#include "builtin.h"
752fde44 22#include "util/color.h"
7c304ee0 23#include "util/debug.h"
514f1c67 24#include "util/evlist.h"
4b6ab94e 25#include <subcmd/exec-cmd.h>
752fde44 26#include "util/machine.h"
6810fc91 27#include "util/session.h"
752fde44 28#include "util/thread.h"
4b6ab94e 29#include <subcmd/parse-options.h>
2ae3a312 30#include "util/strlist.h"
bdc89661 31#include "util/intlist.h"
514f1c67 32#include "util/thread_map.h"
bf2575c1 33#include "util/stat.h"
97978b3e 34#include "trace-event.h"
9aca7f17 35#include "util/parse-events.h"
ba504235 36#include "util/bpf-loader.h"
566a0885 37#include "callchain.h"
fd0db102 38#include "syscalltbl.h"
514f1c67 39
fd0db102 40#include <libaudit.h> /* FIXME: Still needed for audit_errno_to_name */
514f1c67 41#include <stdlib.h>
f9da0b0c 42#include <linux/futex.h>
8dd2a131 43#include <linux/err.h>
997bba8c
ACM
44#include <linux/seccomp.h>
45#include <linux/filter.h>
46#include <linux/audit.h>
47#include <sys/ptrace.h>
39878d49 48#include <linux/random.h>
514f1c67 49
456857bd 50/* For older distros: */
456857bd 51
79d26a6a
BH
52#ifndef EFD_SEMAPHORE
53# define EFD_SEMAPHORE 1
54#endif
55
c188e7ac
ACM
56#ifndef EFD_NONBLOCK
57# define EFD_NONBLOCK 00004000
58#endif
59
60#ifndef EFD_CLOEXEC
61# define EFD_CLOEXEC 02000000
62#endif
63
64#ifndef O_CLOEXEC
65# define O_CLOEXEC 02000000
66#endif
67
68#ifndef SOCK_DCCP
69# define SOCK_DCCP 6
70#endif
71
72#ifndef SOCK_CLOEXEC
73# define SOCK_CLOEXEC 02000000
74#endif
75
76#ifndef SOCK_NONBLOCK
77# define SOCK_NONBLOCK 00004000
78#endif
79
80#ifndef MSG_CMSG_CLOEXEC
81# define MSG_CMSG_CLOEXEC 0x40000000
82#endif
83
a1c2552d
ACM
84#ifndef PERF_FLAG_FD_NO_GROUP
85# define PERF_FLAG_FD_NO_GROUP (1UL << 0)
86#endif
87
88#ifndef PERF_FLAG_FD_OUTPUT
89# define PERF_FLAG_FD_OUTPUT (1UL << 1)
90#endif
91
92#ifndef PERF_FLAG_PID_CGROUP
93# define PERF_FLAG_PID_CGROUP (1UL << 2) /* pid=cgroup id, per-cpu mode only */
94#endif
95
96#ifndef PERF_FLAG_FD_CLOEXEC
97# define PERF_FLAG_FD_CLOEXEC (1UL << 3) /* O_CLOEXEC */
98#endif
99
d1d438a3
ACM
100struct trace {
101 struct perf_tool tool;
fd0db102 102 struct syscalltbl *sctbl;
d1d438a3
ACM
103 struct {
104 int max;
105 struct syscall *table;
106 struct {
107 struct perf_evsel *sys_enter,
108 *sys_exit;
109 } events;
110 } syscalls;
111 struct record_opts opts;
112 struct perf_evlist *evlist;
113 struct machine *host;
114 struct thread *current;
115 u64 base_time;
116 FILE *output;
117 unsigned long nr_events;
118 struct strlist *ev_qualifier;
119 struct {
120 size_t nr;
121 int *entries;
122 } ev_qualifier_ids;
123 struct intlist *tid_list;
124 struct intlist *pid_list;
125 struct {
126 size_t nr;
127 pid_t *entries;
128 } filter_pids;
129 double duration_filter;
130 double runtime_ms;
131 struct {
132 u64 vfs_getname,
133 proc_getname;
134 } stats;
135 bool not_ev_qualifier;
136 bool live;
137 bool full_time;
138 bool sched;
139 bool multiple_threads;
140 bool summary;
141 bool summary_only;
142 bool show_comm;
143 bool show_tool_stats;
144 bool trace_syscalls;
44621819 145 bool kernel_syscallchains;
d1d438a3
ACM
146 bool force;
147 bool vfs_getname;
148 int trace_pgfaults;
fd0db102 149 int open_id;
d1d438a3 150};
a1c2552d 151
77170988
ACM
152struct tp_field {
153 int offset;
154 union {
155 u64 (*integer)(struct tp_field *field, struct perf_sample *sample);
156 void *(*pointer)(struct tp_field *field, struct perf_sample *sample);
157 };
158};
159
160#define TP_UINT_FIELD(bits) \
161static u64 tp_field__u##bits(struct tp_field *field, struct perf_sample *sample) \
162{ \
55d43bca
DA
163 u##bits value; \
164 memcpy(&value, sample->raw_data + field->offset, sizeof(value)); \
165 return value; \
77170988
ACM
166}
167
168TP_UINT_FIELD(8);
169TP_UINT_FIELD(16);
170TP_UINT_FIELD(32);
171TP_UINT_FIELD(64);
172
173#define TP_UINT_FIELD__SWAPPED(bits) \
174static u64 tp_field__swapped_u##bits(struct tp_field *field, struct perf_sample *sample) \
175{ \
55d43bca
DA
176 u##bits value; \
177 memcpy(&value, sample->raw_data + field->offset, sizeof(value)); \
77170988
ACM
178 return bswap_##bits(value);\
179}
180
181TP_UINT_FIELD__SWAPPED(16);
182TP_UINT_FIELD__SWAPPED(32);
183TP_UINT_FIELD__SWAPPED(64);
184
185static int tp_field__init_uint(struct tp_field *field,
186 struct format_field *format_field,
187 bool needs_swap)
188{
189 field->offset = format_field->offset;
190
191 switch (format_field->size) {
192 case 1:
193 field->integer = tp_field__u8;
194 break;
195 case 2:
196 field->integer = needs_swap ? tp_field__swapped_u16 : tp_field__u16;
197 break;
198 case 4:
199 field->integer = needs_swap ? tp_field__swapped_u32 : tp_field__u32;
200 break;
201 case 8:
202 field->integer = needs_swap ? tp_field__swapped_u64 : tp_field__u64;
203 break;
204 default:
205 return -1;
206 }
207
208 return 0;
209}
210
211static void *tp_field__ptr(struct tp_field *field, struct perf_sample *sample)
212{
213 return sample->raw_data + field->offset;
214}
215
216static int tp_field__init_ptr(struct tp_field *field, struct format_field *format_field)
217{
218 field->offset = format_field->offset;
219 field->pointer = tp_field__ptr;
220 return 0;
221}
222
223struct syscall_tp {
224 struct tp_field id;
225 union {
226 struct tp_field args, ret;
227 };
228};
229
230static int perf_evsel__init_tp_uint_field(struct perf_evsel *evsel,
231 struct tp_field *field,
232 const char *name)
233{
234 struct format_field *format_field = perf_evsel__field(evsel, name);
235
236 if (format_field == NULL)
237 return -1;
238
239 return tp_field__init_uint(field, format_field, evsel->needs_swap);
240}
241
242#define perf_evsel__init_sc_tp_uint_field(evsel, name) \
243 ({ struct syscall_tp *sc = evsel->priv;\
244 perf_evsel__init_tp_uint_field(evsel, &sc->name, #name); })
245
246static int perf_evsel__init_tp_ptr_field(struct perf_evsel *evsel,
247 struct tp_field *field,
248 const char *name)
249{
250 struct format_field *format_field = perf_evsel__field(evsel, name);
251
252 if (format_field == NULL)
253 return -1;
254
255 return tp_field__init_ptr(field, format_field);
256}
257
258#define perf_evsel__init_sc_tp_ptr_field(evsel, name) \
259 ({ struct syscall_tp *sc = evsel->priv;\
260 perf_evsel__init_tp_ptr_field(evsel, &sc->name, #name); })
261
262static void perf_evsel__delete_priv(struct perf_evsel *evsel)
263{
04662523 264 zfree(&evsel->priv);
77170988
ACM
265 perf_evsel__delete(evsel);
266}
267
96695d44
NK
268static int perf_evsel__init_syscall_tp(struct perf_evsel *evsel, void *handler)
269{
270 evsel->priv = malloc(sizeof(struct syscall_tp));
271 if (evsel->priv != NULL) {
272 if (perf_evsel__init_sc_tp_uint_field(evsel, id))
273 goto out_delete;
274
275 evsel->handler = handler;
276 return 0;
277 }
278
279 return -ENOMEM;
280
281out_delete:
04662523 282 zfree(&evsel->priv);
96695d44
NK
283 return -ENOENT;
284}
285
ef503831 286static struct perf_evsel *perf_evsel__syscall_newtp(const char *direction, void *handler)
77170988 287{
ef503831 288 struct perf_evsel *evsel = perf_evsel__newtp("raw_syscalls", direction);
77170988 289
9aca7f17 290 /* older kernel (e.g., RHEL6) use syscalls:{enter,exit} */
8dd2a131 291 if (IS_ERR(evsel))
9aca7f17
DA
292 evsel = perf_evsel__newtp("syscalls", direction);
293
8dd2a131
JO
294 if (IS_ERR(evsel))
295 return NULL;
296
297 if (perf_evsel__init_syscall_tp(evsel, handler))
298 goto out_delete;
77170988
ACM
299
300 return evsel;
301
302out_delete:
303 perf_evsel__delete_priv(evsel);
304 return NULL;
305}
306
307#define perf_evsel__sc_tp_uint(evsel, name, sample) \
308 ({ struct syscall_tp *fields = evsel->priv; \
309 fields->name.integer(&fields->name, sample); })
310
311#define perf_evsel__sc_tp_ptr(evsel, name, sample) \
312 ({ struct syscall_tp *fields = evsel->priv; \
313 fields->name.pointer(&fields->name, sample); })
314
01533e97
ACM
315struct syscall_arg {
316 unsigned long val;
75b757ca
ACM
317 struct thread *thread;
318 struct trace *trace;
1f115cb7 319 void *parm;
01533e97
ACM
320 u8 idx;
321 u8 mask;
322};
323
1f115cb7 324struct strarray {
03e3adc9 325 int offset;
1f115cb7
ACM
326 int nr_entries;
327 const char **entries;
328};
329
330#define DEFINE_STRARRAY(array) struct strarray strarray__##array = { \
331 .nr_entries = ARRAY_SIZE(array), \
332 .entries = array, \
333}
334
03e3adc9
ACM
335#define DEFINE_STRARRAY_OFFSET(array, off) struct strarray strarray__##array = { \
336 .offset = off, \
337 .nr_entries = ARRAY_SIZE(array), \
338 .entries = array, \
339}
340
975b7c2f
ACM
341static size_t __syscall_arg__scnprintf_strarray(char *bf, size_t size,
342 const char *intfmt,
343 struct syscall_arg *arg)
1f115cb7 344{
1f115cb7 345 struct strarray *sa = arg->parm;
03e3adc9 346 int idx = arg->val - sa->offset;
1f115cb7
ACM
347
348 if (idx < 0 || idx >= sa->nr_entries)
975b7c2f 349 return scnprintf(bf, size, intfmt, arg->val);
1f115cb7
ACM
350
351 return scnprintf(bf, size, "%s", sa->entries[idx]);
352}
353
975b7c2f
ACM
354static size_t syscall_arg__scnprintf_strarray(char *bf, size_t size,
355 struct syscall_arg *arg)
356{
357 return __syscall_arg__scnprintf_strarray(bf, size, "%d", arg);
358}
359
1f115cb7
ACM
360#define SCA_STRARRAY syscall_arg__scnprintf_strarray
361
844ae5b4
ACM
362#if defined(__i386__) || defined(__x86_64__)
363/*
364 * FIXME: Make this available to all arches as soon as the ioctl beautifier
365 * gets rewritten to support all arches.
366 */
78645cf3
ACM
367static size_t syscall_arg__scnprintf_strhexarray(char *bf, size_t size,
368 struct syscall_arg *arg)
369{
370 return __syscall_arg__scnprintf_strarray(bf, size, "%#x", arg);
371}
372
373#define SCA_STRHEXARRAY syscall_arg__scnprintf_strhexarray
844ae5b4 374#endif /* defined(__i386__) || defined(__x86_64__) */
78645cf3 375
75b757ca
ACM
376static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
377 struct syscall_arg *arg);
378
379#define SCA_FD syscall_arg__scnprintf_fd
380
381static size_t syscall_arg__scnprintf_fd_at(char *bf, size_t size,
382 struct syscall_arg *arg)
383{
384 int fd = arg->val;
385
386 if (fd == AT_FDCWD)
387 return scnprintf(bf, size, "CWD");
388
389 return syscall_arg__scnprintf_fd(bf, size, arg);
390}
391
392#define SCA_FDAT syscall_arg__scnprintf_fd_at
393
394static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
395 struct syscall_arg *arg);
396
397#define SCA_CLOSE_FD syscall_arg__scnprintf_close_fd
398
6e7eeb51 399static size_t syscall_arg__scnprintf_hex(char *bf, size_t size,
01533e97 400 struct syscall_arg *arg)
13d4ff3e 401{
01533e97 402 return scnprintf(bf, size, "%#lx", arg->val);
13d4ff3e
ACM
403}
404
beccb2b5
ACM
405#define SCA_HEX syscall_arg__scnprintf_hex
406
a1c2552d
ACM
407static size_t syscall_arg__scnprintf_int(char *bf, size_t size,
408 struct syscall_arg *arg)
409{
410 return scnprintf(bf, size, "%d", arg->val);
411}
412
413#define SCA_INT syscall_arg__scnprintf_int
414
5cea6ff2
ACM
415static size_t syscall_arg__scnprintf_flock(char *bf, size_t size,
416 struct syscall_arg *arg)
417{
418 int printed = 0, op = arg->val;
419
420 if (op == 0)
421 return scnprintf(bf, size, "NONE");
422#define P_CMD(cmd) \
423 if ((op & LOCK_##cmd) == LOCK_##cmd) { \
424 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #cmd); \
425 op &= ~LOCK_##cmd; \
426 }
427
428 P_CMD(SH);
429 P_CMD(EX);
430 P_CMD(NB);
431 P_CMD(UN);
432 P_CMD(MAND);
433 P_CMD(RW);
434 P_CMD(READ);
435 P_CMD(WRITE);
436#undef P_OP
437
438 if (op)
439 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", op);
440
441 return printed;
442}
443
444#define SCA_FLOCK syscall_arg__scnprintf_flock
445
01533e97 446static size_t syscall_arg__scnprintf_futex_op(char *bf, size_t size, struct syscall_arg *arg)
f9da0b0c
ACM
447{
448 enum syscall_futex_args {
449 SCF_UADDR = (1 << 0),
450 SCF_OP = (1 << 1),
451 SCF_VAL = (1 << 2),
452 SCF_TIMEOUT = (1 << 3),
453 SCF_UADDR2 = (1 << 4),
454 SCF_VAL3 = (1 << 5),
455 };
01533e97 456 int op = arg->val;
f9da0b0c
ACM
457 int cmd = op & FUTEX_CMD_MASK;
458 size_t printed = 0;
459
460 switch (cmd) {
461#define P_FUTEX_OP(n) case FUTEX_##n: printed = scnprintf(bf, size, #n);
01533e97
ACM
462 P_FUTEX_OP(WAIT); arg->mask |= SCF_VAL3|SCF_UADDR2; break;
463 P_FUTEX_OP(WAKE); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
464 P_FUTEX_OP(FD); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
465 P_FUTEX_OP(REQUEUE); arg->mask |= SCF_VAL3|SCF_TIMEOUT; break;
466 P_FUTEX_OP(CMP_REQUEUE); arg->mask |= SCF_TIMEOUT; break;
467 P_FUTEX_OP(CMP_REQUEUE_PI); arg->mask |= SCF_TIMEOUT; break;
f9da0b0c 468 P_FUTEX_OP(WAKE_OP); break;
01533e97
ACM
469 P_FUTEX_OP(LOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
470 P_FUTEX_OP(UNLOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
471 P_FUTEX_OP(TRYLOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2; break;
472 P_FUTEX_OP(WAIT_BITSET); arg->mask |= SCF_UADDR2; break;
473 P_FUTEX_OP(WAKE_BITSET); arg->mask |= SCF_UADDR2; break;
f9da0b0c
ACM
474 P_FUTEX_OP(WAIT_REQUEUE_PI); break;
475 default: printed = scnprintf(bf, size, "%#x", cmd); break;
476 }
477
478 if (op & FUTEX_PRIVATE_FLAG)
479 printed += scnprintf(bf + printed, size - printed, "|PRIV");
480
481 if (op & FUTEX_CLOCK_REALTIME)
482 printed += scnprintf(bf + printed, size - printed, "|CLKRT");
483
484 return printed;
485}
486
efe6b882
ACM
487#define SCA_FUTEX_OP syscall_arg__scnprintf_futex_op
488
729a7841
ACM
489static const char *bpf_cmd[] = {
490 "MAP_CREATE", "MAP_LOOKUP_ELEM", "MAP_UPDATE_ELEM", "MAP_DELETE_ELEM",
491 "MAP_GET_NEXT_KEY", "PROG_LOAD",
492};
493static DEFINE_STRARRAY(bpf_cmd);
494
03e3adc9
ACM
495static const char *epoll_ctl_ops[] = { "ADD", "DEL", "MOD", };
496static DEFINE_STRARRAY_OFFSET(epoll_ctl_ops, 1);
eac032c5 497
1f115cb7
ACM
498static const char *itimers[] = { "REAL", "VIRTUAL", "PROF", };
499static DEFINE_STRARRAY(itimers);
500
b62bee1b
ACM
501static const char *keyctl_options[] = {
502 "GET_KEYRING_ID", "JOIN_SESSION_KEYRING", "UPDATE", "REVOKE", "CHOWN",
503 "SETPERM", "DESCRIBE", "CLEAR", "LINK", "UNLINK", "SEARCH", "READ",
504 "INSTANTIATE", "NEGATE", "SET_REQKEY_KEYRING", "SET_TIMEOUT",
505 "ASSUME_AUTHORITY", "GET_SECURITY", "SESSION_TO_PARENT", "REJECT",
506 "INSTANTIATE_IOV", "INVALIDATE", "GET_PERSISTENT",
507};
508static DEFINE_STRARRAY(keyctl_options);
509
efe6b882
ACM
510static const char *whences[] = { "SET", "CUR", "END",
511#ifdef SEEK_DATA
512"DATA",
513#endif
514#ifdef SEEK_HOLE
515"HOLE",
516#endif
517};
518static DEFINE_STRARRAY(whences);
f9da0b0c 519
80f587d5
ACM
520static const char *fcntl_cmds[] = {
521 "DUPFD", "GETFD", "SETFD", "GETFL", "SETFL", "GETLK", "SETLK",
522 "SETLKW", "SETOWN", "GETOWN", "SETSIG", "GETSIG", "F_GETLK64",
523 "F_SETLK64", "F_SETLKW64", "F_SETOWN_EX", "F_GETOWN_EX",
524 "F_GETOWNER_UIDS",
525};
526static DEFINE_STRARRAY(fcntl_cmds);
527
c045bf02
ACM
528static const char *rlimit_resources[] = {
529 "CPU", "FSIZE", "DATA", "STACK", "CORE", "RSS", "NPROC", "NOFILE",
530 "MEMLOCK", "AS", "LOCKS", "SIGPENDING", "MSGQUEUE", "NICE", "RTPRIO",
531 "RTTIME",
532};
533static DEFINE_STRARRAY(rlimit_resources);
534
eb5b1b14
ACM
535static const char *sighow[] = { "BLOCK", "UNBLOCK", "SETMASK", };
536static DEFINE_STRARRAY(sighow);
537
4f8c1b74
DA
538static const char *clockid[] = {
539 "REALTIME", "MONOTONIC", "PROCESS_CPUTIME_ID", "THREAD_CPUTIME_ID",
28ebb87c
ACM
540 "MONOTONIC_RAW", "REALTIME_COARSE", "MONOTONIC_COARSE", "BOOTTIME",
541 "REALTIME_ALARM", "BOOTTIME_ALARM", "SGI_CYCLE", "TAI"
4f8c1b74
DA
542};
543static DEFINE_STRARRAY(clockid);
544
e10bce81
ACM
545static const char *socket_families[] = {
546 "UNSPEC", "LOCAL", "INET", "AX25", "IPX", "APPLETALK", "NETROM",
547 "BRIDGE", "ATMPVC", "X25", "INET6", "ROSE", "DECnet", "NETBEUI",
548 "SECURITY", "KEY", "NETLINK", "PACKET", "ASH", "ECONET", "ATMSVC",
549 "RDS", "SNA", "IRDA", "PPPOX", "WANPIPE", "LLC", "IB", "CAN", "TIPC",
550 "BLUETOOTH", "IUCV", "RXRPC", "ISDN", "PHONET", "IEEE802154", "CAIF",
551 "ALG", "NFC", "VSOCK",
552};
553static DEFINE_STRARRAY(socket_families);
554
a28b24b2
ACM
555#ifndef SOCK_TYPE_MASK
556#define SOCK_TYPE_MASK 0xf
557#endif
558
559static size_t syscall_arg__scnprintf_socket_type(char *bf, size_t size,
560 struct syscall_arg *arg)
561{
562 size_t printed;
563 int type = arg->val,
564 flags = type & ~SOCK_TYPE_MASK;
565
566 type &= SOCK_TYPE_MASK;
567 /*
568 * Can't use a strarray, MIPS may override for ABI reasons.
569 */
570 switch (type) {
571#define P_SK_TYPE(n) case SOCK_##n: printed = scnprintf(bf, size, #n); break;
572 P_SK_TYPE(STREAM);
573 P_SK_TYPE(DGRAM);
574 P_SK_TYPE(RAW);
575 P_SK_TYPE(RDM);
576 P_SK_TYPE(SEQPACKET);
577 P_SK_TYPE(DCCP);
578 P_SK_TYPE(PACKET);
579#undef P_SK_TYPE
580 default:
581 printed = scnprintf(bf, size, "%#x", type);
582 }
583
584#define P_SK_FLAG(n) \
585 if (flags & SOCK_##n) { \
586 printed += scnprintf(bf + printed, size - printed, "|%s", #n); \
587 flags &= ~SOCK_##n; \
588 }
589
590 P_SK_FLAG(CLOEXEC);
591 P_SK_FLAG(NONBLOCK);
592#undef P_SK_FLAG
593
594 if (flags)
595 printed += scnprintf(bf + printed, size - printed, "|%#x", flags);
596
597 return printed;
598}
599
600#define SCA_SK_TYPE syscall_arg__scnprintf_socket_type
601
b2cc99fd
ACM
602#ifndef MSG_PROBE
603#define MSG_PROBE 0x10
604#endif
b6e8f8f4
DA
605#ifndef MSG_WAITFORONE
606#define MSG_WAITFORONE 0x10000
607#endif
b2cc99fd
ACM
608#ifndef MSG_SENDPAGE_NOTLAST
609#define MSG_SENDPAGE_NOTLAST 0x20000
610#endif
611#ifndef MSG_FASTOPEN
612#define MSG_FASTOPEN 0x20000000
613#endif
614
615static size_t syscall_arg__scnprintf_msg_flags(char *bf, size_t size,
616 struct syscall_arg *arg)
617{
618 int printed = 0, flags = arg->val;
619
620 if (flags == 0)
621 return scnprintf(bf, size, "NONE");
622#define P_MSG_FLAG(n) \
623 if (flags & MSG_##n) { \
624 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
625 flags &= ~MSG_##n; \
626 }
627
628 P_MSG_FLAG(OOB);
629 P_MSG_FLAG(PEEK);
630 P_MSG_FLAG(DONTROUTE);
631 P_MSG_FLAG(TRYHARD);
632 P_MSG_FLAG(CTRUNC);
633 P_MSG_FLAG(PROBE);
634 P_MSG_FLAG(TRUNC);
635 P_MSG_FLAG(DONTWAIT);
636 P_MSG_FLAG(EOR);
637 P_MSG_FLAG(WAITALL);
638 P_MSG_FLAG(FIN);
639 P_MSG_FLAG(SYN);
640 P_MSG_FLAG(CONFIRM);
641 P_MSG_FLAG(RST);
642 P_MSG_FLAG(ERRQUEUE);
643 P_MSG_FLAG(NOSIGNAL);
644 P_MSG_FLAG(MORE);
645 P_MSG_FLAG(WAITFORONE);
646 P_MSG_FLAG(SENDPAGE_NOTLAST);
647 P_MSG_FLAG(FASTOPEN);
648 P_MSG_FLAG(CMSG_CLOEXEC);
649#undef P_MSG_FLAG
650
651 if (flags)
652 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
653
654 return printed;
655}
656
657#define SCA_MSG_FLAGS syscall_arg__scnprintf_msg_flags
658
51108999
ACM
659static size_t syscall_arg__scnprintf_access_mode(char *bf, size_t size,
660 struct syscall_arg *arg)
661{
662 size_t printed = 0;
663 int mode = arg->val;
664
665 if (mode == F_OK) /* 0 */
666 return scnprintf(bf, size, "F");
667#define P_MODE(n) \
668 if (mode & n##_OK) { \
669 printed += scnprintf(bf + printed, size - printed, "%s", #n); \
670 mode &= ~n##_OK; \
671 }
672
673 P_MODE(R);
674 P_MODE(W);
675 P_MODE(X);
676#undef P_MODE
677
678 if (mode)
679 printed += scnprintf(bf + printed, size - printed, "|%#x", mode);
680
681 return printed;
682}
683
684#define SCA_ACCMODE syscall_arg__scnprintf_access_mode
685
f994592d
ACM
686static size_t syscall_arg__scnprintf_filename(char *bf, size_t size,
687 struct syscall_arg *arg);
688
689#define SCA_FILENAME syscall_arg__scnprintf_filename
690
be65a89a 691static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
01533e97 692 struct syscall_arg *arg)
be65a89a 693{
01533e97 694 int printed = 0, flags = arg->val;
be65a89a
ACM
695
696 if (!(flags & O_CREAT))
01533e97 697 arg->mask |= 1 << (arg->idx + 1); /* Mask the mode parm */
be65a89a
ACM
698
699 if (flags == 0)
700 return scnprintf(bf, size, "RDONLY");
701#define P_FLAG(n) \
702 if (flags & O_##n) { \
703 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
704 flags &= ~O_##n; \
705 }
706
707 P_FLAG(APPEND);
708 P_FLAG(ASYNC);
709 P_FLAG(CLOEXEC);
710 P_FLAG(CREAT);
711 P_FLAG(DIRECT);
712 P_FLAG(DIRECTORY);
713 P_FLAG(EXCL);
714 P_FLAG(LARGEFILE);
715 P_FLAG(NOATIME);
716 P_FLAG(NOCTTY);
717#ifdef O_NONBLOCK
718 P_FLAG(NONBLOCK);
719#elif O_NDELAY
720 P_FLAG(NDELAY);
721#endif
722#ifdef O_PATH
723 P_FLAG(PATH);
724#endif
725 P_FLAG(RDWR);
726#ifdef O_DSYNC
727 if ((flags & O_SYNC) == O_SYNC)
728 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", "SYNC");
729 else {
730 P_FLAG(DSYNC);
731 }
732#else
733 P_FLAG(SYNC);
734#endif
735 P_FLAG(TRUNC);
736 P_FLAG(WRONLY);
737#undef P_FLAG
738
739 if (flags)
740 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
741
742 return printed;
743}
744
745#define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags
746
a1c2552d
ACM
747static size_t syscall_arg__scnprintf_perf_flags(char *bf, size_t size,
748 struct syscall_arg *arg)
749{
750 int printed = 0, flags = arg->val;
751
752 if (flags == 0)
753 return 0;
754
755#define P_FLAG(n) \
756 if (flags & PERF_FLAG_##n) { \
757 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
758 flags &= ~PERF_FLAG_##n; \
759 }
760
761 P_FLAG(FD_NO_GROUP);
762 P_FLAG(FD_OUTPUT);
763 P_FLAG(PID_CGROUP);
764 P_FLAG(FD_CLOEXEC);
765#undef P_FLAG
766
767 if (flags)
768 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
769
770 return printed;
771}
772
773#define SCA_PERF_FLAGS syscall_arg__scnprintf_perf_flags
774
49af9e93
ACM
775static size_t syscall_arg__scnprintf_eventfd_flags(char *bf, size_t size,
776 struct syscall_arg *arg)
777{
778 int printed = 0, flags = arg->val;
779
780 if (flags == 0)
781 return scnprintf(bf, size, "NONE");
782#define P_FLAG(n) \
783 if (flags & EFD_##n) { \
784 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
785 flags &= ~EFD_##n; \
786 }
787
788 P_FLAG(SEMAPHORE);
789 P_FLAG(CLOEXEC);
790 P_FLAG(NONBLOCK);
791#undef P_FLAG
792
793 if (flags)
794 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
795
796 return printed;
797}
798
799#define SCA_EFD_FLAGS syscall_arg__scnprintf_eventfd_flags
800
46cce19b
ACM
801static size_t syscall_arg__scnprintf_pipe_flags(char *bf, size_t size,
802 struct syscall_arg *arg)
803{
804 int printed = 0, flags = arg->val;
805
806#define P_FLAG(n) \
807 if (flags & O_##n) { \
808 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
809 flags &= ~O_##n; \
810 }
811
812 P_FLAG(CLOEXEC);
813 P_FLAG(NONBLOCK);
814#undef P_FLAG
815
816 if (flags)
817 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
818
819 return printed;
820}
821
822#define SCA_PIPE_FLAGS syscall_arg__scnprintf_pipe_flags
823
8bad5b0a
ACM
824static size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscall_arg *arg)
825{
826 int sig = arg->val;
827
828 switch (sig) {
829#define P_SIGNUM(n) case SIG##n: return scnprintf(bf, size, #n)
830 P_SIGNUM(HUP);
831 P_SIGNUM(INT);
832 P_SIGNUM(QUIT);
833 P_SIGNUM(ILL);
834 P_SIGNUM(TRAP);
835 P_SIGNUM(ABRT);
836 P_SIGNUM(BUS);
837 P_SIGNUM(FPE);
838 P_SIGNUM(KILL);
839 P_SIGNUM(USR1);
840 P_SIGNUM(SEGV);
841 P_SIGNUM(USR2);
842 P_SIGNUM(PIPE);
843 P_SIGNUM(ALRM);
844 P_SIGNUM(TERM);
8bad5b0a
ACM
845 P_SIGNUM(CHLD);
846 P_SIGNUM(CONT);
847 P_SIGNUM(STOP);
848 P_SIGNUM(TSTP);
849 P_SIGNUM(TTIN);
850 P_SIGNUM(TTOU);
851 P_SIGNUM(URG);
852 P_SIGNUM(XCPU);
853 P_SIGNUM(XFSZ);
854 P_SIGNUM(VTALRM);
855 P_SIGNUM(PROF);
856 P_SIGNUM(WINCH);
857 P_SIGNUM(IO);
858 P_SIGNUM(PWR);
859 P_SIGNUM(SYS);
02c5bb4a
BH
860#ifdef SIGEMT
861 P_SIGNUM(EMT);
862#endif
863#ifdef SIGSTKFLT
864 P_SIGNUM(STKFLT);
865#endif
866#ifdef SIGSWI
867 P_SIGNUM(SWI);
868#endif
8bad5b0a
ACM
869 default: break;
870 }
871
872 return scnprintf(bf, size, "%#x", sig);
873}
874
875#define SCA_SIGNUM syscall_arg__scnprintf_signum
876
844ae5b4
ACM
877#if defined(__i386__) || defined(__x86_64__)
878/*
879 * FIXME: Make this available to all arches.
880 */
78645cf3
ACM
881#define TCGETS 0x5401
882
883static const char *tioctls[] = {
884 "TCGETS", "TCSETS", "TCSETSW", "TCSETSF", "TCGETA", "TCSETA", "TCSETAW",
885 "TCSETAF", "TCSBRK", "TCXONC", "TCFLSH", "TIOCEXCL", "TIOCNXCL",
886 "TIOCSCTTY", "TIOCGPGRP", "TIOCSPGRP", "TIOCOUTQ", "TIOCSTI",
887 "TIOCGWINSZ", "TIOCSWINSZ", "TIOCMGET", "TIOCMBIS", "TIOCMBIC",
888 "TIOCMSET", "TIOCGSOFTCAR", "TIOCSSOFTCAR", "FIONREAD", "TIOCLINUX",
889 "TIOCCONS", "TIOCGSERIAL", "TIOCSSERIAL", "TIOCPKT", "FIONBIO",
890 "TIOCNOTTY", "TIOCSETD", "TIOCGETD", "TCSBRKP", [0x27] = "TIOCSBRK",
891 "TIOCCBRK", "TIOCGSID", "TCGETS2", "TCSETS2", "TCSETSW2", "TCSETSF2",
892 "TIOCGRS485", "TIOCSRS485", "TIOCGPTN", "TIOCSPTLCK",
893 "TIOCGDEV||TCGETX", "TCSETX", "TCSETXF", "TCSETXW", "TIOCSIG",
894 "TIOCVHANGUP", "TIOCGPKT", "TIOCGPTLCK", "TIOCGEXCL",
895 [0x50] = "FIONCLEX", "FIOCLEX", "FIOASYNC", "TIOCSERCONFIG",
896 "TIOCSERGWILD", "TIOCSERSWILD", "TIOCGLCKTRMIOS", "TIOCSLCKTRMIOS",
897 "TIOCSERGSTRUCT", "TIOCSERGETLSR", "TIOCSERGETMULTI", "TIOCSERSETMULTI",
898 "TIOCMIWAIT", "TIOCGICOUNT", [0x60] = "FIOQSIZE",
899};
900
901static DEFINE_STRARRAY_OFFSET(tioctls, 0x5401);
844ae5b4 902#endif /* defined(__i386__) || defined(__x86_64__) */
78645cf3 903
6fb35b95
ACM
904#ifndef SECCOMP_SET_MODE_STRICT
905#define SECCOMP_SET_MODE_STRICT 0
906#endif
907#ifndef SECCOMP_SET_MODE_FILTER
908#define SECCOMP_SET_MODE_FILTER 1
909#endif
910
997bba8c
ACM
911static size_t syscall_arg__scnprintf_seccomp_op(char *bf, size_t size, struct syscall_arg *arg)
912{
913 int op = arg->val;
914 size_t printed = 0;
915
916 switch (op) {
917#define P_SECCOMP_SET_MODE_OP(n) case SECCOMP_SET_MODE_##n: printed = scnprintf(bf, size, #n); break
918 P_SECCOMP_SET_MODE_OP(STRICT);
919 P_SECCOMP_SET_MODE_OP(FILTER);
920#undef P_SECCOMP_SET_MODE_OP
921 default: printed = scnprintf(bf, size, "%#x", op); break;
922 }
923
924 return printed;
925}
926
927#define SCA_SECCOMP_OP syscall_arg__scnprintf_seccomp_op
928
6fb35b95
ACM
929#ifndef SECCOMP_FILTER_FLAG_TSYNC
930#define SECCOMP_FILTER_FLAG_TSYNC 1
931#endif
932
997bba8c
ACM
933static size_t syscall_arg__scnprintf_seccomp_flags(char *bf, size_t size,
934 struct syscall_arg *arg)
935{
936 int printed = 0, flags = arg->val;
937
938#define P_FLAG(n) \
939 if (flags & SECCOMP_FILTER_FLAG_##n) { \
940 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
941 flags &= ~SECCOMP_FILTER_FLAG_##n; \
942 }
943
944 P_FLAG(TSYNC);
945#undef P_FLAG
946
947 if (flags)
948 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
949
950 return printed;
951}
952
953#define SCA_SECCOMP_FLAGS syscall_arg__scnprintf_seccomp_flags
954
a355a61e
ACM
955#ifndef GRND_NONBLOCK
956#define GRND_NONBLOCK 0x0001
957#endif
958#ifndef GRND_RANDOM
959#define GRND_RANDOM 0x0002
960#endif
961
39878d49
ACM
962static size_t syscall_arg__scnprintf_getrandom_flags(char *bf, size_t size,
963 struct syscall_arg *arg)
964{
965 int printed = 0, flags = arg->val;
966
967#define P_FLAG(n) \
968 if (flags & GRND_##n) { \
969 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
970 flags &= ~GRND_##n; \
971 }
972
973 P_FLAG(RANDOM);
974 P_FLAG(NONBLOCK);
975#undef P_FLAG
976
977 if (flags)
978 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
979
980 return printed;
981}
982
983#define SCA_GETRANDOM_FLAGS syscall_arg__scnprintf_getrandom_flags
984
453350dd
ACM
985#define STRARRAY(arg, name, array) \
986 .arg_scnprintf = { [arg] = SCA_STRARRAY, }, \
987 .arg_parm = { [arg] = &strarray__##array, }
988
d1d438a3 989#include "trace/beauty/pid.c"
df4cb167 990#include "trace/beauty/mmap.c"
ba2f22cf 991#include "trace/beauty/mode_t.c"
a3bca91f 992#include "trace/beauty/sched_policy.c"
7206b900 993#include "trace/beauty/waitid_options.c"
a3bca91f 994
514f1c67
ACM
995static struct syscall_fmt {
996 const char *name;
aec1930b 997 const char *alias;
01533e97 998 size_t (*arg_scnprintf[6])(char *bf, size_t size, struct syscall_arg *arg);
1f115cb7 999 void *arg_parm[6];
514f1c67 1000 bool errmsg;
11c8e39f 1001 bool errpid;
514f1c67 1002 bool timeout;
04b34729 1003 bool hexret;
514f1c67 1004} syscall_fmts[] = {
51108999 1005 { .name = "access", .errmsg = true,
34221118
ACM
1006 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */
1007 [1] = SCA_ACCMODE, /* mode */ }, },
aec1930b 1008 { .name = "arch_prctl", .errmsg = true, .alias = "prctl", },
729a7841 1009 { .name = "bpf", .errmsg = true, STRARRAY(0, cmd, bpf_cmd), },
beccb2b5
ACM
1010 { .name = "brk", .hexret = true,
1011 .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, },
34221118
ACM
1012 { .name = "chdir", .errmsg = true,
1013 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
1014 { .name = "chmod", .errmsg = true,
1015 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
1016 { .name = "chroot", .errmsg = true,
1017 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
4f8c1b74 1018 { .name = "clock_gettime", .errmsg = true, STRARRAY(0, clk_id, clockid), },
11c8e39f 1019 { .name = "clone", .errpid = true, },
75b757ca 1020 { .name = "close", .errmsg = true,
48000a1a 1021 .arg_scnprintf = { [0] = SCA_CLOSE_FD, /* fd */ }, },
a14bb860 1022 { .name = "connect", .errmsg = true, },
34221118
ACM
1023 { .name = "creat", .errmsg = true,
1024 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
75b757ca 1025 { .name = "dup", .errmsg = true,
48000a1a 1026 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
75b757ca 1027 { .name = "dup2", .errmsg = true,
48000a1a 1028 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
75b757ca 1029 { .name = "dup3", .errmsg = true,
48000a1a 1030 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
453350dd 1031 { .name = "epoll_ctl", .errmsg = true, STRARRAY(1, op, epoll_ctl_ops), },
49af9e93
ACM
1032 { .name = "eventfd2", .errmsg = true,
1033 .arg_scnprintf = { [1] = SCA_EFD_FLAGS, /* flags */ }, },
75b757ca 1034 { .name = "faccessat", .errmsg = true,
34221118
ACM
1035 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
1036 [1] = SCA_FILENAME, /* filename */ }, },
75b757ca 1037 { .name = "fadvise64", .errmsg = true,
48000a1a 1038 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
75b757ca 1039 { .name = "fallocate", .errmsg = true,
48000a1a 1040 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
75b757ca 1041 { .name = "fchdir", .errmsg = true,
48000a1a 1042 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
75b757ca 1043 { .name = "fchmod", .errmsg = true,
48000a1a 1044 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
75b757ca 1045 { .name = "fchmodat", .errmsg = true,
090389b6
ACM
1046 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */
1047 [1] = SCA_FILENAME, /* filename */ }, },
75b757ca 1048 { .name = "fchown", .errmsg = true,
48000a1a 1049 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
75b757ca 1050 { .name = "fchownat", .errmsg = true,
34221118
ACM
1051 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */
1052 [1] = SCA_FILENAME, /* filename */ }, },
75b757ca
ACM
1053 { .name = "fcntl", .errmsg = true,
1054 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1055 [1] = SCA_STRARRAY, /* cmd */ },
1056 .arg_parm = { [1] = &strarray__fcntl_cmds, /* cmd */ }, },
1057 { .name = "fdatasync", .errmsg = true,
48000a1a 1058 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
5cea6ff2 1059 { .name = "flock", .errmsg = true,
75b757ca
ACM
1060 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1061 [1] = SCA_FLOCK, /* cmd */ }, },
1062 { .name = "fsetxattr", .errmsg = true,
48000a1a 1063 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
75b757ca 1064 { .name = "fstat", .errmsg = true, .alias = "newfstat",
48000a1a 1065 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
75b757ca 1066 { .name = "fstatat", .errmsg = true, .alias = "newfstatat",
34221118
ACM
1067 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
1068 [1] = SCA_FILENAME, /* filename */ }, },
75b757ca 1069 { .name = "fstatfs", .errmsg = true,
48000a1a 1070 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
75b757ca 1071 { .name = "fsync", .errmsg = true,
48000a1a 1072 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
75b757ca 1073 { .name = "ftruncate", .errmsg = true,
48000a1a 1074 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
f9da0b0c
ACM
1075 { .name = "futex", .errmsg = true,
1076 .arg_scnprintf = { [1] = SCA_FUTEX_OP, /* op */ }, },
75b757ca 1077 { .name = "futimesat", .errmsg = true,
090389b6
ACM
1078 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */
1079 [1] = SCA_FILENAME, /* filename */ }, },
75b757ca 1080 { .name = "getdents", .errmsg = true,
48000a1a 1081 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
75b757ca 1082 { .name = "getdents64", .errmsg = true,
48000a1a 1083 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
453350dd 1084 { .name = "getitimer", .errmsg = true, STRARRAY(0, which, itimers), },
c65f1070 1085 { .name = "getpid", .errpid = true, },
d1d438a3 1086 { .name = "getpgid", .errpid = true, },
c65f1070 1087 { .name = "getppid", .errpid = true, },
39878d49
ACM
1088 { .name = "getrandom", .errmsg = true,
1089 .arg_scnprintf = { [2] = SCA_GETRANDOM_FLAGS, /* flags */ }, },
453350dd 1090 { .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
34221118
ACM
1091 { .name = "getxattr", .errmsg = true,
1092 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
1093 { .name = "inotify_add_watch", .errmsg = true,
1094 .arg_scnprintf = { [1] = SCA_FILENAME, /* pathname */ }, },
beccb2b5 1095 { .name = "ioctl", .errmsg = true,
48000a1a 1096 .arg_scnprintf = { [0] = SCA_FD, /* fd */
844ae5b4
ACM
1097#if defined(__i386__) || defined(__x86_64__)
1098/*
1099 * FIXME: Make this available to all arches.
1100 */
78645cf3
ACM
1101 [1] = SCA_STRHEXARRAY, /* cmd */
1102 [2] = SCA_HEX, /* arg */ },
1103 .arg_parm = { [1] = &strarray__tioctls, /* cmd */ }, },
844ae5b4
ACM
1104#else
1105 [2] = SCA_HEX, /* arg */ }, },
1106#endif
b62bee1b 1107 { .name = "keyctl", .errmsg = true, STRARRAY(0, option, keyctl_options), },
8bad5b0a
ACM
1108 { .name = "kill", .errmsg = true,
1109 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
34221118
ACM
1110 { .name = "lchown", .errmsg = true,
1111 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
1112 { .name = "lgetxattr", .errmsg = true,
1113 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
75b757ca 1114 { .name = "linkat", .errmsg = true,
48000a1a 1115 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
34221118
ACM
1116 { .name = "listxattr", .errmsg = true,
1117 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
090389b6
ACM
1118 { .name = "llistxattr", .errmsg = true,
1119 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
1120 { .name = "lremovexattr", .errmsg = true,
1121 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
75b757ca
ACM
1122 { .name = "lseek", .errmsg = true,
1123 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1124 [2] = SCA_STRARRAY, /* whence */ },
1125 .arg_parm = { [2] = &strarray__whences, /* whence */ }, },
34221118
ACM
1126 { .name = "lsetxattr", .errmsg = true,
1127 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
090389b6
ACM
1128 { .name = "lstat", .errmsg = true, .alias = "newlstat",
1129 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
34221118
ACM
1130 { .name = "lsxattr", .errmsg = true,
1131 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
9e9716d1
ACM
1132 { .name = "madvise", .errmsg = true,
1133 .arg_scnprintf = { [0] = SCA_HEX, /* start */
1134 [2] = SCA_MADV_BHV, /* behavior */ }, },
34221118
ACM
1135 { .name = "mkdir", .errmsg = true,
1136 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
75b757ca 1137 { .name = "mkdirat", .errmsg = true,
34221118
ACM
1138 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */
1139 [1] = SCA_FILENAME, /* pathname */ }, },
1140 { .name = "mknod", .errmsg = true,
1141 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
75b757ca 1142 { .name = "mknodat", .errmsg = true,
090389b6
ACM
1143 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */
1144 [1] = SCA_FILENAME, /* filename */ }, },
3d903aa7
ACM
1145 { .name = "mlock", .errmsg = true,
1146 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
1147 { .name = "mlockall", .errmsg = true,
1148 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
beccb2b5 1149 { .name = "mmap", .hexret = true,
ae685380 1150 .arg_scnprintf = { [0] = SCA_HEX, /* addr */
941557e0 1151 [2] = SCA_MMAP_PROT, /* prot */
73faab3a
NK
1152 [3] = SCA_MMAP_FLAGS, /* flags */
1153 [4] = SCA_FD, /* fd */ }, },
beccb2b5 1154 { .name = "mprotect", .errmsg = true,
ae685380
ACM
1155 .arg_scnprintf = { [0] = SCA_HEX, /* start */
1156 [2] = SCA_MMAP_PROT, /* prot */ }, },
090389b6
ACM
1157 { .name = "mq_unlink", .errmsg = true,
1158 .arg_scnprintf = { [0] = SCA_FILENAME, /* u_name */ }, },
ae685380
ACM
1159 { .name = "mremap", .hexret = true,
1160 .arg_scnprintf = { [0] = SCA_HEX, /* addr */
86998dda 1161 [3] = SCA_MREMAP_FLAGS, /* flags */
ae685380 1162 [4] = SCA_HEX, /* new_addr */ }, },
3d903aa7
ACM
1163 { .name = "munlock", .errmsg = true,
1164 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
beccb2b5
ACM
1165 { .name = "munmap", .errmsg = true,
1166 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
75b757ca 1167 { .name = "name_to_handle_at", .errmsg = true,
48000a1a 1168 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
75b757ca 1169 { .name = "newfstatat", .errmsg = true,
34221118
ACM
1170 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
1171 [1] = SCA_FILENAME, /* filename */ }, },
be65a89a 1172 { .name = "open", .errmsg = true,
f994592d
ACM
1173 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */
1174 [1] = SCA_OPEN_FLAGS, /* flags */ }, },
31cd3855 1175 { .name = "open_by_handle_at", .errmsg = true,
75b757ca
ACM
1176 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
1177 [2] = SCA_OPEN_FLAGS, /* flags */ }, },
31cd3855 1178 { .name = "openat", .errmsg = true,
75b757ca 1179 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
34221118 1180 [1] = SCA_FILENAME, /* filename */
75b757ca 1181 [2] = SCA_OPEN_FLAGS, /* flags */ }, },
a1c2552d
ACM
1182 { .name = "perf_event_open", .errmsg = true,
1183 .arg_scnprintf = { [1] = SCA_INT, /* pid */
1184 [2] = SCA_INT, /* cpu */
1185 [3] = SCA_FD, /* group_fd */
1186 [4] = SCA_PERF_FLAGS, /* flags */ }, },
46cce19b
ACM
1187 { .name = "pipe2", .errmsg = true,
1188 .arg_scnprintf = { [1] = SCA_PIPE_FLAGS, /* flags */ }, },
aec1930b
ACM
1189 { .name = "poll", .errmsg = true, .timeout = true, },
1190 { .name = "ppoll", .errmsg = true, .timeout = true, },
75b757ca 1191 { .name = "pread", .errmsg = true, .alias = "pread64",
48000a1a 1192 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
75b757ca 1193 { .name = "preadv", .errmsg = true, .alias = "pread",
48000a1a 1194 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
453350dd 1195 { .name = "prlimit64", .errmsg = true, STRARRAY(1, resource, rlimit_resources), },
75b757ca 1196 { .name = "pwrite", .errmsg = true, .alias = "pwrite64",
48000a1a 1197 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
75b757ca 1198 { .name = "pwritev", .errmsg = true,
48000a1a 1199 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
75b757ca 1200 { .name = "read", .errmsg = true,
48000a1a 1201 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
34221118
ACM
1202 { .name = "readlink", .errmsg = true,
1203 .arg_scnprintf = { [0] = SCA_FILENAME, /* path */ }, },
75b757ca 1204 { .name = "readlinkat", .errmsg = true,
34221118
ACM
1205 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
1206 [1] = SCA_FILENAME, /* pathname */ }, },
75b757ca 1207 { .name = "readv", .errmsg = true,
48000a1a 1208 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
b2cc99fd 1209 { .name = "recvfrom", .errmsg = true,
8d8c66a2
ACM
1210 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1211 [3] = SCA_MSG_FLAGS, /* flags */ }, },
b2cc99fd 1212 { .name = "recvmmsg", .errmsg = true,
8d8c66a2
ACM
1213 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1214 [3] = SCA_MSG_FLAGS, /* flags */ }, },
b2cc99fd 1215 { .name = "recvmsg", .errmsg = true,
8d8c66a2
ACM
1216 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1217 [2] = SCA_MSG_FLAGS, /* flags */ }, },
34221118
ACM
1218 { .name = "removexattr", .errmsg = true,
1219 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
75b757ca 1220 { .name = "renameat", .errmsg = true,
48000a1a 1221 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
34221118
ACM
1222 { .name = "rmdir", .errmsg = true,
1223 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
8bad5b0a
ACM
1224 { .name = "rt_sigaction", .errmsg = true,
1225 .arg_scnprintf = { [0] = SCA_SIGNUM, /* sig */ }, },
453350dd 1226 { .name = "rt_sigprocmask", .errmsg = true, STRARRAY(0, how, sighow), },
8bad5b0a
ACM
1227 { .name = "rt_sigqueueinfo", .errmsg = true,
1228 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
1229 { .name = "rt_tgsigqueueinfo", .errmsg = true,
1230 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
a3bca91f
ACM
1231 { .name = "sched_setscheduler", .errmsg = true,
1232 .arg_scnprintf = { [1] = SCA_SCHED_POLICY, /* policy */ }, },
997bba8c
ACM
1233 { .name = "seccomp", .errmsg = true,
1234 .arg_scnprintf = { [0] = SCA_SECCOMP_OP, /* op */
1235 [1] = SCA_SECCOMP_FLAGS, /* flags */ }, },
aec1930b 1236 { .name = "select", .errmsg = true, .timeout = true, },
b2cc99fd 1237 { .name = "sendmmsg", .errmsg = true,
8d8c66a2
ACM
1238 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1239 [3] = SCA_MSG_FLAGS, /* flags */ }, },
b2cc99fd 1240 { .name = "sendmsg", .errmsg = true,
8d8c66a2
ACM
1241 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1242 [2] = SCA_MSG_FLAGS, /* flags */ }, },
b2cc99fd 1243 { .name = "sendto", .errmsg = true,
8d8c66a2
ACM
1244 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1245 [3] = SCA_MSG_FLAGS, /* flags */ }, },
c65f1070 1246 { .name = "set_tid_address", .errpid = true, },
453350dd 1247 { .name = "setitimer", .errmsg = true, STRARRAY(0, which, itimers), },
d1d438a3 1248 { .name = "setpgid", .errmsg = true, },
453350dd 1249 { .name = "setrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
34221118
ACM
1250 { .name = "setxattr", .errmsg = true,
1251 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
75b757ca 1252 { .name = "shutdown", .errmsg = true,
48000a1a 1253 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
e10bce81 1254 { .name = "socket", .errmsg = true,
a28b24b2
ACM
1255 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
1256 [1] = SCA_SK_TYPE, /* type */ },
07120aa5
ACM
1257 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, },
1258 { .name = "socketpair", .errmsg = true,
1259 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
1260 [1] = SCA_SK_TYPE, /* type */ },
e10bce81 1261 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, },
090389b6
ACM
1262 { .name = "stat", .errmsg = true, .alias = "newstat",
1263 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
34221118
ACM
1264 { .name = "statfs", .errmsg = true,
1265 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
1266 { .name = "swapoff", .errmsg = true,
1267 .arg_scnprintf = { [0] = SCA_FILENAME, /* specialfile */ }, },
1268 { .name = "swapon", .errmsg = true,
1269 .arg_scnprintf = { [0] = SCA_FILENAME, /* specialfile */ }, },
75b757ca 1270 { .name = "symlinkat", .errmsg = true,
48000a1a 1271 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
8bad5b0a
ACM
1272 { .name = "tgkill", .errmsg = true,
1273 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
1274 { .name = "tkill", .errmsg = true,
1275 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
34221118
ACM
1276 { .name = "truncate", .errmsg = true,
1277 .arg_scnprintf = { [0] = SCA_FILENAME, /* path */ }, },
e5959683 1278 { .name = "uname", .errmsg = true, .alias = "newuname", },
75b757ca 1279 { .name = "unlinkat", .errmsg = true,
34221118
ACM
1280 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
1281 [1] = SCA_FILENAME, /* pathname */ }, },
1282 { .name = "utime", .errmsg = true,
1283 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
75b757ca 1284 { .name = "utimensat", .errmsg = true,
34221118
ACM
1285 .arg_scnprintf = { [0] = SCA_FDAT, /* dirfd */
1286 [1] = SCA_FILENAME, /* filename */ }, },
1287 { .name = "utimes", .errmsg = true,
1288 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
090389b6
ACM
1289 { .name = "vmsplice", .errmsg = true,
1290 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
11c8e39f 1291 { .name = "wait4", .errpid = true,
7206b900 1292 .arg_scnprintf = { [2] = SCA_WAITID_OPTIONS, /* options */ }, },
11c8e39f 1293 { .name = "waitid", .errpid = true,
7206b900 1294 .arg_scnprintf = { [3] = SCA_WAITID_OPTIONS, /* options */ }, },
75b757ca 1295 { .name = "write", .errmsg = true,
48000a1a 1296 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
75b757ca 1297 { .name = "writev", .errmsg = true,
48000a1a 1298 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
514f1c67
ACM
1299};
1300
1301static int syscall_fmt__cmp(const void *name, const void *fmtp)
1302{
1303 const struct syscall_fmt *fmt = fmtp;
1304 return strcmp(name, fmt->name);
1305}
1306
1307static struct syscall_fmt *syscall_fmt__find(const char *name)
1308{
1309 const int nmemb = ARRAY_SIZE(syscall_fmts);
1310 return bsearch(name, syscall_fmts, nmemb, sizeof(struct syscall_fmt), syscall_fmt__cmp);
1311}
1312
1313struct syscall {
1314 struct event_format *tp_format;
f208bd8d
ACM
1315 int nr_args;
1316 struct format_field *args;
514f1c67 1317 const char *name;
5089f20e 1318 bool is_exit;
514f1c67 1319 struct syscall_fmt *fmt;
01533e97 1320 size_t (**arg_scnprintf)(char *bf, size_t size, struct syscall_arg *arg);
1f115cb7 1321 void **arg_parm;
514f1c67
ACM
1322};
1323
60c907ab
ACM
1324static size_t fprintf_duration(unsigned long t, FILE *fp)
1325{
1326 double duration = (double)t / NSEC_PER_MSEC;
1327 size_t printed = fprintf(fp, "(");
1328
1329 if (duration >= 1.0)
1330 printed += color_fprintf(fp, PERF_COLOR_RED, "%6.3f ms", duration);
1331 else if (duration >= 0.01)
1332 printed += color_fprintf(fp, PERF_COLOR_YELLOW, "%6.3f ms", duration);
1333 else
1334 printed += color_fprintf(fp, PERF_COLOR_NORMAL, "%6.3f ms", duration);
c24ff998 1335 return printed + fprintf(fp, "): ");
60c907ab
ACM
1336}
1337
f994592d
ACM
1338/**
1339 * filename.ptr: The filename char pointer that will be vfs_getname'd
1340 * filename.entry_str_pos: Where to insert the string translated from
1341 * filename.ptr by the vfs_getname tracepoint/kprobe.
1342 */
752fde44
ACM
1343struct thread_trace {
1344 u64 entry_time;
1345 u64 exit_time;
1346 bool entry_pending;
efd5745e 1347 unsigned long nr_events;
a2ea67d7 1348 unsigned long pfmaj, pfmin;
752fde44 1349 char *entry_str;
1302d88e 1350 double runtime_ms;
f994592d
ACM
1351 struct {
1352 unsigned long ptr;
7f4f8001
ACM
1353 short int entry_str_pos;
1354 bool pending_open;
1355 unsigned int namelen;
1356 char *name;
f994592d 1357 } filename;
75b757ca
ACM
1358 struct {
1359 int max;
1360 char **table;
1361 } paths;
bf2575c1
DA
1362
1363 struct intlist *syscall_stats;
752fde44
ACM
1364};
1365
1366static struct thread_trace *thread_trace__new(void)
1367{
75b757ca
ACM
1368 struct thread_trace *ttrace = zalloc(sizeof(struct thread_trace));
1369
1370 if (ttrace)
1371 ttrace->paths.max = -1;
1372
bf2575c1
DA
1373 ttrace->syscall_stats = intlist__new(NULL);
1374
75b757ca 1375 return ttrace;
752fde44
ACM
1376}
1377
c24ff998 1378static struct thread_trace *thread__trace(struct thread *thread, FILE *fp)
752fde44 1379{
efd5745e
ACM
1380 struct thread_trace *ttrace;
1381
752fde44
ACM
1382 if (thread == NULL)
1383 goto fail;
1384
89dceb22
NK
1385 if (thread__priv(thread) == NULL)
1386 thread__set_priv(thread, thread_trace__new());
48000a1a 1387
89dceb22 1388 if (thread__priv(thread) == NULL)
752fde44
ACM
1389 goto fail;
1390
89dceb22 1391 ttrace = thread__priv(thread);
efd5745e
ACM
1392 ++ttrace->nr_events;
1393
1394 return ttrace;
752fde44 1395fail:
c24ff998 1396 color_fprintf(fp, PERF_COLOR_RED,
752fde44
ACM
1397 "WARNING: not enough memory, dropping samples!\n");
1398 return NULL;
1399}
1400
598d02c5
SF
1401#define TRACE_PFMAJ (1 << 0)
1402#define TRACE_PFMIN (1 << 1)
1403
e4d44e83
ACM
1404static const size_t trace__entry_str_size = 2048;
1405
97119f37 1406static int trace__set_fd_pathname(struct thread *thread, int fd, const char *pathname)
75b757ca 1407{
89dceb22 1408 struct thread_trace *ttrace = thread__priv(thread);
75b757ca
ACM
1409
1410 if (fd > ttrace->paths.max) {
1411 char **npath = realloc(ttrace->paths.table, (fd + 1) * sizeof(char *));
1412
1413 if (npath == NULL)
1414 return -1;
1415
1416 if (ttrace->paths.max != -1) {
1417 memset(npath + ttrace->paths.max + 1, 0,
1418 (fd - ttrace->paths.max) * sizeof(char *));
1419 } else {
1420 memset(npath, 0, (fd + 1) * sizeof(char *));
1421 }
1422
1423 ttrace->paths.table = npath;
1424 ttrace->paths.max = fd;
1425 }
1426
1427 ttrace->paths.table[fd] = strdup(pathname);
1428
1429 return ttrace->paths.table[fd] != NULL ? 0 : -1;
1430}
1431
97119f37
ACM
1432static int thread__read_fd_path(struct thread *thread, int fd)
1433{
1434 char linkname[PATH_MAX], pathname[PATH_MAX];
1435 struct stat st;
1436 int ret;
1437
1438 if (thread->pid_ == thread->tid) {
1439 scnprintf(linkname, sizeof(linkname),
1440 "/proc/%d/fd/%d", thread->pid_, fd);
1441 } else {
1442 scnprintf(linkname, sizeof(linkname),
1443 "/proc/%d/task/%d/fd/%d", thread->pid_, thread->tid, fd);
1444 }
1445
1446 if (lstat(linkname, &st) < 0 || st.st_size + 1 > (off_t)sizeof(pathname))
1447 return -1;
1448
1449 ret = readlink(linkname, pathname, sizeof(pathname));
1450
1451 if (ret < 0 || ret > st.st_size)
1452 return -1;
1453
1454 pathname[ret] = '\0';
1455 return trace__set_fd_pathname(thread, fd, pathname);
1456}
1457
c522739d
ACM
1458static const char *thread__fd_path(struct thread *thread, int fd,
1459 struct trace *trace)
75b757ca 1460{
89dceb22 1461 struct thread_trace *ttrace = thread__priv(thread);
75b757ca
ACM
1462
1463 if (ttrace == NULL)
1464 return NULL;
1465
1466 if (fd < 0)
1467 return NULL;
1468
cdcd1e6b 1469 if ((fd > ttrace->paths.max || ttrace->paths.table[fd] == NULL)) {
c522739d
ACM
1470 if (!trace->live)
1471 return NULL;
1472 ++trace->stats.proc_getname;
cdcd1e6b 1473 if (thread__read_fd_path(thread, fd))
c522739d
ACM
1474 return NULL;
1475 }
75b757ca
ACM
1476
1477 return ttrace->paths.table[fd];
1478}
1479
1480static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
1481 struct syscall_arg *arg)
1482{
1483 int fd = arg->val;
1484 size_t printed = scnprintf(bf, size, "%d", fd);
c522739d 1485 const char *path = thread__fd_path(arg->thread, fd, arg->trace);
75b757ca
ACM
1486
1487 if (path)
1488 printed += scnprintf(bf + printed, size - printed, "<%s>", path);
1489
1490 return printed;
1491}
1492
1493static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
1494 struct syscall_arg *arg)
1495{
1496 int fd = arg->val;
1497 size_t printed = syscall_arg__scnprintf_fd(bf, size, arg);
89dceb22 1498 struct thread_trace *ttrace = thread__priv(arg->thread);
75b757ca 1499
04662523
ACM
1500 if (ttrace && fd >= 0 && fd <= ttrace->paths.max)
1501 zfree(&ttrace->paths.table[fd]);
75b757ca
ACM
1502
1503 return printed;
1504}
1505
f994592d
ACM
1506static void thread__set_filename_pos(struct thread *thread, const char *bf,
1507 unsigned long ptr)
1508{
1509 struct thread_trace *ttrace = thread__priv(thread);
1510
1511 ttrace->filename.ptr = ptr;
1512 ttrace->filename.entry_str_pos = bf - ttrace->entry_str;
1513}
1514
1515static size_t syscall_arg__scnprintf_filename(char *bf, size_t size,
1516 struct syscall_arg *arg)
1517{
1518 unsigned long ptr = arg->val;
1519
1520 if (!arg->trace->vfs_getname)
1521 return scnprintf(bf, size, "%#x", ptr);
1522
1523 thread__set_filename_pos(arg->thread, bf, ptr);
1524 return 0;
1525}
1526
ae9ed035
ACM
1527static bool trace__filter_duration(struct trace *trace, double t)
1528{
1529 return t < (trace->duration_filter * NSEC_PER_MSEC);
1530}
1531
752fde44
ACM
1532static size_t trace__fprintf_tstamp(struct trace *trace, u64 tstamp, FILE *fp)
1533{
1534 double ts = (double)(tstamp - trace->base_time) / NSEC_PER_MSEC;
1535
60c907ab 1536 return fprintf(fp, "%10.3f ", ts);
752fde44
ACM
1537}
1538
f15eb531 1539static bool done = false;
ba209f85 1540static bool interrupted = false;
f15eb531 1541
ba209f85 1542static void sig_handler(int sig)
f15eb531
NK
1543{
1544 done = true;
ba209f85 1545 interrupted = sig == SIGINT;
f15eb531
NK
1546}
1547
752fde44 1548static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thread,
60c907ab 1549 u64 duration, u64 tstamp, FILE *fp)
752fde44
ACM
1550{
1551 size_t printed = trace__fprintf_tstamp(trace, tstamp, fp);
60c907ab 1552 printed += fprintf_duration(duration, fp);
752fde44 1553
50c95cbd
ACM
1554 if (trace->multiple_threads) {
1555 if (trace->show_comm)
1902efe7 1556 printed += fprintf(fp, "%.14s/", thread__comm_str(thread));
38051234 1557 printed += fprintf(fp, "%d ", thread->tid);
50c95cbd 1558 }
752fde44
ACM
1559
1560 return printed;
1561}
1562
c24ff998 1563static int trace__process_event(struct trace *trace, struct machine *machine,
162f0bef 1564 union perf_event *event, struct perf_sample *sample)
752fde44
ACM
1565{
1566 int ret = 0;
1567
1568 switch (event->header.type) {
1569 case PERF_RECORD_LOST:
c24ff998 1570 color_fprintf(trace->output, PERF_COLOR_RED,
752fde44 1571 "LOST %" PRIu64 " events!\n", event->lost.lost);
162f0bef 1572 ret = machine__process_lost_event(machine, event, sample);
3ed5ca2e 1573 break;
752fde44 1574 default:
162f0bef 1575 ret = machine__process_event(machine, event, sample);
752fde44
ACM
1576 break;
1577 }
1578
1579 return ret;
1580}
1581
c24ff998 1582static int trace__tool_process(struct perf_tool *tool,
752fde44 1583 union perf_event *event,
162f0bef 1584 struct perf_sample *sample,
752fde44
ACM
1585 struct machine *machine)
1586{
c24ff998 1587 struct trace *trace = container_of(tool, struct trace, tool);
162f0bef 1588 return trace__process_event(trace, machine, event, sample);
752fde44
ACM
1589}
1590
1591static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
1592{
0a7e6d1b 1593 int err = symbol__init(NULL);
752fde44
ACM
1594
1595 if (err)
1596 return err;
1597
8fb598e5
DA
1598 trace->host = machine__new_host();
1599 if (trace->host == NULL)
1600 return -ENOMEM;
752fde44 1601
959c2199 1602 if (trace_event__register_resolver(trace->host, machine__resolve_kernel_addr) < 0)
706c3da4
ACM
1603 return -errno;
1604
a33fbd56 1605 err = __machine__synthesize_threads(trace->host, &trace->tool, &trace->opts.target,
9d9cad76
KL
1606 evlist->threads, trace__tool_process, false,
1607 trace->opts.proc_map_timeout);
752fde44
ACM
1608 if (err)
1609 symbol__exit();
1610
1611 return err;
1612}
1613
13d4ff3e
ACM
1614static int syscall__set_arg_fmts(struct syscall *sc)
1615{
1616 struct format_field *field;
1617 int idx = 0;
1618
f208bd8d 1619 sc->arg_scnprintf = calloc(sc->nr_args, sizeof(void *));
13d4ff3e
ACM
1620 if (sc->arg_scnprintf == NULL)
1621 return -1;
1622
1f115cb7
ACM
1623 if (sc->fmt)
1624 sc->arg_parm = sc->fmt->arg_parm;
1625
f208bd8d 1626 for (field = sc->args; field; field = field->next) {
beccb2b5
ACM
1627 if (sc->fmt && sc->fmt->arg_scnprintf[idx])
1628 sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx];
1629 else if (field->flags & FIELD_IS_POINTER)
13d4ff3e 1630 sc->arg_scnprintf[idx] = syscall_arg__scnprintf_hex;
d1d438a3
ACM
1631 else if (strcmp(field->type, "pid_t") == 0)
1632 sc->arg_scnprintf[idx] = SCA_PID;
ba2f22cf
ACM
1633 else if (strcmp(field->type, "umode_t") == 0)
1634 sc->arg_scnprintf[idx] = SCA_MODE_T;
13d4ff3e
ACM
1635 ++idx;
1636 }
1637
1638 return 0;
1639}
1640
514f1c67
ACM
1641static int trace__read_syscall_info(struct trace *trace, int id)
1642{
1643 char tp_name[128];
1644 struct syscall *sc;
fd0db102 1645 const char *name = syscalltbl__name(trace->sctbl, id);
3a531260
ACM
1646
1647 if (name == NULL)
1648 return -1;
514f1c67
ACM
1649
1650 if (id > trace->syscalls.max) {
1651 struct syscall *nsyscalls = realloc(trace->syscalls.table, (id + 1) * sizeof(*sc));
1652
1653 if (nsyscalls == NULL)
1654 return -1;
1655
1656 if (trace->syscalls.max != -1) {
1657 memset(nsyscalls + trace->syscalls.max + 1, 0,
1658 (id - trace->syscalls.max) * sizeof(*sc));
1659 } else {
1660 memset(nsyscalls, 0, (id + 1) * sizeof(*sc));
1661 }
1662
1663 trace->syscalls.table = nsyscalls;
1664 trace->syscalls.max = id;
1665 }
1666
1667 sc = trace->syscalls.table + id;
3a531260 1668 sc->name = name;
2ae3a312 1669
3a531260 1670 sc->fmt = syscall_fmt__find(sc->name);
514f1c67 1671
aec1930b 1672 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name);
97978b3e 1673 sc->tp_format = trace_event__tp_format("syscalls", tp_name);
aec1930b 1674
8dd2a131 1675 if (IS_ERR(sc->tp_format) && sc->fmt && sc->fmt->alias) {
aec1930b 1676 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->fmt->alias);
97978b3e 1677 sc->tp_format = trace_event__tp_format("syscalls", tp_name);
aec1930b 1678 }
514f1c67 1679
8dd2a131 1680 if (IS_ERR(sc->tp_format))
13d4ff3e
ACM
1681 return -1;
1682
f208bd8d
ACM
1683 sc->args = sc->tp_format->format.fields;
1684 sc->nr_args = sc->tp_format->format.nr_fields;
c42de706
TS
1685 /*
1686 * We need to check and discard the first variable '__syscall_nr'
1687 * or 'nr' that mean the syscall number. It is needless here.
1688 * So drop '__syscall_nr' or 'nr' field but does not exist on older kernels.
1689 */
1690 if (sc->args && (!strcmp(sc->args->name, "__syscall_nr") || !strcmp(sc->args->name, "nr"))) {
f208bd8d
ACM
1691 sc->args = sc->args->next;
1692 --sc->nr_args;
1693 }
1694
5089f20e
ACM
1695 sc->is_exit = !strcmp(name, "exit_group") || !strcmp(name, "exit");
1696
13d4ff3e 1697 return syscall__set_arg_fmts(sc);
514f1c67
ACM
1698}
1699
d0cc439b
ACM
1700static int trace__validate_ev_qualifier(struct trace *trace)
1701{
8b3ce757 1702 int err = 0, i;
d0cc439b
ACM
1703 struct str_node *pos;
1704
8b3ce757
ACM
1705 trace->ev_qualifier_ids.nr = strlist__nr_entries(trace->ev_qualifier);
1706 trace->ev_qualifier_ids.entries = malloc(trace->ev_qualifier_ids.nr *
1707 sizeof(trace->ev_qualifier_ids.entries[0]));
1708
1709 if (trace->ev_qualifier_ids.entries == NULL) {
1710 fputs("Error:\tNot enough memory for allocating events qualifier ids\n",
1711 trace->output);
1712 err = -EINVAL;
1713 goto out;
1714 }
1715
1716 i = 0;
1717
d0cc439b
ACM
1718 strlist__for_each(pos, trace->ev_qualifier) {
1719 const char *sc = pos->s;
fd0db102 1720 int id = syscalltbl__id(trace->sctbl, sc);
d0cc439b 1721
8b3ce757 1722 if (id < 0) {
d0cc439b
ACM
1723 if (err == 0) {
1724 fputs("Error:\tInvalid syscall ", trace->output);
1725 err = -EINVAL;
1726 } else {
1727 fputs(", ", trace->output);
1728 }
1729
1730 fputs(sc, trace->output);
1731 }
8b3ce757
ACM
1732
1733 trace->ev_qualifier_ids.entries[i++] = id;
d0cc439b
ACM
1734 }
1735
1736 if (err < 0) {
1737 fputs("\nHint:\ttry 'perf list syscalls:sys_enter_*'"
1738 "\nHint:\tand: 'man syscalls'\n", trace->output);
8b3ce757
ACM
1739 zfree(&trace->ev_qualifier_ids.entries);
1740 trace->ev_qualifier_ids.nr = 0;
d0cc439b 1741 }
8b3ce757 1742out:
d0cc439b
ACM
1743 return err;
1744}
1745
55d43bca
DA
1746/*
1747 * args is to be interpreted as a series of longs but we need to handle
1748 * 8-byte unaligned accesses. args points to raw_data within the event
1749 * and raw_data is guaranteed to be 8-byte unaligned because it is
1750 * preceded by raw_size which is a u32. So we need to copy args to a temp
1751 * variable to read it. Most notably this avoids extended load instructions
1752 * on unaligned addresses
1753 */
1754
752fde44 1755static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
55d43bca 1756 unsigned char *args, struct trace *trace,
75b757ca 1757 struct thread *thread)
514f1c67 1758{
514f1c67 1759 size_t printed = 0;
55d43bca
DA
1760 unsigned char *p;
1761 unsigned long val;
514f1c67 1762
f208bd8d 1763 if (sc->args != NULL) {
514f1c67 1764 struct format_field *field;
01533e97
ACM
1765 u8 bit = 1;
1766 struct syscall_arg arg = {
75b757ca
ACM
1767 .idx = 0,
1768 .mask = 0,
1769 .trace = trace,
1770 .thread = thread,
01533e97 1771 };
6e7eeb51 1772
f208bd8d 1773 for (field = sc->args; field;
01533e97
ACM
1774 field = field->next, ++arg.idx, bit <<= 1) {
1775 if (arg.mask & bit)
6e7eeb51 1776 continue;
55d43bca
DA
1777
1778 /* special care for unaligned accesses */
1779 p = args + sizeof(unsigned long) * arg.idx;
1780 memcpy(&val, p, sizeof(val));
1781
4aa58232
ACM
1782 /*
1783 * Suppress this argument if its value is zero and
1784 * and we don't have a string associated in an
1785 * strarray for it.
1786 */
55d43bca 1787 if (val == 0 &&
4aa58232
ACM
1788 !(sc->arg_scnprintf &&
1789 sc->arg_scnprintf[arg.idx] == SCA_STRARRAY &&
1790 sc->arg_parm[arg.idx]))
22ae5cf1
ACM
1791 continue;
1792
752fde44 1793 printed += scnprintf(bf + printed, size - printed,
13d4ff3e 1794 "%s%s: ", printed ? ", " : "", field->name);
01533e97 1795 if (sc->arg_scnprintf && sc->arg_scnprintf[arg.idx]) {
55d43bca 1796 arg.val = val;
1f115cb7
ACM
1797 if (sc->arg_parm)
1798 arg.parm = sc->arg_parm[arg.idx];
01533e97
ACM
1799 printed += sc->arg_scnprintf[arg.idx](bf + printed,
1800 size - printed, &arg);
6e7eeb51 1801 } else {
13d4ff3e 1802 printed += scnprintf(bf + printed, size - printed,
55d43bca 1803 "%ld", val);
6e7eeb51 1804 }
514f1c67
ACM
1805 }
1806 } else {
01533e97
ACM
1807 int i = 0;
1808
514f1c67 1809 while (i < 6) {
55d43bca
DA
1810 /* special care for unaligned accesses */
1811 p = args + sizeof(unsigned long) * i;
1812 memcpy(&val, p, sizeof(val));
752fde44
ACM
1813 printed += scnprintf(bf + printed, size - printed,
1814 "%sarg%d: %ld",
55d43bca 1815 printed ? ", " : "", i, val);
514f1c67
ACM
1816 ++i;
1817 }
1818 }
1819
1820 return printed;
1821}
1822
ba3d7dee 1823typedef int (*tracepoint_handler)(struct trace *trace, struct perf_evsel *evsel,
0c82adcf 1824 union perf_event *event,
ba3d7dee
ACM
1825 struct perf_sample *sample);
1826
1827static struct syscall *trace__syscall_info(struct trace *trace,
bf2575c1 1828 struct perf_evsel *evsel, int id)
ba3d7dee 1829{
ba3d7dee
ACM
1830
1831 if (id < 0) {
adaa18bf
ACM
1832
1833 /*
1834 * XXX: Noticed on x86_64, reproduced as far back as 3.0.36, haven't tried
1835 * before that, leaving at a higher verbosity level till that is
1836 * explained. Reproduced with plain ftrace with:
1837 *
1838 * echo 1 > /t/events/raw_syscalls/sys_exit/enable
1839 * grep "NR -1 " /t/trace_pipe
1840 *
1841 * After generating some load on the machine.
1842 */
1843 if (verbose > 1) {
1844 static u64 n;
1845 fprintf(trace->output, "Invalid syscall %d id, skipping (%s, %" PRIu64 ") ...\n",
1846 id, perf_evsel__name(evsel), ++n);
1847 }
ba3d7dee
ACM
1848 return NULL;
1849 }
1850
1851 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL) &&
1852 trace__read_syscall_info(trace, id))
1853 goto out_cant_read;
1854
1855 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL))
1856 goto out_cant_read;
1857
1858 return &trace->syscalls.table[id];
1859
1860out_cant_read:
7c304ee0
ACM
1861 if (verbose) {
1862 fprintf(trace->output, "Problems reading syscall %d", id);
1863 if (id <= trace->syscalls.max && trace->syscalls.table[id].name != NULL)
1864 fprintf(trace->output, "(%s)", trace->syscalls.table[id].name);
1865 fputs(" information\n", trace->output);
1866 }
ba3d7dee
ACM
1867 return NULL;
1868}
1869
bf2575c1
DA
1870static void thread__update_stats(struct thread_trace *ttrace,
1871 int id, struct perf_sample *sample)
1872{
1873 struct int_node *inode;
1874 struct stats *stats;
1875 u64 duration = 0;
1876
1877 inode = intlist__findnew(ttrace->syscall_stats, id);
1878 if (inode == NULL)
1879 return;
1880
1881 stats = inode->priv;
1882 if (stats == NULL) {
1883 stats = malloc(sizeof(struct stats));
1884 if (stats == NULL)
1885 return;
1886 init_stats(stats);
1887 inode->priv = stats;
1888 }
1889
1890 if (ttrace->entry_time && sample->time > ttrace->entry_time)
1891 duration = sample->time - ttrace->entry_time;
1892
1893 update_stats(stats, duration);
1894}
1895
e596663e
ACM
1896static int trace__printf_interrupted_entry(struct trace *trace, struct perf_sample *sample)
1897{
1898 struct thread_trace *ttrace;
1899 u64 duration;
1900 size_t printed;
1901
1902 if (trace->current == NULL)
1903 return 0;
1904
1905 ttrace = thread__priv(trace->current);
1906
1907 if (!ttrace->entry_pending)
1908 return 0;
1909
1910 duration = sample->time - ttrace->entry_time;
1911
1912 printed = trace__fprintf_entry_head(trace, trace->current, duration, sample->time, trace->output);
1913 printed += fprintf(trace->output, "%-70s) ...\n", ttrace->entry_str);
1914 ttrace->entry_pending = false;
1915
1916 return printed;
1917}
1918
ba3d7dee 1919static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
0c82adcf 1920 union perf_event *event __maybe_unused,
ba3d7dee
ACM
1921 struct perf_sample *sample)
1922{
752fde44 1923 char *msg;
ba3d7dee 1924 void *args;
752fde44 1925 size_t printed = 0;
2ae3a312 1926 struct thread *thread;
b91fc39f 1927 int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
bf2575c1 1928 struct syscall *sc = trace__syscall_info(trace, evsel, id);
2ae3a312
ACM
1929 struct thread_trace *ttrace;
1930
1931 if (sc == NULL)
1932 return -1;
ba3d7dee 1933
8fb598e5 1934 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
c24ff998 1935 ttrace = thread__trace(thread, trace->output);
2ae3a312 1936 if (ttrace == NULL)
b91fc39f 1937 goto out_put;
ba3d7dee 1938
77170988 1939 args = perf_evsel__sc_tp_ptr(evsel, args, sample);
752fde44
ACM
1940
1941 if (ttrace->entry_str == NULL) {
e4d44e83 1942 ttrace->entry_str = malloc(trace__entry_str_size);
752fde44 1943 if (!ttrace->entry_str)
b91fc39f 1944 goto out_put;
752fde44
ACM
1945 }
1946
13f22a2d 1947 if (!trace->summary_only)
6ebad5c1 1948 trace__printf_interrupted_entry(trace, sample);
e596663e 1949
752fde44
ACM
1950 ttrace->entry_time = sample->time;
1951 msg = ttrace->entry_str;
e4d44e83 1952 printed += scnprintf(msg + printed, trace__entry_str_size - printed, "%s(", sc->name);
752fde44 1953
e4d44e83 1954 printed += syscall__scnprintf_args(sc, msg + printed, trace__entry_str_size - printed,
75b757ca 1955 args, trace, thread);
752fde44 1956
5089f20e 1957 if (sc->is_exit) {
fd2eabaf 1958 if (!trace->duration_filter && !trace->summary_only) {
c24ff998
ACM
1959 trace__fprintf_entry_head(trace, thread, 1, sample->time, trace->output);
1960 fprintf(trace->output, "%-70s\n", ttrace->entry_str);
ae9ed035 1961 }
7f4f8001 1962 } else {
752fde44 1963 ttrace->entry_pending = true;
7f4f8001
ACM
1964 /* See trace__vfs_getname & trace__sys_exit */
1965 ttrace->filename.pending_open = false;
1966 }
ba3d7dee 1967
f3b623b8
ACM
1968 if (trace->current != thread) {
1969 thread__put(trace->current);
1970 trace->current = thread__get(thread);
1971 }
b91fc39f
ACM
1972 err = 0;
1973out_put:
1974 thread__put(thread);
1975 return err;
ba3d7dee
ACM
1976}
1977
202ff968
ACM
1978static int trace__fprintf_callchain(struct trace *trace, struct perf_evsel *evsel,
1979 struct perf_sample *sample)
1980{
1981 struct addr_location al;
1982 /* TODO: user-configurable print_opts */
e20ab86e
ACM
1983 const unsigned int print_opts = EVSEL__PRINT_SYM |
1984 EVSEL__PRINT_DSO |
1985 EVSEL__PRINT_UNKNOWN_AS_ADDR;
202ff968
ACM
1986
1987 if (sample->callchain == NULL)
1988 return 0;
1989
1990 if (machine__resolve(trace->host, &al, sample) < 0) {
1991 pr_err("Problem processing %s callchain, skipping...\n",
1992 perf_evsel__name(evsel));
1993 return 0;
1994 }
1995
1996 return perf_evsel__fprintf_callchain(evsel, sample, &al, 38, print_opts,
1997 scripting_max_stack, trace->output);
1998}
1999
ba3d7dee 2000static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
0c82adcf 2001 union perf_event *event __maybe_unused,
ba3d7dee
ACM
2002 struct perf_sample *sample)
2003{
2c82c3ad 2004 long ret;
60c907ab 2005 u64 duration = 0;
2ae3a312 2006 struct thread *thread;
b91fc39f 2007 int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
bf2575c1 2008 struct syscall *sc = trace__syscall_info(trace, evsel, id);
2ae3a312
ACM
2009 struct thread_trace *ttrace;
2010
2011 if (sc == NULL)
2012 return -1;
ba3d7dee 2013
8fb598e5 2014 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
c24ff998 2015 ttrace = thread__trace(thread, trace->output);
2ae3a312 2016 if (ttrace == NULL)
b91fc39f 2017 goto out_put;
ba3d7dee 2018
bf2575c1
DA
2019 if (trace->summary)
2020 thread__update_stats(ttrace, id, sample);
2021
77170988 2022 ret = perf_evsel__sc_tp_uint(evsel, ret, sample);
ba3d7dee 2023
fd0db102 2024 if (id == trace->open_id && ret >= 0 && ttrace->filename.pending_open) {
7f4f8001
ACM
2025 trace__set_fd_pathname(thread, ret, ttrace->filename.name);
2026 ttrace->filename.pending_open = false;
c522739d
ACM
2027 ++trace->stats.vfs_getname;
2028 }
2029
752fde44
ACM
2030 ttrace->exit_time = sample->time;
2031
ae9ed035 2032 if (ttrace->entry_time) {
60c907ab 2033 duration = sample->time - ttrace->entry_time;
ae9ed035
ACM
2034 if (trace__filter_duration(trace, duration))
2035 goto out;
2036 } else if (trace->duration_filter)
2037 goto out;
60c907ab 2038
fd2eabaf
DA
2039 if (trace->summary_only)
2040 goto out;
2041
c24ff998 2042 trace__fprintf_entry_head(trace, thread, duration, sample->time, trace->output);
752fde44
ACM
2043
2044 if (ttrace->entry_pending) {
c24ff998 2045 fprintf(trace->output, "%-70s", ttrace->entry_str);
752fde44 2046 } else {
c24ff998
ACM
2047 fprintf(trace->output, " ... [");
2048 color_fprintf(trace->output, PERF_COLOR_YELLOW, "continued");
2049 fprintf(trace->output, "]: %s()", sc->name);
752fde44
ACM
2050 }
2051
da3c9a44
ACM
2052 if (sc->fmt == NULL) {
2053signed_print:
2c82c3ad 2054 fprintf(trace->output, ") = %ld", ret);
11c8e39f 2055 } else if (ret < 0 && (sc->fmt->errmsg || sc->fmt->errpid)) {
942a91ed 2056 char bf[STRERR_BUFSIZE];
ba3d7dee
ACM
2057 const char *emsg = strerror_r(-ret, bf, sizeof(bf)),
2058 *e = audit_errno_to_name(-ret);
2059
c24ff998 2060 fprintf(trace->output, ") = -1 %s %s", e, emsg);
da3c9a44 2061 } else if (ret == 0 && sc->fmt->timeout)
c24ff998 2062 fprintf(trace->output, ") = 0 Timeout");
04b34729 2063 else if (sc->fmt->hexret)
2c82c3ad 2064 fprintf(trace->output, ") = %#lx", ret);
11c8e39f
ACM
2065 else if (sc->fmt->errpid) {
2066 struct thread *child = machine__find_thread(trace->host, ret, ret);
2067
2068 if (child != NULL) {
2069 fprintf(trace->output, ") = %ld", ret);
2070 if (child->comm_set)
2071 fprintf(trace->output, " (%s)", thread__comm_str(child));
2072 thread__put(child);
2073 }
2074 } else
da3c9a44 2075 goto signed_print;
ba3d7dee 2076
c24ff998 2077 fputc('\n', trace->output);
566a0885 2078
202ff968 2079 trace__fprintf_callchain(trace, evsel, sample);
ae9ed035 2080out:
752fde44 2081 ttrace->entry_pending = false;
b91fc39f
ACM
2082 err = 0;
2083out_put:
2084 thread__put(thread);
2085 return err;
ba3d7dee
ACM
2086}
2087
c522739d 2088static int trace__vfs_getname(struct trace *trace, struct perf_evsel *evsel,
0c82adcf 2089 union perf_event *event __maybe_unused,
c522739d
ACM
2090 struct perf_sample *sample)
2091{
f994592d
ACM
2092 struct thread *thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
2093 struct thread_trace *ttrace;
2094 size_t filename_len, entry_str_len, to_move;
2095 ssize_t remaining_space;
2096 char *pos;
7f4f8001 2097 const char *filename = perf_evsel__rawptr(evsel, sample, "pathname");
f994592d
ACM
2098
2099 if (!thread)
2100 goto out;
2101
2102 ttrace = thread__priv(thread);
2103 if (!ttrace)
2104 goto out;
2105
7f4f8001
ACM
2106 filename_len = strlen(filename);
2107
2108 if (ttrace->filename.namelen < filename_len) {
2109 char *f = realloc(ttrace->filename.name, filename_len + 1);
2110
2111 if (f == NULL)
2112 goto out;
2113
2114 ttrace->filename.namelen = filename_len;
2115 ttrace->filename.name = f;
2116 }
2117
2118 strcpy(ttrace->filename.name, filename);
2119 ttrace->filename.pending_open = true;
2120
f994592d
ACM
2121 if (!ttrace->filename.ptr)
2122 goto out;
2123
2124 entry_str_len = strlen(ttrace->entry_str);
2125 remaining_space = trace__entry_str_size - entry_str_len - 1; /* \0 */
2126 if (remaining_space <= 0)
2127 goto out;
2128
f994592d
ACM
2129 if (filename_len > (size_t)remaining_space) {
2130 filename += filename_len - remaining_space;
2131 filename_len = remaining_space;
2132 }
2133
2134 to_move = entry_str_len - ttrace->filename.entry_str_pos + 1; /* \0 */
2135 pos = ttrace->entry_str + ttrace->filename.entry_str_pos;
2136 memmove(pos + filename_len, pos, to_move);
2137 memcpy(pos, filename, filename_len);
2138
2139 ttrace->filename.ptr = 0;
2140 ttrace->filename.entry_str_pos = 0;
2141out:
c522739d
ACM
2142 return 0;
2143}
2144
1302d88e 2145static int trace__sched_stat_runtime(struct trace *trace, struct perf_evsel *evsel,
0c82adcf 2146 union perf_event *event __maybe_unused,
1302d88e
ACM
2147 struct perf_sample *sample)
2148{
2149 u64 runtime = perf_evsel__intval(evsel, sample, "runtime");
2150 double runtime_ms = (double)runtime / NSEC_PER_MSEC;
8fb598e5 2151 struct thread *thread = machine__findnew_thread(trace->host,
314add6b
AH
2152 sample->pid,
2153 sample->tid);
c24ff998 2154 struct thread_trace *ttrace = thread__trace(thread, trace->output);
1302d88e
ACM
2155
2156 if (ttrace == NULL)
2157 goto out_dump;
2158
2159 ttrace->runtime_ms += runtime_ms;
2160 trace->runtime_ms += runtime_ms;
b91fc39f 2161 thread__put(thread);
1302d88e
ACM
2162 return 0;
2163
2164out_dump:
c24ff998 2165 fprintf(trace->output, "%s: comm=%s,pid=%u,runtime=%" PRIu64 ",vruntime=%" PRIu64 ")\n",
1302d88e
ACM
2166 evsel->name,
2167 perf_evsel__strval(evsel, sample, "comm"),
2168 (pid_t)perf_evsel__intval(evsel, sample, "pid"),
2169 runtime,
2170 perf_evsel__intval(evsel, sample, "vruntime"));
b91fc39f 2171 thread__put(thread);
1302d88e
ACM
2172 return 0;
2173}
2174
1d6c9407
WN
2175static void bpf_output__printer(enum binary_printer_ops op,
2176 unsigned int val, void *extra)
2177{
2178 FILE *output = extra;
2179 unsigned char ch = (unsigned char)val;
2180
2181 switch (op) {
2182 case BINARY_PRINT_CHAR_DATA:
2183 fprintf(output, "%c", isprint(ch) ? ch : '.');
2184 break;
2185 case BINARY_PRINT_DATA_BEGIN:
2186 case BINARY_PRINT_LINE_BEGIN:
2187 case BINARY_PRINT_ADDR:
2188 case BINARY_PRINT_NUM_DATA:
2189 case BINARY_PRINT_NUM_PAD:
2190 case BINARY_PRINT_SEP:
2191 case BINARY_PRINT_CHAR_PAD:
2192 case BINARY_PRINT_LINE_END:
2193 case BINARY_PRINT_DATA_END:
2194 default:
2195 break;
2196 }
2197}
2198
2199static void bpf_output__fprintf(struct trace *trace,
2200 struct perf_sample *sample)
2201{
2202 print_binary(sample->raw_data, sample->raw_size, 8,
2203 bpf_output__printer, trace->output);
2204}
2205
14a052df
ACM
2206static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
2207 union perf_event *event __maybe_unused,
2208 struct perf_sample *sample)
2209{
2210 trace__printf_interrupted_entry(trace, sample);
2211 trace__fprintf_tstamp(trace, sample->time, trace->output);
0808921a
ACM
2212
2213 if (trace->trace_syscalls)
2214 fprintf(trace->output, "( ): ");
2215
2216 fprintf(trace->output, "%s:", evsel->name);
14a052df 2217
1d6c9407
WN
2218 if (perf_evsel__is_bpf_output(evsel)) {
2219 bpf_output__fprintf(trace, sample);
2220 } else if (evsel->tp_format) {
14a052df
ACM
2221 event_format__fprintf(evsel->tp_format, sample->cpu,
2222 sample->raw_data, sample->raw_size,
2223 trace->output);
2224 }
2225
2226 fprintf(trace->output, ")\n");
202ff968
ACM
2227
2228 trace__fprintf_callchain(trace, evsel, sample);
2229
14a052df
ACM
2230 return 0;
2231}
2232
598d02c5
SF
2233static void print_location(FILE *f, struct perf_sample *sample,
2234 struct addr_location *al,
2235 bool print_dso, bool print_sym)
2236{
2237
2238 if ((verbose || print_dso) && al->map)
2239 fprintf(f, "%s@", al->map->dso->long_name);
2240
2241 if ((verbose || print_sym) && al->sym)
4414a3c5 2242 fprintf(f, "%s+0x%" PRIx64, al->sym->name,
598d02c5
SF
2243 al->addr - al->sym->start);
2244 else if (al->map)
4414a3c5 2245 fprintf(f, "0x%" PRIx64, al->addr);
598d02c5 2246 else
4414a3c5 2247 fprintf(f, "0x%" PRIx64, sample->addr);
598d02c5
SF
2248}
2249
2250static int trace__pgfault(struct trace *trace,
2251 struct perf_evsel *evsel,
473398a2 2252 union perf_event *event __maybe_unused,
598d02c5
SF
2253 struct perf_sample *sample)
2254{
2255 struct thread *thread;
598d02c5
SF
2256 struct addr_location al;
2257 char map_type = 'd';
a2ea67d7 2258 struct thread_trace *ttrace;
b91fc39f 2259 int err = -1;
598d02c5
SF
2260
2261 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
a2ea67d7
SF
2262 ttrace = thread__trace(thread, trace->output);
2263 if (ttrace == NULL)
b91fc39f 2264 goto out_put;
a2ea67d7
SF
2265
2266 if (evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ)
2267 ttrace->pfmaj++;
2268 else
2269 ttrace->pfmin++;
2270
2271 if (trace->summary_only)
b91fc39f 2272 goto out;
598d02c5 2273
473398a2 2274 thread__find_addr_location(thread, sample->cpumode, MAP__FUNCTION,
598d02c5
SF
2275 sample->ip, &al);
2276
2277 trace__fprintf_entry_head(trace, thread, 0, sample->time, trace->output);
2278
2279 fprintf(trace->output, "%sfault [",
2280 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ?
2281 "maj" : "min");
2282
2283 print_location(trace->output, sample, &al, false, true);
2284
2285 fprintf(trace->output, "] => ");
2286
473398a2 2287 thread__find_addr_location(thread, sample->cpumode, MAP__VARIABLE,
598d02c5
SF
2288 sample->addr, &al);
2289
2290 if (!al.map) {
473398a2 2291 thread__find_addr_location(thread, sample->cpumode,
598d02c5
SF
2292 MAP__FUNCTION, sample->addr, &al);
2293
2294 if (al.map)
2295 map_type = 'x';
2296 else
2297 map_type = '?';
2298 }
2299
2300 print_location(trace->output, sample, &al, true, false);
2301
2302 fprintf(trace->output, " (%c%c)\n", map_type, al.level);
b91fc39f
ACM
2303out:
2304 err = 0;
2305out_put:
2306 thread__put(thread);
2307 return err;
598d02c5
SF
2308}
2309
bdc89661
DA
2310static bool skip_sample(struct trace *trace, struct perf_sample *sample)
2311{
2312 if ((trace->pid_list && intlist__find(trace->pid_list, sample->pid)) ||
2313 (trace->tid_list && intlist__find(trace->tid_list, sample->tid)))
2314 return false;
2315
2316 if (trace->pid_list || trace->tid_list)
2317 return true;
2318
2319 return false;
2320}
2321
e6001980 2322static void trace__set_base_time(struct trace *trace,
8a07a809 2323 struct perf_evsel *evsel,
e6001980
ACM
2324 struct perf_sample *sample)
2325{
8a07a809
ACM
2326 /*
2327 * BPF events were not setting PERF_SAMPLE_TIME, so be more robust
2328 * and don't use sample->time unconditionally, we may end up having
2329 * some other event in the future without PERF_SAMPLE_TIME for good
2330 * reason, i.e. we may not be interested in its timestamps, just in
2331 * it taking place, picking some piece of information when it
2332 * appears in our event stream (vfs_getname comes to mind).
2333 */
2334 if (trace->base_time == 0 && !trace->full_time &&
2335 (evsel->attr.sample_type & PERF_SAMPLE_TIME))
e6001980
ACM
2336 trace->base_time = sample->time;
2337}
2338
6810fc91 2339static int trace__process_sample(struct perf_tool *tool,
0c82adcf 2340 union perf_event *event,
6810fc91
DA
2341 struct perf_sample *sample,
2342 struct perf_evsel *evsel,
2343 struct machine *machine __maybe_unused)
2344{
2345 struct trace *trace = container_of(tool, struct trace, tool);
2346 int err = 0;
2347
744a9719 2348 tracepoint_handler handler = evsel->handler;
6810fc91 2349
bdc89661
DA
2350 if (skip_sample(trace, sample))
2351 return 0;
2352
e6001980 2353 trace__set_base_time(trace, evsel, sample);
6810fc91 2354
3160565f
DA
2355 if (handler) {
2356 ++trace->nr_events;
0c82adcf 2357 handler(trace, evsel, event, sample);
3160565f 2358 }
6810fc91
DA
2359
2360 return err;
2361}
2362
bdc89661
DA
2363static int parse_target_str(struct trace *trace)
2364{
2365 if (trace->opts.target.pid) {
2366 trace->pid_list = intlist__new(trace->opts.target.pid);
2367 if (trace->pid_list == NULL) {
2368 pr_err("Error parsing process id string\n");
2369 return -EINVAL;
2370 }
2371 }
2372
2373 if (trace->opts.target.tid) {
2374 trace->tid_list = intlist__new(trace->opts.target.tid);
2375 if (trace->tid_list == NULL) {
2376 pr_err("Error parsing thread id string\n");
2377 return -EINVAL;
2378 }
2379 }
2380
2381 return 0;
2382}
2383
1e28fe0a 2384static int trace__record(struct trace *trace, int argc, const char **argv)
5e2485b1
DA
2385{
2386 unsigned int rec_argc, i, j;
2387 const char **rec_argv;
2388 const char * const record_args[] = {
2389 "record",
2390 "-R",
2391 "-m", "1024",
2392 "-c", "1",
5e2485b1
DA
2393 };
2394
1e28fe0a
SF
2395 const char * const sc_args[] = { "-e", };
2396 unsigned int sc_args_nr = ARRAY_SIZE(sc_args);
2397 const char * const majpf_args[] = { "-e", "major-faults" };
2398 unsigned int majpf_args_nr = ARRAY_SIZE(majpf_args);
2399 const char * const minpf_args[] = { "-e", "minor-faults" };
2400 unsigned int minpf_args_nr = ARRAY_SIZE(minpf_args);
2401
9aca7f17 2402 /* +1 is for the event string below */
1e28fe0a
SF
2403 rec_argc = ARRAY_SIZE(record_args) + sc_args_nr + 1 +
2404 majpf_args_nr + minpf_args_nr + argc;
5e2485b1
DA
2405 rec_argv = calloc(rec_argc + 1, sizeof(char *));
2406
2407 if (rec_argv == NULL)
2408 return -ENOMEM;
2409
1e28fe0a 2410 j = 0;
5e2485b1 2411 for (i = 0; i < ARRAY_SIZE(record_args); i++)
1e28fe0a
SF
2412 rec_argv[j++] = record_args[i];
2413
e281a960
SF
2414 if (trace->trace_syscalls) {
2415 for (i = 0; i < sc_args_nr; i++)
2416 rec_argv[j++] = sc_args[i];
2417
2418 /* event string may be different for older kernels - e.g., RHEL6 */
2419 if (is_valid_tracepoint("raw_syscalls:sys_enter"))
2420 rec_argv[j++] = "raw_syscalls:sys_enter,raw_syscalls:sys_exit";
2421 else if (is_valid_tracepoint("syscalls:sys_enter"))
2422 rec_argv[j++] = "syscalls:sys_enter,syscalls:sys_exit";
2423 else {
2424 pr_err("Neither raw_syscalls nor syscalls events exist.\n");
2425 return -1;
2426 }
9aca7f17 2427 }
9aca7f17 2428
1e28fe0a
SF
2429 if (trace->trace_pgfaults & TRACE_PFMAJ)
2430 for (i = 0; i < majpf_args_nr; i++)
2431 rec_argv[j++] = majpf_args[i];
2432
2433 if (trace->trace_pgfaults & TRACE_PFMIN)
2434 for (i = 0; i < minpf_args_nr; i++)
2435 rec_argv[j++] = minpf_args[i];
2436
2437 for (i = 0; i < (unsigned int)argc; i++)
2438 rec_argv[j++] = argv[i];
5e2485b1 2439
1e28fe0a 2440 return cmd_record(j, rec_argv, NULL);
5e2485b1
DA
2441}
2442
bf2575c1
DA
2443static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp);
2444
08c98776 2445static bool perf_evlist__add_vfs_getname(struct perf_evlist *evlist)
c522739d 2446{
ef503831 2447 struct perf_evsel *evsel = perf_evsel__newtp("probe", "vfs_getname");
8dd2a131
JO
2448
2449 if (IS_ERR(evsel))
08c98776 2450 return false;
c522739d
ACM
2451
2452 if (perf_evsel__field(evsel, "pathname") == NULL) {
2453 perf_evsel__delete(evsel);
08c98776 2454 return false;
c522739d
ACM
2455 }
2456
744a9719 2457 evsel->handler = trace__vfs_getname;
c522739d 2458 perf_evlist__add(evlist, evsel);
08c98776 2459 return true;
c522739d
ACM
2460}
2461
598d02c5
SF
2462static int perf_evlist__add_pgfault(struct perf_evlist *evlist,
2463 u64 config)
2464{
2465 struct perf_evsel *evsel;
2466 struct perf_event_attr attr = {
2467 .type = PERF_TYPE_SOFTWARE,
2468 .mmap_data = 1,
598d02c5
SF
2469 };
2470
2471 attr.config = config;
0524798c 2472 attr.sample_period = 1;
598d02c5
SF
2473
2474 event_attr_init(&attr);
2475
2476 evsel = perf_evsel__new(&attr);
2477 if (!evsel)
2478 return -ENOMEM;
2479
2480 evsel->handler = trace__pgfault;
2481 perf_evlist__add(evlist, evsel);
2482
2483 return 0;
2484}
2485
ddbb1b13
ACM
2486static void trace__handle_event(struct trace *trace, union perf_event *event, struct perf_sample *sample)
2487{
2488 const u32 type = event->header.type;
2489 struct perf_evsel *evsel;
2490
ddbb1b13
ACM
2491 if (type != PERF_RECORD_SAMPLE) {
2492 trace__process_event(trace, trace->host, event, sample);
2493 return;
2494 }
2495
2496 evsel = perf_evlist__id2evsel(trace->evlist, sample->id);
2497 if (evsel == NULL) {
2498 fprintf(trace->output, "Unknown tp ID %" PRIu64 ", skipping...\n", sample->id);
2499 return;
2500 }
2501
e6001980
ACM
2502 trace__set_base_time(trace, evsel, sample);
2503
ddbb1b13
ACM
2504 if (evsel->attr.type == PERF_TYPE_TRACEPOINT &&
2505 sample->raw_data == NULL) {
2506 fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n",
2507 perf_evsel__name(evsel), sample->tid,
2508 sample->cpu, sample->raw_size);
2509 } else {
2510 tracepoint_handler handler = evsel->handler;
2511 handler(trace, evsel, event, sample);
2512 }
2513}
2514
c27366f0
ACM
2515static int trace__add_syscall_newtp(struct trace *trace)
2516{
2517 int ret = -1;
2518 struct perf_evlist *evlist = trace->evlist;
2519 struct perf_evsel *sys_enter, *sys_exit;
2520
2521 sys_enter = perf_evsel__syscall_newtp("sys_enter", trace__sys_enter);
2522 if (sys_enter == NULL)
2523 goto out;
2524
2525 if (perf_evsel__init_sc_tp_ptr_field(sys_enter, args))
2526 goto out_delete_sys_enter;
2527
2528 sys_exit = perf_evsel__syscall_newtp("sys_exit", trace__sys_exit);
2529 if (sys_exit == NULL)
2530 goto out_delete_sys_enter;
2531
2532 if (perf_evsel__init_sc_tp_uint_field(sys_exit, ret))
2533 goto out_delete_sys_exit;
2534
2535 perf_evlist__add(evlist, sys_enter);
2536 perf_evlist__add(evlist, sys_exit);
2537
44621819
ACM
2538 if (trace->opts.callgraph_set && !trace->kernel_syscallchains) {
2539 /*
2540 * We're interested only in the user space callchain
2541 * leading to the syscall, allow overriding that for
2542 * debugging reasons using --kernel_syscall_callchains
2543 */
2544 sys_exit->attr.exclude_callchain_kernel = 1;
2545 }
2546
8b3ce757
ACM
2547 trace->syscalls.events.sys_enter = sys_enter;
2548 trace->syscalls.events.sys_exit = sys_exit;
c27366f0
ACM
2549
2550 ret = 0;
2551out:
2552 return ret;
2553
2554out_delete_sys_exit:
2555 perf_evsel__delete_priv(sys_exit);
2556out_delete_sys_enter:
2557 perf_evsel__delete_priv(sys_enter);
2558 goto out;
2559}
2560
19867b61
ACM
2561static int trace__set_ev_qualifier_filter(struct trace *trace)
2562{
2563 int err = -1;
2564 char *filter = asprintf_expr_inout_ints("id", !trace->not_ev_qualifier,
2565 trace->ev_qualifier_ids.nr,
2566 trace->ev_qualifier_ids.entries);
2567
2568 if (filter == NULL)
2569 goto out_enomem;
2570
2571 if (!perf_evsel__append_filter(trace->syscalls.events.sys_enter, "&&", filter))
2572 err = perf_evsel__append_filter(trace->syscalls.events.sys_exit, "&&", filter);
2573
2574 free(filter);
2575out:
2576 return err;
2577out_enomem:
2578 errno = ENOMEM;
2579 goto out;
2580}
c27366f0 2581
f15eb531 2582static int trace__run(struct trace *trace, int argc, const char **argv)
514f1c67 2583{
14a052df 2584 struct perf_evlist *evlist = trace->evlist;
94ad89bc 2585 struct perf_evsel *evsel;
efd5745e
ACM
2586 int err = -1, i;
2587 unsigned long before;
f15eb531 2588 const bool forks = argc > 0;
46fb3c21 2589 bool draining = false;
514f1c67 2590
75b757ca
ACM
2591 trace->live = true;
2592
c27366f0 2593 if (trace->trace_syscalls && trace__add_syscall_newtp(trace))
801c67b0 2594 goto out_error_raw_syscalls;
514f1c67 2595
e281a960 2596 if (trace->trace_syscalls)
08c98776 2597 trace->vfs_getname = perf_evlist__add_vfs_getname(evlist);
c522739d 2598
598d02c5 2599 if ((trace->trace_pgfaults & TRACE_PFMAJ) &&
e2726d99 2600 perf_evlist__add_pgfault(evlist, PERF_COUNT_SW_PAGE_FAULTS_MAJ)) {
5ed08dae 2601 goto out_error_mem;
e2726d99 2602 }
598d02c5
SF
2603
2604 if ((trace->trace_pgfaults & TRACE_PFMIN) &&
2605 perf_evlist__add_pgfault(evlist, PERF_COUNT_SW_PAGE_FAULTS_MIN))
5ed08dae 2606 goto out_error_mem;
598d02c5 2607
1302d88e 2608 if (trace->sched &&
2cc990ba
ACM
2609 perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime",
2610 trace__sched_stat_runtime))
2611 goto out_error_sched_stat_runtime;
1302d88e 2612
514f1c67
ACM
2613 err = perf_evlist__create_maps(evlist, &trace->opts.target);
2614 if (err < 0) {
c24ff998 2615 fprintf(trace->output, "Problems parsing the target to trace, check your options!\n");
514f1c67
ACM
2616 goto out_delete_evlist;
2617 }
2618
752fde44
ACM
2619 err = trace__symbols_init(trace, evlist);
2620 if (err < 0) {
c24ff998 2621 fprintf(trace->output, "Problems initializing symbol libraries!\n");
03ad9747 2622 goto out_delete_evlist;
752fde44
ACM
2623 }
2624
fde54b78
ACM
2625 perf_evlist__config(evlist, &trace->opts, NULL);
2626
2627 if (trace->opts.callgraph_set && trace->syscalls.events.sys_exit) {
2628 perf_evsel__config_callchain(trace->syscalls.events.sys_exit,
2629 &trace->opts, &callchain_param);
2630 /*
2631 * Now we have evsels with different sample_ids, use
2632 * PERF_SAMPLE_IDENTIFIER to map from sample to evsel
2633 * from a fixed position in each ring buffer record.
2634 *
2635 * As of this the changeset introducing this comment, this
2636 * isn't strictly needed, as the fields that can come before
2637 * PERF_SAMPLE_ID are all used, but we'll probably disable
2638 * some of those for things like copying the payload of
2639 * pointer syscall arguments, and for vfs_getname we don't
2640 * need PERF_SAMPLE_ADDR and PERF_SAMPLE_IP, so do this
2641 * here as a warning we need to use PERF_SAMPLE_IDENTIFIER.
2642 */
2643 perf_evlist__set_sample_bit(evlist, IDENTIFIER);
2644 perf_evlist__reset_sample_bit(evlist, ID);
2645 }
514f1c67 2646
f15eb531
NK
2647 signal(SIGCHLD, sig_handler);
2648 signal(SIGINT, sig_handler);
2649
2650 if (forks) {
6ef73ec4 2651 err = perf_evlist__prepare_workload(evlist, &trace->opts.target,
735f7e0b 2652 argv, false, NULL);
f15eb531 2653 if (err < 0) {
c24ff998 2654 fprintf(trace->output, "Couldn't run the workload!\n");
03ad9747 2655 goto out_delete_evlist;
f15eb531
NK
2656 }
2657 }
2658
514f1c67 2659 err = perf_evlist__open(evlist);
a8f23d8f
ACM
2660 if (err < 0)
2661 goto out_error_open;
514f1c67 2662
ba504235
WN
2663 err = bpf__apply_obj_config();
2664 if (err) {
2665 char errbuf[BUFSIZ];
2666
2667 bpf__strerror_apply_obj_config(err, errbuf, sizeof(errbuf));
2668 pr_err("ERROR: Apply config to BPF failed: %s\n",
2669 errbuf);
2670 goto out_error_open;
2671 }
2672
241b057c
ACM
2673 /*
2674 * Better not use !target__has_task() here because we need to cover the
2675 * case where no threads were specified in the command line, but a
2676 * workload was, and in that case we will fill in the thread_map when
2677 * we fork the workload in perf_evlist__prepare_workload.
2678 */
f078c385
ACM
2679 if (trace->filter_pids.nr > 0)
2680 err = perf_evlist__set_filter_pids(evlist, trace->filter_pids.nr, trace->filter_pids.entries);
e13798c7 2681 else if (thread_map__pid(evlist->threads, 0) == -1)
f078c385
ACM
2682 err = perf_evlist__set_filter_pid(evlist, getpid());
2683
94ad89bc
ACM
2684 if (err < 0)
2685 goto out_error_mem;
2686
19867b61
ACM
2687 if (trace->ev_qualifier_ids.nr > 0) {
2688 err = trace__set_ev_qualifier_filter(trace);
2689 if (err < 0)
2690 goto out_errno;
19867b61 2691
2e5e5f87
ACM
2692 pr_debug("event qualifier tracepoint filter: %s\n",
2693 trace->syscalls.events.sys_exit->filter);
2694 }
19867b61 2695
94ad89bc
ACM
2696 err = perf_evlist__apply_filters(evlist, &evsel);
2697 if (err < 0)
2698 goto out_error_apply_filters;
241b057c 2699
f885037e 2700 err = perf_evlist__mmap(evlist, trace->opts.mmap_pages, false);
e09b18d4
ACM
2701 if (err < 0)
2702 goto out_error_mmap;
514f1c67 2703
cb24d01d
ACM
2704 if (!target__none(&trace->opts.target))
2705 perf_evlist__enable(evlist);
2706
f15eb531
NK
2707 if (forks)
2708 perf_evlist__start_workload(evlist);
2709
e13798c7 2710 trace->multiple_threads = thread_map__pid(evlist->threads, 0) == -1 ||
42052bea
ACM
2711 evlist->threads->nr > 1 ||
2712 perf_evlist__first(evlist)->attr.inherit;
514f1c67 2713again:
efd5745e 2714 before = trace->nr_events;
514f1c67
ACM
2715
2716 for (i = 0; i < evlist->nr_mmaps; i++) {
2717 union perf_event *event;
2718
2719 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
514f1c67 2720 struct perf_sample sample;
514f1c67 2721
efd5745e 2722 ++trace->nr_events;
514f1c67 2723
514f1c67
ACM
2724 err = perf_evlist__parse_sample(evlist, event, &sample);
2725 if (err) {
c24ff998 2726 fprintf(trace->output, "Can't parse sample, err = %d, skipping...\n", err);
8e50d384 2727 goto next_event;
514f1c67
ACM
2728 }
2729
ddbb1b13 2730 trace__handle_event(trace, event, &sample);
8e50d384
ZZ
2731next_event:
2732 perf_evlist__mmap_consume(evlist, i);
20c5f10e 2733
ba209f85
ACM
2734 if (interrupted)
2735 goto out_disable;
02ac5421
ACM
2736
2737 if (done && !draining) {
2738 perf_evlist__disable(evlist);
2739 draining = true;
2740 }
514f1c67
ACM
2741 }
2742 }
2743
efd5745e 2744 if (trace->nr_events == before) {
ba209f85 2745 int timeout = done ? 100 : -1;
f15eb531 2746
46fb3c21
ACM
2747 if (!draining && perf_evlist__poll(evlist, timeout) > 0) {
2748 if (perf_evlist__filter_pollfd(evlist, POLLERR | POLLHUP) == 0)
2749 draining = true;
2750
ba209f85 2751 goto again;
46fb3c21 2752 }
ba209f85
ACM
2753 } else {
2754 goto again;
f15eb531
NK
2755 }
2756
ba209f85 2757out_disable:
f3b623b8
ACM
2758 thread__zput(trace->current);
2759
ba209f85 2760 perf_evlist__disable(evlist);
514f1c67 2761
c522739d
ACM
2762 if (!err) {
2763 if (trace->summary)
2764 trace__fprintf_thread_summary(trace, trace->output);
2765
2766 if (trace->show_tool_stats) {
2767 fprintf(trace->output, "Stats:\n "
2768 " vfs_getname : %" PRIu64 "\n"
2769 " proc_getname: %" PRIu64 "\n",
2770 trace->stats.vfs_getname,
2771 trace->stats.proc_getname);
2772 }
2773 }
bf2575c1 2774
514f1c67
ACM
2775out_delete_evlist:
2776 perf_evlist__delete(evlist);
14a052df 2777 trace->evlist = NULL;
75b757ca 2778 trace->live = false;
514f1c67 2779 return err;
6ef068cb
ACM
2780{
2781 char errbuf[BUFSIZ];
a8f23d8f 2782
2cc990ba 2783out_error_sched_stat_runtime:
988bdb31 2784 tracing_path__strerror_open_tp(errno, errbuf, sizeof(errbuf), "sched", "sched_stat_runtime");
2cc990ba
ACM
2785 goto out_error;
2786
801c67b0 2787out_error_raw_syscalls:
988bdb31 2788 tracing_path__strerror_open_tp(errno, errbuf, sizeof(errbuf), "raw_syscalls", "sys_(enter|exit)");
a8f23d8f
ACM
2789 goto out_error;
2790
e09b18d4
ACM
2791out_error_mmap:
2792 perf_evlist__strerror_mmap(evlist, errno, errbuf, sizeof(errbuf));
2793 goto out_error;
2794
a8f23d8f
ACM
2795out_error_open:
2796 perf_evlist__strerror_open(evlist, errno, errbuf, sizeof(errbuf));
2797
2798out_error:
6ef068cb 2799 fprintf(trace->output, "%s\n", errbuf);
87f91868 2800 goto out_delete_evlist;
94ad89bc
ACM
2801
2802out_error_apply_filters:
2803 fprintf(trace->output,
2804 "Failed to set filter \"%s\" on event %s with %d (%s)\n",
2805 evsel->filter, perf_evsel__name(evsel), errno,
2806 strerror_r(errno, errbuf, sizeof(errbuf)));
2807 goto out_delete_evlist;
514f1c67 2808}
5ed08dae
ACM
2809out_error_mem:
2810 fprintf(trace->output, "Not enough memory to run!\n");
2811 goto out_delete_evlist;
19867b61
ACM
2812
2813out_errno:
2814 fprintf(trace->output, "errno=%d,%s\n", errno, strerror(errno));
2815 goto out_delete_evlist;
a8f23d8f 2816}
514f1c67 2817
6810fc91
DA
2818static int trace__replay(struct trace *trace)
2819{
2820 const struct perf_evsel_str_handler handlers[] = {
c522739d 2821 { "probe:vfs_getname", trace__vfs_getname, },
6810fc91 2822 };
f5fc1412
JO
2823 struct perf_data_file file = {
2824 .path = input_name,
2825 .mode = PERF_DATA_MODE_READ,
e366a6d8 2826 .force = trace->force,
f5fc1412 2827 };
6810fc91 2828 struct perf_session *session;
003824e8 2829 struct perf_evsel *evsel;
6810fc91
DA
2830 int err = -1;
2831
2832 trace->tool.sample = trace__process_sample;
2833 trace->tool.mmap = perf_event__process_mmap;
384c671e 2834 trace->tool.mmap2 = perf_event__process_mmap2;
6810fc91
DA
2835 trace->tool.comm = perf_event__process_comm;
2836 trace->tool.exit = perf_event__process_exit;
2837 trace->tool.fork = perf_event__process_fork;
2838 trace->tool.attr = perf_event__process_attr;
2839 trace->tool.tracing_data = perf_event__process_tracing_data;
2840 trace->tool.build_id = perf_event__process_build_id;
2841
0a8cb85c 2842 trace->tool.ordered_events = true;
6810fc91
DA
2843 trace->tool.ordering_requires_timestamps = true;
2844
2845 /* add tid to output */
2846 trace->multiple_threads = true;
2847
f5fc1412 2848 session = perf_session__new(&file, false, &trace->tool);
6810fc91 2849 if (session == NULL)
52e02834 2850 return -1;
6810fc91 2851
0a7e6d1b 2852 if (symbol__init(&session->header.env) < 0)
cb2ffae2
NK
2853 goto out;
2854
8fb598e5
DA
2855 trace->host = &session->machines.host;
2856
6810fc91
DA
2857 err = perf_session__set_tracepoints_handlers(session, handlers);
2858 if (err)
2859 goto out;
2860
003824e8
NK
2861 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2862 "raw_syscalls:sys_enter");
9aca7f17
DA
2863 /* older kernels have syscalls tp versus raw_syscalls */
2864 if (evsel == NULL)
2865 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2866 "syscalls:sys_enter");
003824e8 2867
e281a960
SF
2868 if (evsel &&
2869 (perf_evsel__init_syscall_tp(evsel, trace__sys_enter) < 0 ||
2870 perf_evsel__init_sc_tp_ptr_field(evsel, args))) {
003824e8
NK
2871 pr_err("Error during initialize raw_syscalls:sys_enter event\n");
2872 goto out;
2873 }
2874
2875 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2876 "raw_syscalls:sys_exit");
9aca7f17
DA
2877 if (evsel == NULL)
2878 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2879 "syscalls:sys_exit");
e281a960
SF
2880 if (evsel &&
2881 (perf_evsel__init_syscall_tp(evsel, trace__sys_exit) < 0 ||
2882 perf_evsel__init_sc_tp_uint_field(evsel, ret))) {
003824e8 2883 pr_err("Error during initialize raw_syscalls:sys_exit event\n");
6810fc91
DA
2884 goto out;
2885 }
2886
1e28fe0a
SF
2887 evlist__for_each(session->evlist, evsel) {
2888 if (evsel->attr.type == PERF_TYPE_SOFTWARE &&
2889 (evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ||
2890 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MIN ||
2891 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS))
2892 evsel->handler = trace__pgfault;
2893 }
2894
bdc89661
DA
2895 err = parse_target_str(trace);
2896 if (err != 0)
2897 goto out;
2898
6810fc91
DA
2899 setup_pager();
2900
b7b61cbe 2901 err = perf_session__process_events(session);
6810fc91
DA
2902 if (err)
2903 pr_err("Failed to process events, error %d", err);
2904
bf2575c1
DA
2905 else if (trace->summary)
2906 trace__fprintf_thread_summary(trace, trace->output);
2907
6810fc91
DA
2908out:
2909 perf_session__delete(session);
2910
2911 return err;
2912}
2913
1302d88e
ACM
2914static size_t trace__fprintf_threads_header(FILE *fp)
2915{
2916 size_t printed;
2917
99ff7150 2918 printed = fprintf(fp, "\n Summary of events:\n\n");
bf2575c1
DA
2919
2920 return printed;
2921}
2922
2923static size_t thread__dump_stats(struct thread_trace *ttrace,
2924 struct trace *trace, FILE *fp)
2925{
2926 struct stats *stats;
2927 size_t printed = 0;
2928 struct syscall *sc;
2929 struct int_node *inode = intlist__first(ttrace->syscall_stats);
2930
2931 if (inode == NULL)
2932 return 0;
2933
2934 printed += fprintf(fp, "\n");
2935
834fd46d
MW
2936 printed += fprintf(fp, " syscall calls total min avg max stddev\n");
2937 printed += fprintf(fp, " (msec) (msec) (msec) (msec) (%%)\n");
2938 printed += fprintf(fp, " --------------- -------- --------- --------- --------- --------- ------\n");
99ff7150 2939
bf2575c1
DA
2940 /* each int_node is a syscall */
2941 while (inode) {
2942 stats = inode->priv;
2943 if (stats) {
2944 double min = (double)(stats->min) / NSEC_PER_MSEC;
2945 double max = (double)(stats->max) / NSEC_PER_MSEC;
2946 double avg = avg_stats(stats);
2947 double pct;
2948 u64 n = (u64) stats->n;
2949
2950 pct = avg ? 100.0 * stddev_stats(stats)/avg : 0.0;
2951 avg /= NSEC_PER_MSEC;
2952
2953 sc = &trace->syscalls.table[inode->i];
99ff7150 2954 printed += fprintf(fp, " %-15s", sc->name);
834fd46d
MW
2955 printed += fprintf(fp, " %8" PRIu64 " %9.3f %9.3f %9.3f",
2956 n, avg * n, min, avg);
27a778b5 2957 printed += fprintf(fp, " %9.3f %9.2f%%\n", max, pct);
bf2575c1
DA
2958 }
2959
2960 inode = intlist__next(inode);
2961 }
2962
2963 printed += fprintf(fp, "\n\n");
1302d88e
ACM
2964
2965 return printed;
2966}
2967
896cbb56
DA
2968/* struct used to pass data to per-thread function */
2969struct summary_data {
2970 FILE *fp;
2971 struct trace *trace;
2972 size_t printed;
2973};
2974
2975static int trace__fprintf_one_thread(struct thread *thread, void *priv)
2976{
2977 struct summary_data *data = priv;
2978 FILE *fp = data->fp;
2979 size_t printed = data->printed;
2980 struct trace *trace = data->trace;
89dceb22 2981 struct thread_trace *ttrace = thread__priv(thread);
896cbb56
DA
2982 double ratio;
2983
2984 if (ttrace == NULL)
2985 return 0;
2986
2987 ratio = (double)ttrace->nr_events / trace->nr_events * 100.0;
2988
15e65c69 2989 printed += fprintf(fp, " %s (%d), ", thread__comm_str(thread), thread->tid);
99ff7150 2990 printed += fprintf(fp, "%lu events, ", ttrace->nr_events);
15e65c69 2991 printed += fprintf(fp, "%.1f%%", ratio);
a2ea67d7
SF
2992 if (ttrace->pfmaj)
2993 printed += fprintf(fp, ", %lu majfaults", ttrace->pfmaj);
2994 if (ttrace->pfmin)
2995 printed += fprintf(fp, ", %lu minfaults", ttrace->pfmin);
99ff7150 2996 printed += fprintf(fp, ", %.3f msec\n", ttrace->runtime_ms);
bf2575c1 2997 printed += thread__dump_stats(ttrace, trace, fp);
896cbb56
DA
2998
2999 data->printed += printed;
3000
3001 return 0;
3002}
3003
1302d88e
ACM
3004static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp)
3005{
896cbb56
DA
3006 struct summary_data data = {
3007 .fp = fp,
3008 .trace = trace
3009 };
3010 data.printed = trace__fprintf_threads_header(fp);
1302d88e 3011
896cbb56
DA
3012 machine__for_each_thread(trace->host, trace__fprintf_one_thread, &data);
3013
3014 return data.printed;
1302d88e
ACM
3015}
3016
ae9ed035
ACM
3017static int trace__set_duration(const struct option *opt, const char *str,
3018 int unset __maybe_unused)
3019{
3020 struct trace *trace = opt->value;
3021
3022 trace->duration_filter = atof(str);
3023 return 0;
3024}
3025
f078c385
ACM
3026static int trace__set_filter_pids(const struct option *opt, const char *str,
3027 int unset __maybe_unused)
3028{
3029 int ret = -1;
3030 size_t i;
3031 struct trace *trace = opt->value;
3032 /*
3033 * FIXME: introduce a intarray class, plain parse csv and create a
3034 * { int nr, int entries[] } struct...
3035 */
3036 struct intlist *list = intlist__new(str);
3037
3038 if (list == NULL)
3039 return -1;
3040
3041 i = trace->filter_pids.nr = intlist__nr_entries(list) + 1;
3042 trace->filter_pids.entries = calloc(i, sizeof(pid_t));
3043
3044 if (trace->filter_pids.entries == NULL)
3045 goto out;
3046
3047 trace->filter_pids.entries[0] = getpid();
3048
3049 for (i = 1; i < trace->filter_pids.nr; ++i)
3050 trace->filter_pids.entries[i] = intlist__entry(list, i - 1)->i;
3051
3052 intlist__delete(list);
3053 ret = 0;
3054out:
3055 return ret;
3056}
3057
c24ff998
ACM
3058static int trace__open_output(struct trace *trace, const char *filename)
3059{
3060 struct stat st;
3061
3062 if (!stat(filename, &st) && st.st_size) {
3063 char oldname[PATH_MAX];
3064
3065 scnprintf(oldname, sizeof(oldname), "%s.old", filename);
3066 unlink(oldname);
3067 rename(filename, oldname);
3068 }
3069
3070 trace->output = fopen(filename, "w");
3071
3072 return trace->output == NULL ? -errno : 0;
3073}
3074
598d02c5
SF
3075static int parse_pagefaults(const struct option *opt, const char *str,
3076 int unset __maybe_unused)
3077{
3078 int *trace_pgfaults = opt->value;
3079
3080 if (strcmp(str, "all") == 0)
3081 *trace_pgfaults |= TRACE_PFMAJ | TRACE_PFMIN;
3082 else if (strcmp(str, "maj") == 0)
3083 *trace_pgfaults |= TRACE_PFMAJ;
3084 else if (strcmp(str, "min") == 0)
3085 *trace_pgfaults |= TRACE_PFMIN;
3086 else
3087 return -1;
3088
3089 return 0;
3090}
3091
14a052df
ACM
3092static void evlist__set_evsel_handler(struct perf_evlist *evlist, void *handler)
3093{
3094 struct perf_evsel *evsel;
3095
3096 evlist__for_each(evlist, evsel)
3097 evsel->handler = handler;
3098}
3099
514f1c67
ACM
3100int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
3101{
6fdd9cb7 3102 const char *trace_usage[] = {
f15eb531
NK
3103 "perf trace [<options>] [<command>]",
3104 "perf trace [<options>] -- <command> [<options>]",
5e2485b1
DA
3105 "perf trace record [<options>] [<command>]",
3106 "perf trace record [<options>] -- <command> [<options>]",
514f1c67
ACM
3107 NULL
3108 };
3109 struct trace trace = {
514f1c67
ACM
3110 .syscalls = {
3111 . max = -1,
3112 },
3113 .opts = {
3114 .target = {
3115 .uid = UINT_MAX,
3116 .uses_mmap = true,
3117 },
3118 .user_freq = UINT_MAX,
3119 .user_interval = ULLONG_MAX,
509051ea 3120 .no_buffering = true,
38d5447d 3121 .mmap_pages = UINT_MAX,
9d9cad76 3122 .proc_map_timeout = 500,
514f1c67 3123 },
007d66a0 3124 .output = stderr,
50c95cbd 3125 .show_comm = true,
e281a960 3126 .trace_syscalls = true,
44621819 3127 .kernel_syscallchains = false,
514f1c67 3128 };
c24ff998 3129 const char *output_name = NULL;
2ae3a312 3130 const char *ev_qualifier_str = NULL;
514f1c67 3131 const struct option trace_options[] = {
14a052df
ACM
3132 OPT_CALLBACK(0, "event", &trace.evlist, "event",
3133 "event selector. use 'perf list' to list available events",
3134 parse_events_option),
50c95cbd
ACM
3135 OPT_BOOLEAN(0, "comm", &trace.show_comm,
3136 "show the thread COMM next to its id"),
c522739d 3137 OPT_BOOLEAN(0, "tool_stats", &trace.show_tool_stats, "show tool stats"),
d303e85a 3138 OPT_STRING('e', "expr", &ev_qualifier_str, "expr", "list of syscalls to trace"),
c24ff998 3139 OPT_STRING('o', "output", &output_name, "file", "output file name"),
6810fc91 3140 OPT_STRING('i', "input", &input_name, "file", "Analyze events in file"),
514f1c67
ACM
3141 OPT_STRING('p', "pid", &trace.opts.target.pid, "pid",
3142 "trace events on existing process id"),
ac9be8ee 3143 OPT_STRING('t', "tid", &trace.opts.target.tid, "tid",
514f1c67 3144 "trace events on existing thread id"),
fa0e4ffe
ACM
3145 OPT_CALLBACK(0, "filter-pids", &trace, "CSV list of pids",
3146 "pids to filter (by the kernel)", trace__set_filter_pids),
ac9be8ee 3147 OPT_BOOLEAN('a', "all-cpus", &trace.opts.target.system_wide,
514f1c67 3148 "system-wide collection from all CPUs"),
ac9be8ee 3149 OPT_STRING('C', "cpu", &trace.opts.target.cpu_list, "cpu",
514f1c67 3150 "list of cpus to monitor"),
6810fc91 3151 OPT_BOOLEAN(0, "no-inherit", &trace.opts.no_inherit,
514f1c67 3152 "child tasks do not inherit counters"),
994a1f78
JO
3153 OPT_CALLBACK('m', "mmap-pages", &trace.opts.mmap_pages, "pages",
3154 "number of mmap data pages",
3155 perf_evlist__parse_mmap_pages),
ac9be8ee 3156 OPT_STRING('u', "uid", &trace.opts.target.uid_str, "user",
514f1c67 3157 "user to profile"),
ae9ed035
ACM
3158 OPT_CALLBACK(0, "duration", &trace, "float",
3159 "show only events with duration > N.M ms",
3160 trace__set_duration),
1302d88e 3161 OPT_BOOLEAN(0, "sched", &trace.sched, "show blocking scheduler events"),
7c304ee0 3162 OPT_INCR('v', "verbose", &verbose, "be more verbose"),
4bb09192
DA
3163 OPT_BOOLEAN('T', "time", &trace.full_time,
3164 "Show full timestamp, not time relative to first start"),
fd2eabaf
DA
3165 OPT_BOOLEAN('s', "summary", &trace.summary_only,
3166 "Show only syscall summary with statistics"),
3167 OPT_BOOLEAN('S', "with-summary", &trace.summary,
3168 "Show all syscalls and summary with statistics"),
598d02c5
SF
3169 OPT_CALLBACK_DEFAULT('F', "pf", &trace.trace_pgfaults, "all|maj|min",
3170 "Trace pagefaults", parse_pagefaults, "maj"),
e281a960 3171 OPT_BOOLEAN(0, "syscalls", &trace.trace_syscalls, "Trace syscalls"),
e366a6d8 3172 OPT_BOOLEAN('f', "force", &trace.force, "don't complain, do it"),
566a0885
MW
3173 OPT_CALLBACK(0, "call-graph", &trace.opts,
3174 "record_mode[,record_size]", record_callchain_help,
3175 &record_parse_callchain_opt),
44621819
ACM
3176 OPT_BOOLEAN(0, "kernel-syscall-graph", &trace.kernel_syscallchains,
3177 "Show the kernel callchains on the syscall exit path"),
9d9cad76
KL
3178 OPT_UINTEGER(0, "proc-map-timeout", &trace.opts.proc_map_timeout,
3179 "per thread proc mmap processing timeout in ms"),
514f1c67
ACM
3180 OPT_END()
3181 };
6fdd9cb7 3182 const char * const trace_subcommands[] = { "record", NULL };
514f1c67 3183 int err;
32caf0d1 3184 char bf[BUFSIZ];
514f1c67 3185
4d08cb80
ACM
3186 signal(SIGSEGV, sighandler_dump_stack);
3187 signal(SIGFPE, sighandler_dump_stack);
3188
14a052df 3189 trace.evlist = perf_evlist__new();
fd0db102 3190 trace.sctbl = syscalltbl__new();
14a052df 3191
fd0db102 3192 if (trace.evlist == NULL || trace.sctbl == NULL) {
14a052df 3193 pr_err("Not enough memory to run!\n");
ff8f695c 3194 err = -ENOMEM;
14a052df
ACM
3195 goto out;
3196 }
3197
6fdd9cb7
YS
3198 argc = parse_options_subcommand(argc, argv, trace_options, trace_subcommands,
3199 trace_usage, PARSE_OPT_STOP_AT_NON_OPTION);
fd2eabaf 3200
d7888573
WN
3201 err = bpf__setup_stdout(trace.evlist);
3202 if (err) {
3203 bpf__strerror_setup_stdout(trace.evlist, err, bf, sizeof(bf));
3204 pr_err("ERROR: Setup BPF stdout failed: %s\n", bf);
3205 goto out;
3206 }
3207
59247e33
ACM
3208 err = -1;
3209
598d02c5
SF
3210 if (trace.trace_pgfaults) {
3211 trace.opts.sample_address = true;
3212 trace.opts.sample_time = true;
3213 }
3214
566a0885
MW
3215 if (trace.opts.callgraph_set)
3216 symbol_conf.use_callchain = true;
3217
14a052df
ACM
3218 if (trace.evlist->nr_entries > 0)
3219 evlist__set_evsel_handler(trace.evlist, trace__event_handler);
3220
1e28fe0a
SF
3221 if ((argc >= 1) && (strcmp(argv[0], "record") == 0))
3222 return trace__record(&trace, argc-1, &argv[1]);
3223
3224 /* summary_only implies summary option, but don't overwrite summary if set */
3225 if (trace.summary_only)
3226 trace.summary = trace.summary_only;
3227
726f3234
ACM
3228 if (!trace.trace_syscalls && !trace.trace_pgfaults &&
3229 trace.evlist->nr_entries == 0 /* Was --events used? */) {
e281a960
SF
3230 pr_err("Please specify something to trace.\n");
3231 return -1;
3232 }
3233
59247e33
ACM
3234 if (!trace.trace_syscalls && ev_qualifier_str) {
3235 pr_err("The -e option can't be used with --no-syscalls.\n");
3236 goto out;
3237 }
3238
c24ff998
ACM
3239 if (output_name != NULL) {
3240 err = trace__open_output(&trace, output_name);
3241 if (err < 0) {
3242 perror("failed to create output file");
3243 goto out;
3244 }
3245 }
3246
fd0db102
ACM
3247 trace.open_id = syscalltbl__id(trace.sctbl, "open");
3248
2ae3a312 3249 if (ev_qualifier_str != NULL) {
b059efdf 3250 const char *s = ev_qualifier_str;
005438a8
ACM
3251 struct strlist_config slist_config = {
3252 .dirname = system_path(STRACE_GROUPS_DIR),
3253 };
b059efdf
ACM
3254
3255 trace.not_ev_qualifier = *s == '!';
3256 if (trace.not_ev_qualifier)
3257 ++s;
005438a8 3258 trace.ev_qualifier = strlist__new(s, &slist_config);
2ae3a312 3259 if (trace.ev_qualifier == NULL) {
c24ff998
ACM
3260 fputs("Not enough memory to parse event qualifier",
3261 trace.output);
3262 err = -ENOMEM;
3263 goto out_close;
2ae3a312 3264 }
d0cc439b
ACM
3265
3266 err = trace__validate_ev_qualifier(&trace);
3267 if (err)
3268 goto out_close;
2ae3a312
ACM
3269 }
3270
602ad878 3271 err = target__validate(&trace.opts.target);
32caf0d1 3272 if (err) {
602ad878 3273 target__strerror(&trace.opts.target, err, bf, sizeof(bf));
c24ff998
ACM
3274 fprintf(trace.output, "%s", bf);
3275 goto out_close;
32caf0d1
NK
3276 }
3277
602ad878 3278 err = target__parse_uid(&trace.opts.target);
514f1c67 3279 if (err) {
602ad878 3280 target__strerror(&trace.opts.target, err, bf, sizeof(bf));
c24ff998
ACM
3281 fprintf(trace.output, "%s", bf);
3282 goto out_close;
514f1c67
ACM
3283 }
3284
602ad878 3285 if (!argc && target__none(&trace.opts.target))
ee76120e
NK
3286 trace.opts.target.system_wide = true;
3287
6810fc91
DA
3288 if (input_name)
3289 err = trace__replay(&trace);
3290 else
3291 err = trace__run(&trace, argc, argv);
1302d88e 3292
c24ff998
ACM
3293out_close:
3294 if (output_name != NULL)
3295 fclose(trace.output);
3296out:
1302d88e 3297 return err;
514f1c67 3298}