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