perf stat: Add units to nanosec-based counters
[deliverable/linux.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"
752fde44 6#include "util/machine.h"
6810fc91 7#include "util/session.h"
752fde44 8#include "util/thread.h"
514f1c67 9#include "util/parse-options.h"
2ae3a312 10#include "util/strlist.h"
bdc89661 11#include "util/intlist.h"
514f1c67 12#include "util/thread_map.h"
514f1c67
ACM
13
14#include <libaudit.h>
15#include <stdlib.h>
49af9e93 16#include <sys/eventfd.h>
ae685380 17#include <sys/mman.h>
f9da0b0c 18#include <linux/futex.h>
514f1c67 19
456857bd
IM
20/* For older distros: */
21#ifndef MAP_STACK
22# define MAP_STACK 0x20000
23#endif
24
25#ifndef MADV_HWPOISON
26# define MADV_HWPOISON 100
27#endif
28
29#ifndef MADV_MERGEABLE
30# define MADV_MERGEABLE 12
31#endif
32
33#ifndef MADV_UNMERGEABLE
34# define MADV_UNMERGEABLE 13
35#endif
36
01533e97
ACM
37struct syscall_arg {
38 unsigned long val;
75b757ca
ACM
39 struct thread *thread;
40 struct trace *trace;
1f115cb7 41 void *parm;
01533e97
ACM
42 u8 idx;
43 u8 mask;
44};
45
1f115cb7
ACM
46struct strarray {
47 int nr_entries;
48 const char **entries;
49};
50
51#define DEFINE_STRARRAY(array) struct strarray strarray__##array = { \
52 .nr_entries = ARRAY_SIZE(array), \
53 .entries = array, \
54}
55
56static size_t syscall_arg__scnprintf_strarray(char *bf, size_t size,
57 struct syscall_arg *arg)
58{
59 int idx = arg->val;
60 struct strarray *sa = arg->parm;
61
62 if (idx < 0 || idx >= sa->nr_entries)
63 return scnprintf(bf, size, "%d", idx);
64
65 return scnprintf(bf, size, "%s", sa->entries[idx]);
66}
67
68#define SCA_STRARRAY syscall_arg__scnprintf_strarray
69
75b757ca
ACM
70static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
71 struct syscall_arg *arg);
72
73#define SCA_FD syscall_arg__scnprintf_fd
74
75static size_t syscall_arg__scnprintf_fd_at(char *bf, size_t size,
76 struct syscall_arg *arg)
77{
78 int fd = arg->val;
79
80 if (fd == AT_FDCWD)
81 return scnprintf(bf, size, "CWD");
82
83 return syscall_arg__scnprintf_fd(bf, size, arg);
84}
85
86#define SCA_FDAT syscall_arg__scnprintf_fd_at
87
88static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
89 struct syscall_arg *arg);
90
91#define SCA_CLOSE_FD syscall_arg__scnprintf_close_fd
92
6e7eeb51 93static size_t syscall_arg__scnprintf_hex(char *bf, size_t size,
01533e97 94 struct syscall_arg *arg)
13d4ff3e 95{
01533e97 96 return scnprintf(bf, size, "%#lx", arg->val);
13d4ff3e
ACM
97}
98
beccb2b5
ACM
99#define SCA_HEX syscall_arg__scnprintf_hex
100
6e7eeb51 101static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size,
01533e97 102 struct syscall_arg *arg)
ae685380 103{
01533e97 104 int printed = 0, prot = arg->val;
ae685380
ACM
105
106 if (prot == PROT_NONE)
107 return scnprintf(bf, size, "NONE");
108#define P_MMAP_PROT(n) \
109 if (prot & PROT_##n) { \
110 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
111 prot &= ~PROT_##n; \
112 }
113
114 P_MMAP_PROT(EXEC);
115 P_MMAP_PROT(READ);
116 P_MMAP_PROT(WRITE);
117#ifdef PROT_SEM
118 P_MMAP_PROT(SEM);
119#endif
120 P_MMAP_PROT(GROWSDOWN);
121 P_MMAP_PROT(GROWSUP);
122#undef P_MMAP_PROT
123
124 if (prot)
125 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", prot);
126
127 return printed;
128}
129
130#define SCA_MMAP_PROT syscall_arg__scnprintf_mmap_prot
131
6e7eeb51 132static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size,
01533e97 133 struct syscall_arg *arg)
941557e0 134{
01533e97 135 int printed = 0, flags = arg->val;
941557e0
ACM
136
137#define P_MMAP_FLAG(n) \
138 if (flags & MAP_##n) { \
139 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
140 flags &= ~MAP_##n; \
141 }
142
143 P_MMAP_FLAG(SHARED);
144 P_MMAP_FLAG(PRIVATE);
41817815 145#ifdef MAP_32BIT
941557e0 146 P_MMAP_FLAG(32BIT);
41817815 147#endif
941557e0
ACM
148 P_MMAP_FLAG(ANONYMOUS);
149 P_MMAP_FLAG(DENYWRITE);
150 P_MMAP_FLAG(EXECUTABLE);
151 P_MMAP_FLAG(FILE);
152 P_MMAP_FLAG(FIXED);
153 P_MMAP_FLAG(GROWSDOWN);
f2935f3e 154#ifdef MAP_HUGETLB
941557e0 155 P_MMAP_FLAG(HUGETLB);
f2935f3e 156#endif
941557e0
ACM
157 P_MMAP_FLAG(LOCKED);
158 P_MMAP_FLAG(NONBLOCK);
159 P_MMAP_FLAG(NORESERVE);
160 P_MMAP_FLAG(POPULATE);
161 P_MMAP_FLAG(STACK);
162#ifdef MAP_UNINITIALIZED
163 P_MMAP_FLAG(UNINITIALIZED);
164#endif
165#undef P_MMAP_FLAG
166
167 if (flags)
168 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
169
170 return printed;
171}
172
173#define SCA_MMAP_FLAGS syscall_arg__scnprintf_mmap_flags
174
6e7eeb51 175static size_t syscall_arg__scnprintf_madvise_behavior(char *bf, size_t size,
01533e97 176 struct syscall_arg *arg)
9e9716d1 177{
01533e97 178 int behavior = arg->val;
9e9716d1
ACM
179
180 switch (behavior) {
181#define P_MADV_BHV(n) case MADV_##n: return scnprintf(bf, size, #n)
182 P_MADV_BHV(NORMAL);
183 P_MADV_BHV(RANDOM);
184 P_MADV_BHV(SEQUENTIAL);
185 P_MADV_BHV(WILLNEED);
186 P_MADV_BHV(DONTNEED);
187 P_MADV_BHV(REMOVE);
188 P_MADV_BHV(DONTFORK);
189 P_MADV_BHV(DOFORK);
190 P_MADV_BHV(HWPOISON);
191#ifdef MADV_SOFT_OFFLINE
192 P_MADV_BHV(SOFT_OFFLINE);
193#endif
194 P_MADV_BHV(MERGEABLE);
195 P_MADV_BHV(UNMERGEABLE);
f2935f3e 196#ifdef MADV_HUGEPAGE
9e9716d1 197 P_MADV_BHV(HUGEPAGE);
f2935f3e
DA
198#endif
199#ifdef MADV_NOHUGEPAGE
9e9716d1 200 P_MADV_BHV(NOHUGEPAGE);
f2935f3e 201#endif
9e9716d1
ACM
202#ifdef MADV_DONTDUMP
203 P_MADV_BHV(DONTDUMP);
204#endif
205#ifdef MADV_DODUMP
206 P_MADV_BHV(DODUMP);
207#endif
208#undef P_MADV_PHV
209 default: break;
210 }
211
212 return scnprintf(bf, size, "%#x", behavior);
213}
214
215#define SCA_MADV_BHV syscall_arg__scnprintf_madvise_behavior
216
5cea6ff2
ACM
217static size_t syscall_arg__scnprintf_flock(char *bf, size_t size,
218 struct syscall_arg *arg)
219{
220 int printed = 0, op = arg->val;
221
222 if (op == 0)
223 return scnprintf(bf, size, "NONE");
224#define P_CMD(cmd) \
225 if ((op & LOCK_##cmd) == LOCK_##cmd) { \
226 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #cmd); \
227 op &= ~LOCK_##cmd; \
228 }
229
230 P_CMD(SH);
231 P_CMD(EX);
232 P_CMD(NB);
233 P_CMD(UN);
234 P_CMD(MAND);
235 P_CMD(RW);
236 P_CMD(READ);
237 P_CMD(WRITE);
238#undef P_OP
239
240 if (op)
241 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", op);
242
243 return printed;
244}
245
246#define SCA_FLOCK syscall_arg__scnprintf_flock
247
01533e97 248static size_t syscall_arg__scnprintf_futex_op(char *bf, size_t size, struct syscall_arg *arg)
f9da0b0c
ACM
249{
250 enum syscall_futex_args {
251 SCF_UADDR = (1 << 0),
252 SCF_OP = (1 << 1),
253 SCF_VAL = (1 << 2),
254 SCF_TIMEOUT = (1 << 3),
255 SCF_UADDR2 = (1 << 4),
256 SCF_VAL3 = (1 << 5),
257 };
01533e97 258 int op = arg->val;
f9da0b0c
ACM
259 int cmd = op & FUTEX_CMD_MASK;
260 size_t printed = 0;
261
262 switch (cmd) {
263#define P_FUTEX_OP(n) case FUTEX_##n: printed = scnprintf(bf, size, #n);
01533e97
ACM
264 P_FUTEX_OP(WAIT); arg->mask |= SCF_VAL3|SCF_UADDR2; break;
265 P_FUTEX_OP(WAKE); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
266 P_FUTEX_OP(FD); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
267 P_FUTEX_OP(REQUEUE); arg->mask |= SCF_VAL3|SCF_TIMEOUT; break;
268 P_FUTEX_OP(CMP_REQUEUE); arg->mask |= SCF_TIMEOUT; break;
269 P_FUTEX_OP(CMP_REQUEUE_PI); arg->mask |= SCF_TIMEOUT; break;
f9da0b0c 270 P_FUTEX_OP(WAKE_OP); break;
01533e97
ACM
271 P_FUTEX_OP(LOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
272 P_FUTEX_OP(UNLOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
273 P_FUTEX_OP(TRYLOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2; break;
274 P_FUTEX_OP(WAIT_BITSET); arg->mask |= SCF_UADDR2; break;
275 P_FUTEX_OP(WAKE_BITSET); arg->mask |= SCF_UADDR2; break;
f9da0b0c
ACM
276 P_FUTEX_OP(WAIT_REQUEUE_PI); break;
277 default: printed = scnprintf(bf, size, "%#x", cmd); break;
278 }
279
280 if (op & FUTEX_PRIVATE_FLAG)
281 printed += scnprintf(bf + printed, size - printed, "|PRIV");
282
283 if (op & FUTEX_CLOCK_REALTIME)
284 printed += scnprintf(bf + printed, size - printed, "|CLKRT");
285
286 return printed;
287}
288
efe6b882
ACM
289#define SCA_FUTEX_OP syscall_arg__scnprintf_futex_op
290
eac032c5
ACM
291static const char *epoll_ctl_ops[] = { [1] = "ADD", "DEL", "MOD", };
292static DEFINE_STRARRAY(epoll_ctl_ops);
293
1f115cb7
ACM
294static const char *itimers[] = { "REAL", "VIRTUAL", "PROF", };
295static DEFINE_STRARRAY(itimers);
296
efe6b882
ACM
297static const char *whences[] = { "SET", "CUR", "END",
298#ifdef SEEK_DATA
299"DATA",
300#endif
301#ifdef SEEK_HOLE
302"HOLE",
303#endif
304};
305static DEFINE_STRARRAY(whences);
f9da0b0c 306
80f587d5
ACM
307static const char *fcntl_cmds[] = {
308 "DUPFD", "GETFD", "SETFD", "GETFL", "SETFL", "GETLK", "SETLK",
309 "SETLKW", "SETOWN", "GETOWN", "SETSIG", "GETSIG", "F_GETLK64",
310 "F_SETLK64", "F_SETLKW64", "F_SETOWN_EX", "F_GETOWN_EX",
311 "F_GETOWNER_UIDS",
312};
313static DEFINE_STRARRAY(fcntl_cmds);
314
c045bf02
ACM
315static const char *rlimit_resources[] = {
316 "CPU", "FSIZE", "DATA", "STACK", "CORE", "RSS", "NPROC", "NOFILE",
317 "MEMLOCK", "AS", "LOCKS", "SIGPENDING", "MSGQUEUE", "NICE", "RTPRIO",
318 "RTTIME",
319};
320static DEFINE_STRARRAY(rlimit_resources);
321
eb5b1b14
ACM
322static const char *sighow[] = { "BLOCK", "UNBLOCK", "SETMASK", };
323static DEFINE_STRARRAY(sighow);
324
4f8c1b74
DA
325static const char *clockid[] = {
326 "REALTIME", "MONOTONIC", "PROCESS_CPUTIME_ID", "THREAD_CPUTIME_ID",
327 "MONOTONIC_RAW", "REALTIME_COARSE", "MONOTONIC_COARSE",
328};
329static DEFINE_STRARRAY(clockid);
330
e10bce81
ACM
331static const char *socket_families[] = {
332 "UNSPEC", "LOCAL", "INET", "AX25", "IPX", "APPLETALK", "NETROM",
333 "BRIDGE", "ATMPVC", "X25", "INET6", "ROSE", "DECnet", "NETBEUI",
334 "SECURITY", "KEY", "NETLINK", "PACKET", "ASH", "ECONET", "ATMSVC",
335 "RDS", "SNA", "IRDA", "PPPOX", "WANPIPE", "LLC", "IB", "CAN", "TIPC",
336 "BLUETOOTH", "IUCV", "RXRPC", "ISDN", "PHONET", "IEEE802154", "CAIF",
337 "ALG", "NFC", "VSOCK",
338};
339static DEFINE_STRARRAY(socket_families);
340
a28b24b2
ACM
341#ifndef SOCK_TYPE_MASK
342#define SOCK_TYPE_MASK 0xf
343#endif
344
345static size_t syscall_arg__scnprintf_socket_type(char *bf, size_t size,
346 struct syscall_arg *arg)
347{
348 size_t printed;
349 int type = arg->val,
350 flags = type & ~SOCK_TYPE_MASK;
351
352 type &= SOCK_TYPE_MASK;
353 /*
354 * Can't use a strarray, MIPS may override for ABI reasons.
355 */
356 switch (type) {
357#define P_SK_TYPE(n) case SOCK_##n: printed = scnprintf(bf, size, #n); break;
358 P_SK_TYPE(STREAM);
359 P_SK_TYPE(DGRAM);
360 P_SK_TYPE(RAW);
361 P_SK_TYPE(RDM);
362 P_SK_TYPE(SEQPACKET);
363 P_SK_TYPE(DCCP);
364 P_SK_TYPE(PACKET);
365#undef P_SK_TYPE
366 default:
367 printed = scnprintf(bf, size, "%#x", type);
368 }
369
370#define P_SK_FLAG(n) \
371 if (flags & SOCK_##n) { \
372 printed += scnprintf(bf + printed, size - printed, "|%s", #n); \
373 flags &= ~SOCK_##n; \
374 }
375
376 P_SK_FLAG(CLOEXEC);
377 P_SK_FLAG(NONBLOCK);
378#undef P_SK_FLAG
379
380 if (flags)
381 printed += scnprintf(bf + printed, size - printed, "|%#x", flags);
382
383 return printed;
384}
385
386#define SCA_SK_TYPE syscall_arg__scnprintf_socket_type
387
b2cc99fd
ACM
388#ifndef MSG_PROBE
389#define MSG_PROBE 0x10
390#endif
b6e8f8f4
DA
391#ifndef MSG_WAITFORONE
392#define MSG_WAITFORONE 0x10000
393#endif
b2cc99fd
ACM
394#ifndef MSG_SENDPAGE_NOTLAST
395#define MSG_SENDPAGE_NOTLAST 0x20000
396#endif
397#ifndef MSG_FASTOPEN
398#define MSG_FASTOPEN 0x20000000
399#endif
400
401static size_t syscall_arg__scnprintf_msg_flags(char *bf, size_t size,
402 struct syscall_arg *arg)
403{
404 int printed = 0, flags = arg->val;
405
406 if (flags == 0)
407 return scnprintf(bf, size, "NONE");
408#define P_MSG_FLAG(n) \
409 if (flags & MSG_##n) { \
410 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
411 flags &= ~MSG_##n; \
412 }
413
414 P_MSG_FLAG(OOB);
415 P_MSG_FLAG(PEEK);
416 P_MSG_FLAG(DONTROUTE);
417 P_MSG_FLAG(TRYHARD);
418 P_MSG_FLAG(CTRUNC);
419 P_MSG_FLAG(PROBE);
420 P_MSG_FLAG(TRUNC);
421 P_MSG_FLAG(DONTWAIT);
422 P_MSG_FLAG(EOR);
423 P_MSG_FLAG(WAITALL);
424 P_MSG_FLAG(FIN);
425 P_MSG_FLAG(SYN);
426 P_MSG_FLAG(CONFIRM);
427 P_MSG_FLAG(RST);
428 P_MSG_FLAG(ERRQUEUE);
429 P_MSG_FLAG(NOSIGNAL);
430 P_MSG_FLAG(MORE);
431 P_MSG_FLAG(WAITFORONE);
432 P_MSG_FLAG(SENDPAGE_NOTLAST);
433 P_MSG_FLAG(FASTOPEN);
434 P_MSG_FLAG(CMSG_CLOEXEC);
435#undef P_MSG_FLAG
436
437 if (flags)
438 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
439
440 return printed;
441}
442
443#define SCA_MSG_FLAGS syscall_arg__scnprintf_msg_flags
444
51108999
ACM
445static size_t syscall_arg__scnprintf_access_mode(char *bf, size_t size,
446 struct syscall_arg *arg)
447{
448 size_t printed = 0;
449 int mode = arg->val;
450
451 if (mode == F_OK) /* 0 */
452 return scnprintf(bf, size, "F");
453#define P_MODE(n) \
454 if (mode & n##_OK) { \
455 printed += scnprintf(bf + printed, size - printed, "%s", #n); \
456 mode &= ~n##_OK; \
457 }
458
459 P_MODE(R);
460 P_MODE(W);
461 P_MODE(X);
462#undef P_MODE
463
464 if (mode)
465 printed += scnprintf(bf + printed, size - printed, "|%#x", mode);
466
467 return printed;
468}
469
470#define SCA_ACCMODE syscall_arg__scnprintf_access_mode
471
be65a89a 472static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
01533e97 473 struct syscall_arg *arg)
be65a89a 474{
01533e97 475 int printed = 0, flags = arg->val;
be65a89a
ACM
476
477 if (!(flags & O_CREAT))
01533e97 478 arg->mask |= 1 << (arg->idx + 1); /* Mask the mode parm */
be65a89a
ACM
479
480 if (flags == 0)
481 return scnprintf(bf, size, "RDONLY");
482#define P_FLAG(n) \
483 if (flags & O_##n) { \
484 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
485 flags &= ~O_##n; \
486 }
487
488 P_FLAG(APPEND);
489 P_FLAG(ASYNC);
490 P_FLAG(CLOEXEC);
491 P_FLAG(CREAT);
492 P_FLAG(DIRECT);
493 P_FLAG(DIRECTORY);
494 P_FLAG(EXCL);
495 P_FLAG(LARGEFILE);
496 P_FLAG(NOATIME);
497 P_FLAG(NOCTTY);
498#ifdef O_NONBLOCK
499 P_FLAG(NONBLOCK);
500#elif O_NDELAY
501 P_FLAG(NDELAY);
502#endif
503#ifdef O_PATH
504 P_FLAG(PATH);
505#endif
506 P_FLAG(RDWR);
507#ifdef O_DSYNC
508 if ((flags & O_SYNC) == O_SYNC)
509 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", "SYNC");
510 else {
511 P_FLAG(DSYNC);
512 }
513#else
514 P_FLAG(SYNC);
515#endif
516 P_FLAG(TRUNC);
517 P_FLAG(WRONLY);
518#undef P_FLAG
519
520 if (flags)
521 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
522
523 return printed;
524}
525
526#define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags
527
49af9e93
ACM
528static size_t syscall_arg__scnprintf_eventfd_flags(char *bf, size_t size,
529 struct syscall_arg *arg)
530{
531 int printed = 0, flags = arg->val;
532
533 if (flags == 0)
534 return scnprintf(bf, size, "NONE");
535#define P_FLAG(n) \
536 if (flags & EFD_##n) { \
537 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
538 flags &= ~EFD_##n; \
539 }
540
541 P_FLAG(SEMAPHORE);
542 P_FLAG(CLOEXEC);
543 P_FLAG(NONBLOCK);
544#undef P_FLAG
545
546 if (flags)
547 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
548
549 return printed;
550}
551
552#define SCA_EFD_FLAGS syscall_arg__scnprintf_eventfd_flags
553
46cce19b
ACM
554static size_t syscall_arg__scnprintf_pipe_flags(char *bf, size_t size,
555 struct syscall_arg *arg)
556{
557 int printed = 0, flags = arg->val;
558
559#define P_FLAG(n) \
560 if (flags & O_##n) { \
561 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
562 flags &= ~O_##n; \
563 }
564
565 P_FLAG(CLOEXEC);
566 P_FLAG(NONBLOCK);
567#undef P_FLAG
568
569 if (flags)
570 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
571
572 return printed;
573}
574
575#define SCA_PIPE_FLAGS syscall_arg__scnprintf_pipe_flags
576
8bad5b0a
ACM
577static size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscall_arg *arg)
578{
579 int sig = arg->val;
580
581 switch (sig) {
582#define P_SIGNUM(n) case SIG##n: return scnprintf(bf, size, #n)
583 P_SIGNUM(HUP);
584 P_SIGNUM(INT);
585 P_SIGNUM(QUIT);
586 P_SIGNUM(ILL);
587 P_SIGNUM(TRAP);
588 P_SIGNUM(ABRT);
589 P_SIGNUM(BUS);
590 P_SIGNUM(FPE);
591 P_SIGNUM(KILL);
592 P_SIGNUM(USR1);
593 P_SIGNUM(SEGV);
594 P_SIGNUM(USR2);
595 P_SIGNUM(PIPE);
596 P_SIGNUM(ALRM);
597 P_SIGNUM(TERM);
598 P_SIGNUM(STKFLT);
599 P_SIGNUM(CHLD);
600 P_SIGNUM(CONT);
601 P_SIGNUM(STOP);
602 P_SIGNUM(TSTP);
603 P_SIGNUM(TTIN);
604 P_SIGNUM(TTOU);
605 P_SIGNUM(URG);
606 P_SIGNUM(XCPU);
607 P_SIGNUM(XFSZ);
608 P_SIGNUM(VTALRM);
609 P_SIGNUM(PROF);
610 P_SIGNUM(WINCH);
611 P_SIGNUM(IO);
612 P_SIGNUM(PWR);
613 P_SIGNUM(SYS);
614 default: break;
615 }
616
617 return scnprintf(bf, size, "%#x", sig);
618}
619
620#define SCA_SIGNUM syscall_arg__scnprintf_signum
621
453350dd
ACM
622#define STRARRAY(arg, name, array) \
623 .arg_scnprintf = { [arg] = SCA_STRARRAY, }, \
624 .arg_parm = { [arg] = &strarray__##array, }
625
514f1c67
ACM
626static struct syscall_fmt {
627 const char *name;
aec1930b 628 const char *alias;
01533e97 629 size_t (*arg_scnprintf[6])(char *bf, size_t size, struct syscall_arg *arg);
1f115cb7 630 void *arg_parm[6];
514f1c67
ACM
631 bool errmsg;
632 bool timeout;
04b34729 633 bool hexret;
514f1c67 634} syscall_fmts[] = {
51108999
ACM
635 { .name = "access", .errmsg = true,
636 .arg_scnprintf = { [1] = SCA_ACCMODE, /* mode */ }, },
aec1930b 637 { .name = "arch_prctl", .errmsg = true, .alias = "prctl", },
beccb2b5
ACM
638 { .name = "brk", .hexret = true,
639 .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, },
4f8c1b74 640 { .name = "clock_gettime", .errmsg = true, STRARRAY(0, clk_id, clockid), },
75b757ca
ACM
641 { .name = "close", .errmsg = true,
642 .arg_scnprintf = { [0] = SCA_CLOSE_FD, /* fd */ }, },
a14bb860 643 { .name = "connect", .errmsg = true, },
75b757ca
ACM
644 { .name = "dup", .errmsg = true,
645 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
646 { .name = "dup2", .errmsg = true,
647 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
648 { .name = "dup3", .errmsg = true,
649 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
453350dd 650 { .name = "epoll_ctl", .errmsg = true, STRARRAY(1, op, epoll_ctl_ops), },
49af9e93
ACM
651 { .name = "eventfd2", .errmsg = true,
652 .arg_scnprintf = { [1] = SCA_EFD_FLAGS, /* flags */ }, },
75b757ca
ACM
653 { .name = "faccessat", .errmsg = true,
654 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
655 { .name = "fadvise64", .errmsg = true,
656 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
657 { .name = "fallocate", .errmsg = true,
658 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
659 { .name = "fchdir", .errmsg = true,
660 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
661 { .name = "fchmod", .errmsg = true,
662 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
663 { .name = "fchmodat", .errmsg = true,
664 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
665 { .name = "fchown", .errmsg = true,
666 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
667 { .name = "fchownat", .errmsg = true,
668 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
669 { .name = "fcntl", .errmsg = true,
670 .arg_scnprintf = { [0] = SCA_FD, /* fd */
671 [1] = SCA_STRARRAY, /* cmd */ },
672 .arg_parm = { [1] = &strarray__fcntl_cmds, /* cmd */ }, },
673 { .name = "fdatasync", .errmsg = true,
674 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
5cea6ff2 675 { .name = "flock", .errmsg = true,
75b757ca
ACM
676 .arg_scnprintf = { [0] = SCA_FD, /* fd */
677 [1] = SCA_FLOCK, /* cmd */ }, },
678 { .name = "fsetxattr", .errmsg = true,
679 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
680 { .name = "fstat", .errmsg = true, .alias = "newfstat",
681 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
682 { .name = "fstatat", .errmsg = true, .alias = "newfstatat",
683 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
684 { .name = "fstatfs", .errmsg = true,
685 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
686 { .name = "fsync", .errmsg = true,
687 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
688 { .name = "ftruncate", .errmsg = true,
689 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
f9da0b0c
ACM
690 { .name = "futex", .errmsg = true,
691 .arg_scnprintf = { [1] = SCA_FUTEX_OP, /* op */ }, },
75b757ca
ACM
692 { .name = "futimesat", .errmsg = true,
693 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
694 { .name = "getdents", .errmsg = true,
695 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
696 { .name = "getdents64", .errmsg = true,
697 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
453350dd
ACM
698 { .name = "getitimer", .errmsg = true, STRARRAY(0, which, itimers), },
699 { .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
beccb2b5 700 { .name = "ioctl", .errmsg = true,
75b757ca
ACM
701 .arg_scnprintf = { [0] = SCA_FD, /* fd */
702 [2] = SCA_HEX, /* arg */ }, },
8bad5b0a
ACM
703 { .name = "kill", .errmsg = true,
704 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
75b757ca
ACM
705 { .name = "linkat", .errmsg = true,
706 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
707 { .name = "lseek", .errmsg = true,
708 .arg_scnprintf = { [0] = SCA_FD, /* fd */
709 [2] = SCA_STRARRAY, /* whence */ },
710 .arg_parm = { [2] = &strarray__whences, /* whence */ }, },
e5959683 711 { .name = "lstat", .errmsg = true, .alias = "newlstat", },
9e9716d1
ACM
712 { .name = "madvise", .errmsg = true,
713 .arg_scnprintf = { [0] = SCA_HEX, /* start */
714 [2] = SCA_MADV_BHV, /* behavior */ }, },
75b757ca
ACM
715 { .name = "mkdirat", .errmsg = true,
716 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
717 { .name = "mknodat", .errmsg = true,
718 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
3d903aa7
ACM
719 { .name = "mlock", .errmsg = true,
720 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
721 { .name = "mlockall", .errmsg = true,
722 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
beccb2b5 723 { .name = "mmap", .hexret = true,
ae685380 724 .arg_scnprintf = { [0] = SCA_HEX, /* addr */
941557e0
ACM
725 [2] = SCA_MMAP_PROT, /* prot */
726 [3] = SCA_MMAP_FLAGS, /* flags */ }, },
beccb2b5 727 { .name = "mprotect", .errmsg = true,
ae685380
ACM
728 .arg_scnprintf = { [0] = SCA_HEX, /* start */
729 [2] = SCA_MMAP_PROT, /* prot */ }, },
730 { .name = "mremap", .hexret = true,
731 .arg_scnprintf = { [0] = SCA_HEX, /* addr */
732 [4] = SCA_HEX, /* new_addr */ }, },
3d903aa7
ACM
733 { .name = "munlock", .errmsg = true,
734 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
beccb2b5
ACM
735 { .name = "munmap", .errmsg = true,
736 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
75b757ca
ACM
737 { .name = "name_to_handle_at", .errmsg = true,
738 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
739 { .name = "newfstatat", .errmsg = true,
740 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
be65a89a
ACM
741 { .name = "open", .errmsg = true,
742 .arg_scnprintf = { [1] = SCA_OPEN_FLAGS, /* flags */ }, },
31cd3855 743 { .name = "open_by_handle_at", .errmsg = true,
75b757ca
ACM
744 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
745 [2] = SCA_OPEN_FLAGS, /* flags */ }, },
31cd3855 746 { .name = "openat", .errmsg = true,
75b757ca
ACM
747 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
748 [2] = SCA_OPEN_FLAGS, /* flags */ }, },
46cce19b
ACM
749 { .name = "pipe2", .errmsg = true,
750 .arg_scnprintf = { [1] = SCA_PIPE_FLAGS, /* flags */ }, },
aec1930b
ACM
751 { .name = "poll", .errmsg = true, .timeout = true, },
752 { .name = "ppoll", .errmsg = true, .timeout = true, },
75b757ca
ACM
753 { .name = "pread", .errmsg = true, .alias = "pread64",
754 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
755 { .name = "preadv", .errmsg = true, .alias = "pread",
756 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
453350dd 757 { .name = "prlimit64", .errmsg = true, STRARRAY(1, resource, rlimit_resources), },
75b757ca
ACM
758 { .name = "pwrite", .errmsg = true, .alias = "pwrite64",
759 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
760 { .name = "pwritev", .errmsg = true,
761 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
762 { .name = "read", .errmsg = true,
763 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
764 { .name = "readlinkat", .errmsg = true,
765 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
766 { .name = "readv", .errmsg = true,
767 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
b2cc99fd
ACM
768 { .name = "recvfrom", .errmsg = true,
769 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
770 { .name = "recvmmsg", .errmsg = true,
771 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
772 { .name = "recvmsg", .errmsg = true,
773 .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, },
75b757ca
ACM
774 { .name = "renameat", .errmsg = true,
775 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
8bad5b0a
ACM
776 { .name = "rt_sigaction", .errmsg = true,
777 .arg_scnprintf = { [0] = SCA_SIGNUM, /* sig */ }, },
453350dd 778 { .name = "rt_sigprocmask", .errmsg = true, STRARRAY(0, how, sighow), },
8bad5b0a
ACM
779 { .name = "rt_sigqueueinfo", .errmsg = true,
780 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
781 { .name = "rt_tgsigqueueinfo", .errmsg = true,
782 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
aec1930b 783 { .name = "select", .errmsg = true, .timeout = true, },
b2cc99fd
ACM
784 { .name = "sendmmsg", .errmsg = true,
785 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
786 { .name = "sendmsg", .errmsg = true,
787 .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, },
788 { .name = "sendto", .errmsg = true,
789 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
453350dd
ACM
790 { .name = "setitimer", .errmsg = true, STRARRAY(0, which, itimers), },
791 { .name = "setrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
75b757ca
ACM
792 { .name = "shutdown", .errmsg = true,
793 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
e10bce81 794 { .name = "socket", .errmsg = true,
a28b24b2
ACM
795 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
796 [1] = SCA_SK_TYPE, /* type */ },
07120aa5
ACM
797 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, },
798 { .name = "socketpair", .errmsg = true,
799 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
800 [1] = SCA_SK_TYPE, /* type */ },
e10bce81 801 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, },
aec1930b 802 { .name = "stat", .errmsg = true, .alias = "newstat", },
75b757ca
ACM
803 { .name = "symlinkat", .errmsg = true,
804 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
8bad5b0a
ACM
805 { .name = "tgkill", .errmsg = true,
806 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
807 { .name = "tkill", .errmsg = true,
808 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
e5959683 809 { .name = "uname", .errmsg = true, .alias = "newuname", },
75b757ca
ACM
810 { .name = "unlinkat", .errmsg = true,
811 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
812 { .name = "utimensat", .errmsg = true,
813 .arg_scnprintf = { [0] = SCA_FDAT, /* dirfd */ }, },
814 { .name = "write", .errmsg = true,
815 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
816 { .name = "writev", .errmsg = true,
817 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
514f1c67
ACM
818};
819
820static int syscall_fmt__cmp(const void *name, const void *fmtp)
821{
822 const struct syscall_fmt *fmt = fmtp;
823 return strcmp(name, fmt->name);
824}
825
826static struct syscall_fmt *syscall_fmt__find(const char *name)
827{
828 const int nmemb = ARRAY_SIZE(syscall_fmts);
829 return bsearch(name, syscall_fmts, nmemb, sizeof(struct syscall_fmt), syscall_fmt__cmp);
830}
831
832struct syscall {
833 struct event_format *tp_format;
834 const char *name;
2ae3a312 835 bool filtered;
514f1c67 836 struct syscall_fmt *fmt;
01533e97 837 size_t (**arg_scnprintf)(char *bf, size_t size, struct syscall_arg *arg);
1f115cb7 838 void **arg_parm;
514f1c67
ACM
839};
840
60c907ab
ACM
841static size_t fprintf_duration(unsigned long t, FILE *fp)
842{
843 double duration = (double)t / NSEC_PER_MSEC;
844 size_t printed = fprintf(fp, "(");
845
846 if (duration >= 1.0)
847 printed += color_fprintf(fp, PERF_COLOR_RED, "%6.3f ms", duration);
848 else if (duration >= 0.01)
849 printed += color_fprintf(fp, PERF_COLOR_YELLOW, "%6.3f ms", duration);
850 else
851 printed += color_fprintf(fp, PERF_COLOR_NORMAL, "%6.3f ms", duration);
c24ff998 852 return printed + fprintf(fp, "): ");
60c907ab
ACM
853}
854
752fde44
ACM
855struct thread_trace {
856 u64 entry_time;
857 u64 exit_time;
858 bool entry_pending;
efd5745e 859 unsigned long nr_events;
752fde44 860 char *entry_str;
1302d88e 861 double runtime_ms;
75b757ca
ACM
862 struct {
863 int max;
864 char **table;
865 } paths;
752fde44
ACM
866};
867
868static struct thread_trace *thread_trace__new(void)
869{
75b757ca
ACM
870 struct thread_trace *ttrace = zalloc(sizeof(struct thread_trace));
871
872 if (ttrace)
873 ttrace->paths.max = -1;
874
875 return ttrace;
752fde44
ACM
876}
877
c24ff998 878static struct thread_trace *thread__trace(struct thread *thread, FILE *fp)
752fde44 879{
efd5745e
ACM
880 struct thread_trace *ttrace;
881
752fde44
ACM
882 if (thread == NULL)
883 goto fail;
884
885 if (thread->priv == NULL)
886 thread->priv = thread_trace__new();
efd5745e 887
752fde44
ACM
888 if (thread->priv == NULL)
889 goto fail;
890
efd5745e
ACM
891 ttrace = thread->priv;
892 ++ttrace->nr_events;
893
894 return ttrace;
752fde44 895fail:
c24ff998 896 color_fprintf(fp, PERF_COLOR_RED,
752fde44
ACM
897 "WARNING: not enough memory, dropping samples!\n");
898 return NULL;
899}
900
514f1c67 901struct trace {
c24ff998 902 struct perf_tool tool;
514f1c67
ACM
903 int audit_machine;
904 struct {
905 int max;
906 struct syscall *table;
907 } syscalls;
908 struct perf_record_opts opts;
752fde44
ACM
909 struct machine host;
910 u64 base_time;
4bb09192 911 bool full_time;
c24ff998 912 FILE *output;
efd5745e 913 unsigned long nr_events;
b059efdf
ACM
914 struct strlist *ev_qualifier;
915 bool not_ev_qualifier;
75b757ca 916 bool live;
bdc89661
DA
917 struct intlist *tid_list;
918 struct intlist *pid_list;
1302d88e 919 bool sched;
752fde44 920 bool multiple_threads;
50c95cbd 921 bool show_comm;
ae9ed035 922 double duration_filter;
1302d88e 923 double runtime_ms;
514f1c67
ACM
924};
925
75b757ca
ACM
926static int thread__read_fd_path(struct thread *thread, int fd)
927{
928 struct thread_trace *ttrace = thread->priv;
929 char linkname[PATH_MAX], pathname[PATH_MAX];
930 struct stat st;
931 int ret;
932
933 if (thread->pid_ == thread->tid) {
934 scnprintf(linkname, sizeof(linkname),
935 "/proc/%d/fd/%d", thread->pid_, fd);
936 } else {
937 scnprintf(linkname, sizeof(linkname),
938 "/proc/%d/task/%d/fd/%d", thread->pid_, thread->tid, fd);
939 }
940
941 if (lstat(linkname, &st) < 0 || st.st_size + 1 > (off_t)sizeof(pathname))
942 return -1;
943
944 ret = readlink(linkname, pathname, sizeof(pathname));
945
946 if (ret < 0 || ret > st.st_size)
947 return -1;
948
949 pathname[ret] = '\0';
950
951 if (fd > ttrace->paths.max) {
952 char **npath = realloc(ttrace->paths.table, (fd + 1) * sizeof(char *));
953
954 if (npath == NULL)
955 return -1;
956
957 if (ttrace->paths.max != -1) {
958 memset(npath + ttrace->paths.max + 1, 0,
959 (fd - ttrace->paths.max) * sizeof(char *));
960 } else {
961 memset(npath, 0, (fd + 1) * sizeof(char *));
962 }
963
964 ttrace->paths.table = npath;
965 ttrace->paths.max = fd;
966 }
967
968 ttrace->paths.table[fd] = strdup(pathname);
969
970 return ttrace->paths.table[fd] != NULL ? 0 : -1;
971}
972
973static const char *thread__fd_path(struct thread *thread, int fd, bool live)
974{
975 struct thread_trace *ttrace = thread->priv;
976
977 if (ttrace == NULL)
978 return NULL;
979
980 if (fd < 0)
981 return NULL;
982
983 if ((fd > ttrace->paths.max || ttrace->paths.table[fd] == NULL) &&
984 (!live || thread__read_fd_path(thread, fd)))
985 return NULL;
986
987 return ttrace->paths.table[fd];
988}
989
990static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
991 struct syscall_arg *arg)
992{
993 int fd = arg->val;
994 size_t printed = scnprintf(bf, size, "%d", fd);
995 const char *path = thread__fd_path(arg->thread, fd, arg->trace->live);
996
997 if (path)
998 printed += scnprintf(bf + printed, size - printed, "<%s>", path);
999
1000 return printed;
1001}
1002
1003static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
1004 struct syscall_arg *arg)
1005{
1006 int fd = arg->val;
1007 size_t printed = syscall_arg__scnprintf_fd(bf, size, arg);
1008 struct thread_trace *ttrace = arg->thread->priv;
1009
1010 if (ttrace && fd >= 0 && fd <= ttrace->paths.max) {
1011 free(ttrace->paths.table[fd]);
1012 ttrace->paths.table[fd] = NULL;
1013 }
1014
1015 return printed;
1016}
1017
ae9ed035
ACM
1018static bool trace__filter_duration(struct trace *trace, double t)
1019{
1020 return t < (trace->duration_filter * NSEC_PER_MSEC);
1021}
1022
752fde44
ACM
1023static size_t trace__fprintf_tstamp(struct trace *trace, u64 tstamp, FILE *fp)
1024{
1025 double ts = (double)(tstamp - trace->base_time) / NSEC_PER_MSEC;
1026
60c907ab 1027 return fprintf(fp, "%10.3f ", ts);
752fde44
ACM
1028}
1029
f15eb531
NK
1030static bool done = false;
1031
1032static void sig_handler(int sig __maybe_unused)
1033{
1034 done = true;
1035}
1036
752fde44 1037static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thread,
60c907ab 1038 u64 duration, u64 tstamp, FILE *fp)
752fde44
ACM
1039{
1040 size_t printed = trace__fprintf_tstamp(trace, tstamp, fp);
60c907ab 1041 printed += fprintf_duration(duration, fp);
752fde44 1042
50c95cbd
ACM
1043 if (trace->multiple_threads) {
1044 if (trace->show_comm)
1045 printed += fprintf(fp, "%.14s/", thread->comm);
38051234 1046 printed += fprintf(fp, "%d ", thread->tid);
50c95cbd 1047 }
752fde44
ACM
1048
1049 return printed;
1050}
1051
c24ff998
ACM
1052static int trace__process_event(struct trace *trace, struct machine *machine,
1053 union perf_event *event)
752fde44
ACM
1054{
1055 int ret = 0;
1056
1057 switch (event->header.type) {
1058 case PERF_RECORD_LOST:
c24ff998 1059 color_fprintf(trace->output, PERF_COLOR_RED,
752fde44
ACM
1060 "LOST %" PRIu64 " events!\n", event->lost.lost);
1061 ret = machine__process_lost_event(machine, event);
1062 default:
1063 ret = machine__process_event(machine, event);
1064 break;
1065 }
1066
1067 return ret;
1068}
1069
c24ff998 1070static int trace__tool_process(struct perf_tool *tool,
752fde44
ACM
1071 union perf_event *event,
1072 struct perf_sample *sample __maybe_unused,
1073 struct machine *machine)
1074{
c24ff998
ACM
1075 struct trace *trace = container_of(tool, struct trace, tool);
1076 return trace__process_event(trace, machine, event);
752fde44
ACM
1077}
1078
1079static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
1080{
1081 int err = symbol__init();
1082
1083 if (err)
1084 return err;
1085
1086 machine__init(&trace->host, "", HOST_KERNEL_ID);
1087 machine__create_kernel_maps(&trace->host);
1088
1089 if (perf_target__has_task(&trace->opts.target)) {
c24ff998 1090 err = perf_event__synthesize_thread_map(&trace->tool, evlist->threads,
752fde44
ACM
1091 trace__tool_process,
1092 &trace->host);
1093 } else {
c24ff998 1094 err = perf_event__synthesize_threads(&trace->tool, trace__tool_process,
752fde44
ACM
1095 &trace->host);
1096 }
1097
1098 if (err)
1099 symbol__exit();
1100
1101 return err;
1102}
1103
13d4ff3e
ACM
1104static int syscall__set_arg_fmts(struct syscall *sc)
1105{
1106 struct format_field *field;
1107 int idx = 0;
1108
1109 sc->arg_scnprintf = calloc(sc->tp_format->format.nr_fields - 1, sizeof(void *));
1110 if (sc->arg_scnprintf == NULL)
1111 return -1;
1112
1f115cb7
ACM
1113 if (sc->fmt)
1114 sc->arg_parm = sc->fmt->arg_parm;
1115
13d4ff3e 1116 for (field = sc->tp_format->format.fields->next; field; field = field->next) {
beccb2b5
ACM
1117 if (sc->fmt && sc->fmt->arg_scnprintf[idx])
1118 sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx];
1119 else if (field->flags & FIELD_IS_POINTER)
13d4ff3e
ACM
1120 sc->arg_scnprintf[idx] = syscall_arg__scnprintf_hex;
1121 ++idx;
1122 }
1123
1124 return 0;
1125}
1126
514f1c67
ACM
1127static int trace__read_syscall_info(struct trace *trace, int id)
1128{
1129 char tp_name[128];
1130 struct syscall *sc;
3a531260
ACM
1131 const char *name = audit_syscall_to_name(id, trace->audit_machine);
1132
1133 if (name == NULL)
1134 return -1;
514f1c67
ACM
1135
1136 if (id > trace->syscalls.max) {
1137 struct syscall *nsyscalls = realloc(trace->syscalls.table, (id + 1) * sizeof(*sc));
1138
1139 if (nsyscalls == NULL)
1140 return -1;
1141
1142 if (trace->syscalls.max != -1) {
1143 memset(nsyscalls + trace->syscalls.max + 1, 0,
1144 (id - trace->syscalls.max) * sizeof(*sc));
1145 } else {
1146 memset(nsyscalls, 0, (id + 1) * sizeof(*sc));
1147 }
1148
1149 trace->syscalls.table = nsyscalls;
1150 trace->syscalls.max = id;
1151 }
1152
1153 sc = trace->syscalls.table + id;
3a531260 1154 sc->name = name;
2ae3a312 1155
b059efdf
ACM
1156 if (trace->ev_qualifier) {
1157 bool in = strlist__find(trace->ev_qualifier, name) != NULL;
1158
1159 if (!(in ^ trace->not_ev_qualifier)) {
1160 sc->filtered = true;
1161 /*
1162 * No need to do read tracepoint information since this will be
1163 * filtered out.
1164 */
1165 return 0;
1166 }
2ae3a312
ACM
1167 }
1168
3a531260 1169 sc->fmt = syscall_fmt__find(sc->name);
514f1c67 1170
aec1930b 1171 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name);
514f1c67 1172 sc->tp_format = event_format__new("syscalls", tp_name);
aec1930b
ACM
1173
1174 if (sc->tp_format == NULL && sc->fmt && sc->fmt->alias) {
1175 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->fmt->alias);
1176 sc->tp_format = event_format__new("syscalls", tp_name);
1177 }
514f1c67 1178
13d4ff3e
ACM
1179 if (sc->tp_format == NULL)
1180 return -1;
1181
1182 return syscall__set_arg_fmts(sc);
514f1c67
ACM
1183}
1184
752fde44 1185static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
75b757ca
ACM
1186 unsigned long *args, struct trace *trace,
1187 struct thread *thread)
514f1c67 1188{
514f1c67
ACM
1189 size_t printed = 0;
1190
1191 if (sc->tp_format != NULL) {
1192 struct format_field *field;
01533e97
ACM
1193 u8 bit = 1;
1194 struct syscall_arg arg = {
75b757ca
ACM
1195 .idx = 0,
1196 .mask = 0,
1197 .trace = trace,
1198 .thread = thread,
01533e97 1199 };
6e7eeb51
ACM
1200
1201 for (field = sc->tp_format->format.fields->next; field;
01533e97
ACM
1202 field = field->next, ++arg.idx, bit <<= 1) {
1203 if (arg.mask & bit)
6e7eeb51 1204 continue;
4aa58232
ACM
1205 /*
1206 * Suppress this argument if its value is zero and
1207 * and we don't have a string associated in an
1208 * strarray for it.
1209 */
1210 if (args[arg.idx] == 0 &&
1211 !(sc->arg_scnprintf &&
1212 sc->arg_scnprintf[arg.idx] == SCA_STRARRAY &&
1213 sc->arg_parm[arg.idx]))
22ae5cf1
ACM
1214 continue;
1215
752fde44 1216 printed += scnprintf(bf + printed, size - printed,
13d4ff3e 1217 "%s%s: ", printed ? ", " : "", field->name);
01533e97
ACM
1218 if (sc->arg_scnprintf && sc->arg_scnprintf[arg.idx]) {
1219 arg.val = args[arg.idx];
1f115cb7
ACM
1220 if (sc->arg_parm)
1221 arg.parm = sc->arg_parm[arg.idx];
01533e97
ACM
1222 printed += sc->arg_scnprintf[arg.idx](bf + printed,
1223 size - printed, &arg);
6e7eeb51 1224 } else {
13d4ff3e 1225 printed += scnprintf(bf + printed, size - printed,
01533e97 1226 "%ld", args[arg.idx]);
6e7eeb51 1227 }
514f1c67
ACM
1228 }
1229 } else {
01533e97
ACM
1230 int i = 0;
1231
514f1c67 1232 while (i < 6) {
752fde44
ACM
1233 printed += scnprintf(bf + printed, size - printed,
1234 "%sarg%d: %ld",
1235 printed ? ", " : "", i, args[i]);
514f1c67
ACM
1236 ++i;
1237 }
1238 }
1239
1240 return printed;
1241}
1242
ba3d7dee
ACM
1243typedef int (*tracepoint_handler)(struct trace *trace, struct perf_evsel *evsel,
1244 struct perf_sample *sample);
1245
1246static struct syscall *trace__syscall_info(struct trace *trace,
1247 struct perf_evsel *evsel,
1248 struct perf_sample *sample)
1249{
1250 int id = perf_evsel__intval(evsel, sample, "id");
1251
1252 if (id < 0) {
adaa18bf
ACM
1253
1254 /*
1255 * XXX: Noticed on x86_64, reproduced as far back as 3.0.36, haven't tried
1256 * before that, leaving at a higher verbosity level till that is
1257 * explained. Reproduced with plain ftrace with:
1258 *
1259 * echo 1 > /t/events/raw_syscalls/sys_exit/enable
1260 * grep "NR -1 " /t/trace_pipe
1261 *
1262 * After generating some load on the machine.
1263 */
1264 if (verbose > 1) {
1265 static u64 n;
1266 fprintf(trace->output, "Invalid syscall %d id, skipping (%s, %" PRIu64 ") ...\n",
1267 id, perf_evsel__name(evsel), ++n);
1268 }
ba3d7dee
ACM
1269 return NULL;
1270 }
1271
1272 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL) &&
1273 trace__read_syscall_info(trace, id))
1274 goto out_cant_read;
1275
1276 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL))
1277 goto out_cant_read;
1278
1279 return &trace->syscalls.table[id];
1280
1281out_cant_read:
7c304ee0
ACM
1282 if (verbose) {
1283 fprintf(trace->output, "Problems reading syscall %d", id);
1284 if (id <= trace->syscalls.max && trace->syscalls.table[id].name != NULL)
1285 fprintf(trace->output, "(%s)", trace->syscalls.table[id].name);
1286 fputs(" information\n", trace->output);
1287 }
ba3d7dee
ACM
1288 return NULL;
1289}
1290
1291static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
1292 struct perf_sample *sample)
1293{
752fde44 1294 char *msg;
ba3d7dee 1295 void *args;
752fde44 1296 size_t printed = 0;
2ae3a312 1297 struct thread *thread;
ba3d7dee 1298 struct syscall *sc = trace__syscall_info(trace, evsel, sample);
2ae3a312
ACM
1299 struct thread_trace *ttrace;
1300
1301 if (sc == NULL)
1302 return -1;
ba3d7dee 1303
2ae3a312
ACM
1304 if (sc->filtered)
1305 return 0;
1306
314add6b
AH
1307 thread = machine__findnew_thread(&trace->host, sample->pid,
1308 sample->tid);
c24ff998 1309 ttrace = thread__trace(thread, trace->output);
2ae3a312 1310 if (ttrace == NULL)
ba3d7dee
ACM
1311 return -1;
1312
1313 args = perf_evsel__rawptr(evsel, sample, "args");
1314 if (args == NULL) {
c24ff998 1315 fprintf(trace->output, "Problems reading syscall arguments\n");
ba3d7dee
ACM
1316 return -1;
1317 }
1318
752fde44
ACM
1319 ttrace = thread->priv;
1320
1321 if (ttrace->entry_str == NULL) {
1322 ttrace->entry_str = malloc(1024);
1323 if (!ttrace->entry_str)
1324 return -1;
1325 }
1326
1327 ttrace->entry_time = sample->time;
1328 msg = ttrace->entry_str;
1329 printed += scnprintf(msg + printed, 1024 - printed, "%s(", sc->name);
1330
75b757ca
ACM
1331 printed += syscall__scnprintf_args(sc, msg + printed, 1024 - printed,
1332 args, trace, thread);
752fde44
ACM
1333
1334 if (!strcmp(sc->name, "exit_group") || !strcmp(sc->name, "exit")) {
ae9ed035 1335 if (!trace->duration_filter) {
c24ff998
ACM
1336 trace__fprintf_entry_head(trace, thread, 1, sample->time, trace->output);
1337 fprintf(trace->output, "%-70s\n", ttrace->entry_str);
ae9ed035 1338 }
752fde44
ACM
1339 } else
1340 ttrace->entry_pending = true;
ba3d7dee
ACM
1341
1342 return 0;
1343}
1344
1345static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
1346 struct perf_sample *sample)
1347{
1348 int ret;
60c907ab 1349 u64 duration = 0;
2ae3a312 1350 struct thread *thread;
ba3d7dee 1351 struct syscall *sc = trace__syscall_info(trace, evsel, sample);
2ae3a312
ACM
1352 struct thread_trace *ttrace;
1353
1354 if (sc == NULL)
1355 return -1;
ba3d7dee 1356
2ae3a312
ACM
1357 if (sc->filtered)
1358 return 0;
1359
314add6b
AH
1360 thread = machine__findnew_thread(&trace->host, sample->pid,
1361 sample->tid);
c24ff998 1362 ttrace = thread__trace(thread, trace->output);
2ae3a312 1363 if (ttrace == NULL)
ba3d7dee
ACM
1364 return -1;
1365
1366 ret = perf_evsel__intval(evsel, sample, "ret");
1367
752fde44
ACM
1368 ttrace = thread->priv;
1369
1370 ttrace->exit_time = sample->time;
1371
ae9ed035 1372 if (ttrace->entry_time) {
60c907ab 1373 duration = sample->time - ttrace->entry_time;
ae9ed035
ACM
1374 if (trace__filter_duration(trace, duration))
1375 goto out;
1376 } else if (trace->duration_filter)
1377 goto out;
60c907ab 1378
c24ff998 1379 trace__fprintf_entry_head(trace, thread, duration, sample->time, trace->output);
752fde44
ACM
1380
1381 if (ttrace->entry_pending) {
c24ff998 1382 fprintf(trace->output, "%-70s", ttrace->entry_str);
752fde44 1383 } else {
c24ff998
ACM
1384 fprintf(trace->output, " ... [");
1385 color_fprintf(trace->output, PERF_COLOR_YELLOW, "continued");
1386 fprintf(trace->output, "]: %s()", sc->name);
752fde44
ACM
1387 }
1388
da3c9a44
ACM
1389 if (sc->fmt == NULL) {
1390signed_print:
1391 fprintf(trace->output, ") = %d", ret);
1392 } else if (ret < 0 && sc->fmt->errmsg) {
ba3d7dee
ACM
1393 char bf[256];
1394 const char *emsg = strerror_r(-ret, bf, sizeof(bf)),
1395 *e = audit_errno_to_name(-ret);
1396
c24ff998 1397 fprintf(trace->output, ") = -1 %s %s", e, emsg);
da3c9a44 1398 } else if (ret == 0 && sc->fmt->timeout)
c24ff998 1399 fprintf(trace->output, ") = 0 Timeout");
04b34729
ACM
1400 else if (sc->fmt->hexret)
1401 fprintf(trace->output, ") = %#x", ret);
ba3d7dee 1402 else
da3c9a44 1403 goto signed_print;
ba3d7dee 1404
c24ff998 1405 fputc('\n', trace->output);
ae9ed035 1406out:
752fde44
ACM
1407 ttrace->entry_pending = false;
1408
ba3d7dee
ACM
1409 return 0;
1410}
1411
1302d88e
ACM
1412static int trace__sched_stat_runtime(struct trace *trace, struct perf_evsel *evsel,
1413 struct perf_sample *sample)
1414{
1415 u64 runtime = perf_evsel__intval(evsel, sample, "runtime");
1416 double runtime_ms = (double)runtime / NSEC_PER_MSEC;
314add6b
AH
1417 struct thread *thread = machine__findnew_thread(&trace->host,
1418 sample->pid,
1419 sample->tid);
c24ff998 1420 struct thread_trace *ttrace = thread__trace(thread, trace->output);
1302d88e
ACM
1421
1422 if (ttrace == NULL)
1423 goto out_dump;
1424
1425 ttrace->runtime_ms += runtime_ms;
1426 trace->runtime_ms += runtime_ms;
1427 return 0;
1428
1429out_dump:
c24ff998 1430 fprintf(trace->output, "%s: comm=%s,pid=%u,runtime=%" PRIu64 ",vruntime=%" PRIu64 ")\n",
1302d88e
ACM
1431 evsel->name,
1432 perf_evsel__strval(evsel, sample, "comm"),
1433 (pid_t)perf_evsel__intval(evsel, sample, "pid"),
1434 runtime,
1435 perf_evsel__intval(evsel, sample, "vruntime"));
1436 return 0;
1437}
1438
bdc89661
DA
1439static bool skip_sample(struct trace *trace, struct perf_sample *sample)
1440{
1441 if ((trace->pid_list && intlist__find(trace->pid_list, sample->pid)) ||
1442 (trace->tid_list && intlist__find(trace->tid_list, sample->tid)))
1443 return false;
1444
1445 if (trace->pid_list || trace->tid_list)
1446 return true;
1447
1448 return false;
1449}
1450
6810fc91
DA
1451static int trace__process_sample(struct perf_tool *tool,
1452 union perf_event *event __maybe_unused,
1453 struct perf_sample *sample,
1454 struct perf_evsel *evsel,
1455 struct machine *machine __maybe_unused)
1456{
1457 struct trace *trace = container_of(tool, struct trace, tool);
1458 int err = 0;
1459
1460 tracepoint_handler handler = evsel->handler.func;
1461
bdc89661
DA
1462 if (skip_sample(trace, sample))
1463 return 0;
1464
4bb09192 1465 if (!trace->full_time && trace->base_time == 0)
6810fc91
DA
1466 trace->base_time = sample->time;
1467
1468 if (handler)
1469 handler(trace, evsel, sample);
1470
1471 return err;
1472}
1473
1474static bool
1475perf_session__has_tp(struct perf_session *session, const char *name)
1476{
1477 struct perf_evsel *evsel;
1478
1479 evsel = perf_evlist__find_tracepoint_by_name(session->evlist, name);
1480
1481 return evsel != NULL;
1482}
1483
bdc89661
DA
1484static int parse_target_str(struct trace *trace)
1485{
1486 if (trace->opts.target.pid) {
1487 trace->pid_list = intlist__new(trace->opts.target.pid);
1488 if (trace->pid_list == NULL) {
1489 pr_err("Error parsing process id string\n");
1490 return -EINVAL;
1491 }
1492 }
1493
1494 if (trace->opts.target.tid) {
1495 trace->tid_list = intlist__new(trace->opts.target.tid);
1496 if (trace->tid_list == NULL) {
1497 pr_err("Error parsing thread id string\n");
1498 return -EINVAL;
1499 }
1500 }
1501
1502 return 0;
1503}
1504
f15eb531 1505static int trace__run(struct trace *trace, int argc, const char **argv)
514f1c67 1506{
334fe7a3 1507 struct perf_evlist *evlist = perf_evlist__new();
ba3d7dee 1508 struct perf_evsel *evsel;
efd5745e
ACM
1509 int err = -1, i;
1510 unsigned long before;
f15eb531 1511 const bool forks = argc > 0;
514f1c67 1512
75b757ca
ACM
1513 trace->live = true;
1514
514f1c67 1515 if (evlist == NULL) {
c24ff998 1516 fprintf(trace->output, "Not enough memory to run!\n");
514f1c67
ACM
1517 goto out;
1518 }
1519
39876e7d
ACM
1520 if (perf_evlist__add_newtp(evlist, "raw_syscalls", "sys_enter", trace__sys_enter) ||
1521 perf_evlist__add_newtp(evlist, "raw_syscalls", "sys_exit", trace__sys_exit)) {
c24ff998 1522 fprintf(trace->output, "Couldn't read the raw_syscalls tracepoints information!\n");
514f1c67
ACM
1523 goto out_delete_evlist;
1524 }
1525
1302d88e
ACM
1526 if (trace->sched &&
1527 perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime",
1528 trace__sched_stat_runtime)) {
c24ff998 1529 fprintf(trace->output, "Couldn't read the sched_stat_runtime tracepoint information!\n");
1302d88e
ACM
1530 goto out_delete_evlist;
1531 }
1532
514f1c67
ACM
1533 err = perf_evlist__create_maps(evlist, &trace->opts.target);
1534 if (err < 0) {
c24ff998 1535 fprintf(trace->output, "Problems parsing the target to trace, check your options!\n");
514f1c67
ACM
1536 goto out_delete_evlist;
1537 }
1538
752fde44
ACM
1539 err = trace__symbols_init(trace, evlist);
1540 if (err < 0) {
c24ff998 1541 fprintf(trace->output, "Problems initializing symbol libraries!\n");
3beb0861 1542 goto out_delete_maps;
752fde44
ACM
1543 }
1544
f77a9518 1545 perf_evlist__config(evlist, &trace->opts);
514f1c67 1546
f15eb531
NK
1547 signal(SIGCHLD, sig_handler);
1548 signal(SIGINT, sig_handler);
1549
1550 if (forks) {
6ef73ec4 1551 err = perf_evlist__prepare_workload(evlist, &trace->opts.target,
55e162ea 1552 argv, false, false);
f15eb531 1553 if (err < 0) {
c24ff998 1554 fprintf(trace->output, "Couldn't run the workload!\n");
3beb0861 1555 goto out_delete_maps;
f15eb531
NK
1556 }
1557 }
1558
514f1c67
ACM
1559 err = perf_evlist__open(evlist);
1560 if (err < 0) {
c24ff998 1561 fprintf(trace->output, "Couldn't create the events: %s\n", strerror(errno));
3beb0861 1562 goto out_delete_maps;
514f1c67
ACM
1563 }
1564
1565 err = perf_evlist__mmap(evlist, UINT_MAX, false);
1566 if (err < 0) {
c24ff998 1567 fprintf(trace->output, "Couldn't mmap the events: %s\n", strerror(errno));
3beb0861 1568 goto out_close_evlist;
514f1c67
ACM
1569 }
1570
1571 perf_evlist__enable(evlist);
f15eb531
NK
1572
1573 if (forks)
1574 perf_evlist__start_workload(evlist);
1575
752fde44 1576 trace->multiple_threads = evlist->threads->map[0] == -1 || evlist->threads->nr > 1;
514f1c67 1577again:
efd5745e 1578 before = trace->nr_events;
514f1c67
ACM
1579
1580 for (i = 0; i < evlist->nr_mmaps; i++) {
1581 union perf_event *event;
1582
1583 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
1584 const u32 type = event->header.type;
ba3d7dee 1585 tracepoint_handler handler;
514f1c67 1586 struct perf_sample sample;
514f1c67 1587
efd5745e 1588 ++trace->nr_events;
514f1c67 1589
514f1c67
ACM
1590 err = perf_evlist__parse_sample(evlist, event, &sample);
1591 if (err) {
c24ff998 1592 fprintf(trace->output, "Can't parse sample, err = %d, skipping...\n", err);
514f1c67
ACM
1593 continue;
1594 }
1595
4bb09192 1596 if (!trace->full_time && trace->base_time == 0)
752fde44
ACM
1597 trace->base_time = sample.time;
1598
1599 if (type != PERF_RECORD_SAMPLE) {
c24ff998 1600 trace__process_event(trace, &trace->host, event);
752fde44
ACM
1601 continue;
1602 }
1603
514f1c67
ACM
1604 evsel = perf_evlist__id2evsel(evlist, sample.id);
1605 if (evsel == NULL) {
c24ff998 1606 fprintf(trace->output, "Unknown tp ID %" PRIu64 ", skipping...\n", sample.id);
514f1c67
ACM
1607 continue;
1608 }
1609
fc551f8d 1610 if (sample.raw_data == NULL) {
c24ff998 1611 fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n",
fc551f8d
ACM
1612 perf_evsel__name(evsel), sample.tid,
1613 sample.cpu, sample.raw_size);
1614 continue;
1615 }
1616
ba3d7dee
ACM
1617 handler = evsel->handler.func;
1618 handler(trace, evsel, &sample);
20c5f10e
ACM
1619
1620 if (done)
1621 goto out_unmap_evlist;
514f1c67
ACM
1622 }
1623 }
1624
efd5745e 1625 if (trace->nr_events == before) {
f15eb531 1626 if (done)
3beb0861 1627 goto out_unmap_evlist;
f15eb531 1628
514f1c67 1629 poll(evlist->pollfd, evlist->nr_fds, -1);
f15eb531
NK
1630 }
1631
1632 if (done)
1633 perf_evlist__disable(evlist);
514f1c67
ACM
1634
1635 goto again;
1636
3beb0861
NK
1637out_unmap_evlist:
1638 perf_evlist__munmap(evlist);
1639out_close_evlist:
1640 perf_evlist__close(evlist);
1641out_delete_maps:
1642 perf_evlist__delete_maps(evlist);
514f1c67
ACM
1643out_delete_evlist:
1644 perf_evlist__delete(evlist);
1645out:
75b757ca 1646 trace->live = false;
514f1c67
ACM
1647 return err;
1648}
1649
6810fc91
DA
1650static int trace__replay(struct trace *trace)
1651{
1652 const struct perf_evsel_str_handler handlers[] = {
1653 { "raw_syscalls:sys_enter", trace__sys_enter, },
1654 { "raw_syscalls:sys_exit", trace__sys_exit, },
1655 };
1656
1657 struct perf_session *session;
1658 int err = -1;
1659
1660 trace->tool.sample = trace__process_sample;
1661 trace->tool.mmap = perf_event__process_mmap;
384c671e 1662 trace->tool.mmap2 = perf_event__process_mmap2;
6810fc91
DA
1663 trace->tool.comm = perf_event__process_comm;
1664 trace->tool.exit = perf_event__process_exit;
1665 trace->tool.fork = perf_event__process_fork;
1666 trace->tool.attr = perf_event__process_attr;
1667 trace->tool.tracing_data = perf_event__process_tracing_data;
1668 trace->tool.build_id = perf_event__process_build_id;
1669
1670 trace->tool.ordered_samples = true;
1671 trace->tool.ordering_requires_timestamps = true;
1672
1673 /* add tid to output */
1674 trace->multiple_threads = true;
1675
1676 if (symbol__init() < 0)
1677 return -1;
1678
1679 session = perf_session__new(input_name, O_RDONLY, 0, false,
1680 &trace->tool);
1681 if (session == NULL)
1682 return -ENOMEM;
1683
1684 err = perf_session__set_tracepoints_handlers(session, handlers);
1685 if (err)
1686 goto out;
1687
1688 if (!perf_session__has_tp(session, "raw_syscalls:sys_enter")) {
1689 pr_err("Data file does not have raw_syscalls:sys_enter events\n");
1690 goto out;
1691 }
1692
1693 if (!perf_session__has_tp(session, "raw_syscalls:sys_exit")) {
1694 pr_err("Data file does not have raw_syscalls:sys_exit events\n");
1695 goto out;
1696 }
1697
bdc89661
DA
1698 err = parse_target_str(trace);
1699 if (err != 0)
1700 goto out;
1701
6810fc91
DA
1702 setup_pager();
1703
1704 err = perf_session__process_events(session, &trace->tool);
1705 if (err)
1706 pr_err("Failed to process events, error %d", err);
1707
1708out:
1709 perf_session__delete(session);
1710
1711 return err;
1712}
1713
1302d88e
ACM
1714static size_t trace__fprintf_threads_header(FILE *fp)
1715{
1716 size_t printed;
1717
1718 printed = fprintf(fp, "\n _____________________________________________________________________\n");
1719 printed += fprintf(fp," __) Summary of events (__\n\n");
1720 printed += fprintf(fp," [ task - pid ] [ events ] [ ratio ] [ runtime ]\n");
1721 printed += fprintf(fp," _____________________________________________________________________\n\n");
1722
1723 return printed;
1724}
1725
1726static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp)
1727{
1728 size_t printed = trace__fprintf_threads_header(fp);
1729 struct rb_node *nd;
1730
1731 for (nd = rb_first(&trace->host.threads); nd; nd = rb_next(nd)) {
1732 struct thread *thread = rb_entry(nd, struct thread, rb_node);
1733 struct thread_trace *ttrace = thread->priv;
1734 const char *color;
1735 double ratio;
1736
1737 if (ttrace == NULL)
1738 continue;
1739
1740 ratio = (double)ttrace->nr_events / trace->nr_events * 100.0;
1741
1742 color = PERF_COLOR_NORMAL;
1743 if (ratio > 50.0)
1744 color = PERF_COLOR_RED;
1745 else if (ratio > 25.0)
1746 color = PERF_COLOR_GREEN;
1747 else if (ratio > 5.0)
1748 color = PERF_COLOR_YELLOW;
1749
1750 printed += color_fprintf(fp, color, "%20s", thread->comm);
38051234 1751 printed += fprintf(fp, " - %-5d :%11lu [", thread->tid, ttrace->nr_events);
1302d88e
ACM
1752 printed += color_fprintf(fp, color, "%5.1f%%", ratio);
1753 printed += fprintf(fp, " ] %10.3f ms\n", ttrace->runtime_ms);
1754 }
1755
1756 return printed;
1757}
1758
ae9ed035
ACM
1759static int trace__set_duration(const struct option *opt, const char *str,
1760 int unset __maybe_unused)
1761{
1762 struct trace *trace = opt->value;
1763
1764 trace->duration_filter = atof(str);
1765 return 0;
1766}
1767
c24ff998
ACM
1768static int trace__open_output(struct trace *trace, const char *filename)
1769{
1770 struct stat st;
1771
1772 if (!stat(filename, &st) && st.st_size) {
1773 char oldname[PATH_MAX];
1774
1775 scnprintf(oldname, sizeof(oldname), "%s.old", filename);
1776 unlink(oldname);
1777 rename(filename, oldname);
1778 }
1779
1780 trace->output = fopen(filename, "w");
1781
1782 return trace->output == NULL ? -errno : 0;
1783}
1784
514f1c67
ACM
1785int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
1786{
1787 const char * const trace_usage[] = {
f15eb531
NK
1788 "perf trace [<options>] [<command>]",
1789 "perf trace [<options>] -- <command> [<options>]",
514f1c67
ACM
1790 NULL
1791 };
1792 struct trace trace = {
1793 .audit_machine = audit_detect_machine(),
1794 .syscalls = {
1795 . max = -1,
1796 },
1797 .opts = {
1798 .target = {
1799 .uid = UINT_MAX,
1800 .uses_mmap = true,
1801 },
1802 .user_freq = UINT_MAX,
1803 .user_interval = ULLONG_MAX,
1804 .no_delay = true,
1805 .mmap_pages = 1024,
1806 },
c24ff998 1807 .output = stdout,
50c95cbd 1808 .show_comm = true,
514f1c67 1809 };
c24ff998 1810 const char *output_name = NULL;
2ae3a312 1811 const char *ev_qualifier_str = NULL;
514f1c67 1812 const struct option trace_options[] = {
50c95cbd
ACM
1813 OPT_BOOLEAN(0, "comm", &trace.show_comm,
1814 "show the thread COMM next to its id"),
2ae3a312
ACM
1815 OPT_STRING('e', "expr", &ev_qualifier_str, "expr",
1816 "list of events to trace"),
c24ff998 1817 OPT_STRING('o', "output", &output_name, "file", "output file name"),
6810fc91 1818 OPT_STRING('i', "input", &input_name, "file", "Analyze events in file"),
514f1c67
ACM
1819 OPT_STRING('p', "pid", &trace.opts.target.pid, "pid",
1820 "trace events on existing process id"),
ac9be8ee 1821 OPT_STRING('t', "tid", &trace.opts.target.tid, "tid",
514f1c67 1822 "trace events on existing thread id"),
ac9be8ee 1823 OPT_BOOLEAN('a', "all-cpus", &trace.opts.target.system_wide,
514f1c67 1824 "system-wide collection from all CPUs"),
ac9be8ee 1825 OPT_STRING('C', "cpu", &trace.opts.target.cpu_list, "cpu",
514f1c67 1826 "list of cpus to monitor"),
6810fc91 1827 OPT_BOOLEAN(0, "no-inherit", &trace.opts.no_inherit,
514f1c67 1828 "child tasks do not inherit counters"),
994a1f78
JO
1829 OPT_CALLBACK('m', "mmap-pages", &trace.opts.mmap_pages, "pages",
1830 "number of mmap data pages",
1831 perf_evlist__parse_mmap_pages),
ac9be8ee 1832 OPT_STRING('u', "uid", &trace.opts.target.uid_str, "user",
514f1c67 1833 "user to profile"),
ae9ed035
ACM
1834 OPT_CALLBACK(0, "duration", &trace, "float",
1835 "show only events with duration > N.M ms",
1836 trace__set_duration),
1302d88e 1837 OPT_BOOLEAN(0, "sched", &trace.sched, "show blocking scheduler events"),
7c304ee0 1838 OPT_INCR('v', "verbose", &verbose, "be more verbose"),
4bb09192
DA
1839 OPT_BOOLEAN('T', "time", &trace.full_time,
1840 "Show full timestamp, not time relative to first start"),
514f1c67
ACM
1841 OPT_END()
1842 };
1843 int err;
32caf0d1 1844 char bf[BUFSIZ];
514f1c67
ACM
1845
1846 argc = parse_options(argc, argv, trace_options, trace_usage, 0);
514f1c67 1847
c24ff998
ACM
1848 if (output_name != NULL) {
1849 err = trace__open_output(&trace, output_name);
1850 if (err < 0) {
1851 perror("failed to create output file");
1852 goto out;
1853 }
1854 }
1855
2ae3a312 1856 if (ev_qualifier_str != NULL) {
b059efdf
ACM
1857 const char *s = ev_qualifier_str;
1858
1859 trace.not_ev_qualifier = *s == '!';
1860 if (trace.not_ev_qualifier)
1861 ++s;
1862 trace.ev_qualifier = strlist__new(true, s);
2ae3a312 1863 if (trace.ev_qualifier == NULL) {
c24ff998
ACM
1864 fputs("Not enough memory to parse event qualifier",
1865 trace.output);
1866 err = -ENOMEM;
1867 goto out_close;
2ae3a312
ACM
1868 }
1869 }
1870
32caf0d1
NK
1871 err = perf_target__validate(&trace.opts.target);
1872 if (err) {
1873 perf_target__strerror(&trace.opts.target, err, bf, sizeof(bf));
c24ff998
ACM
1874 fprintf(trace.output, "%s", bf);
1875 goto out_close;
32caf0d1
NK
1876 }
1877
514f1c67
ACM
1878 err = perf_target__parse_uid(&trace.opts.target);
1879 if (err) {
514f1c67 1880 perf_target__strerror(&trace.opts.target, err, bf, sizeof(bf));
c24ff998
ACM
1881 fprintf(trace.output, "%s", bf);
1882 goto out_close;
514f1c67
ACM
1883 }
1884
f15eb531 1885 if (!argc && perf_target__none(&trace.opts.target))
ee76120e
NK
1886 trace.opts.target.system_wide = true;
1887
6810fc91
DA
1888 if (input_name)
1889 err = trace__replay(&trace);
1890 else
1891 err = trace__run(&trace, argc, argv);
1302d88e
ACM
1892
1893 if (trace.sched && !err)
c24ff998 1894 trace__fprintf_thread_summary(&trace, trace.output);
1302d88e 1895
c24ff998
ACM
1896out_close:
1897 if (output_name != NULL)
1898 fclose(trace.output);
1899out:
1302d88e 1900 return err;
514f1c67 1901}
This page took 0.150091 seconds and 5 git commands to generate.