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