1 #include <traceevent/event-parse.h>
3 #include "util/color.h"
4 #include "util/debug.h"
5 #include "util/evlist.h"
6 #include "util/machine.h"
7 #include "util/session.h"
8 #include "util/thread.h"
9 #include "util/parse-options.h"
10 #include "util/strlist.h"
11 #include "util/intlist.h"
12 #include "util/thread_map.h"
16 #include <sys/eventfd.h>
18 #include <linux/futex.h>
20 /* For older distros: */
22 # define MAP_STACK 0x20000
26 # define MADV_HWPOISON 100
29 #ifndef MADV_MERGEABLE
30 # define MADV_MERGEABLE 12
33 #ifndef MADV_UNMERGEABLE
34 # define MADV_UNMERGEABLE 13
39 struct thread *thread;
51 #define DEFINE_STRARRAY(array) struct strarray strarray__##array = { \
52 .nr_entries = ARRAY_SIZE(array), \
56 static size_t syscall_arg__scnprintf_strarray(char *bf, size_t size,
57 struct syscall_arg *arg)
60 struct strarray *sa = arg->parm;
62 if (idx < 0 || idx >= sa->nr_entries)
63 return scnprintf(bf, size, "%d", idx);
65 return scnprintf(bf, size, "%s", sa->entries[idx]);
68 #define SCA_STRARRAY syscall_arg__scnprintf_strarray
70 static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
71 struct syscall_arg *arg);
73 #define SCA_FD syscall_arg__scnprintf_fd
75 static size_t syscall_arg__scnprintf_fd_at(char *bf, size_t size,
76 struct syscall_arg *arg)
81 return scnprintf(bf, size, "CWD");
83 return syscall_arg__scnprintf_fd(bf, size, arg);
86 #define SCA_FDAT syscall_arg__scnprintf_fd_at
88 static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
89 struct syscall_arg *arg);
91 #define SCA_CLOSE_FD syscall_arg__scnprintf_close_fd
93 static size_t syscall_arg__scnprintf_hex(char *bf, size_t size,
94 struct syscall_arg *arg)
96 return scnprintf(bf, size, "%#lx", arg->val);
99 #define SCA_HEX syscall_arg__scnprintf_hex
101 static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size,
102 struct syscall_arg *arg)
104 int printed = 0, prot = arg->val;
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); \
120 P_MMAP_PROT(GROWSDOWN);
121 P_MMAP_PROT(GROWSUP);
125 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", prot);
130 #define SCA_MMAP_PROT syscall_arg__scnprintf_mmap_prot
132 static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size,
133 struct syscall_arg *arg)
135 int printed = 0, flags = arg->val;
137 #define P_MMAP_FLAG(n) \
138 if (flags & MAP_##n) { \
139 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
144 P_MMAP_FLAG(PRIVATE);
148 P_MMAP_FLAG(ANONYMOUS);
149 P_MMAP_FLAG(DENYWRITE);
150 P_MMAP_FLAG(EXECUTABLE);
153 P_MMAP_FLAG(GROWSDOWN);
155 P_MMAP_FLAG(HUGETLB);
158 P_MMAP_FLAG(NONBLOCK);
159 P_MMAP_FLAG(NORESERVE);
160 P_MMAP_FLAG(POPULATE);
162 #ifdef MAP_UNINITIALIZED
163 P_MMAP_FLAG(UNINITIALIZED);
168 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
173 #define SCA_MMAP_FLAGS syscall_arg__scnprintf_mmap_flags
175 static size_t syscall_arg__scnprintf_madvise_behavior(char *bf, size_t size,
176 struct syscall_arg *arg)
178 int behavior = arg->val;
181 #define P_MADV_BHV(n) case MADV_##n: return scnprintf(bf, size, #n)
184 P_MADV_BHV(SEQUENTIAL);
185 P_MADV_BHV(WILLNEED);
186 P_MADV_BHV(DONTNEED);
188 P_MADV_BHV(DONTFORK);
190 P_MADV_BHV(HWPOISON);
191 #ifdef MADV_SOFT_OFFLINE
192 P_MADV_BHV(SOFT_OFFLINE);
194 P_MADV_BHV(MERGEABLE);
195 P_MADV_BHV(UNMERGEABLE);
197 P_MADV_BHV(HUGEPAGE);
199 #ifdef MADV_NOHUGEPAGE
200 P_MADV_BHV(NOHUGEPAGE);
203 P_MADV_BHV(DONTDUMP);
212 return scnprintf(bf, size, "%#x", behavior);
215 #define SCA_MADV_BHV syscall_arg__scnprintf_madvise_behavior
217 static size_t syscall_arg__scnprintf_flock(char *bf, size_t size,
218 struct syscall_arg *arg)
220 int printed = 0, op = arg->val;
223 return scnprintf(bf, size, "NONE");
225 if ((op & LOCK_##cmd) == LOCK_##cmd) { \
226 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #cmd); \
241 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", op);
246 #define SCA_FLOCK syscall_arg__scnprintf_flock
248 static size_t syscall_arg__scnprintf_futex_op(char *bf, size_t size, struct syscall_arg *arg)
250 enum syscall_futex_args {
251 SCF_UADDR = (1 << 0),
254 SCF_TIMEOUT = (1 << 3),
255 SCF_UADDR2 = (1 << 4),
259 int cmd = op & FUTEX_CMD_MASK;
263 #define P_FUTEX_OP(n) case FUTEX_##n: printed = scnprintf(bf, size, #n);
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;
270 P_FUTEX_OP(WAKE_OP); break;
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;
276 P_FUTEX_OP(WAIT_REQUEUE_PI); break;
277 default: printed = scnprintf(bf, size, "%#x", cmd); break;
280 if (op & FUTEX_PRIVATE_FLAG)
281 printed += scnprintf(bf + printed, size - printed, "|PRIV");
283 if (op & FUTEX_CLOCK_REALTIME)
284 printed += scnprintf(bf + printed, size - printed, "|CLKRT");
289 #define SCA_FUTEX_OP syscall_arg__scnprintf_futex_op
291 static const char *epoll_ctl_ops[] = { [1] = "ADD", "DEL", "MOD", };
292 static DEFINE_STRARRAY(epoll_ctl_ops);
294 static const char *itimers[] = { "REAL", "VIRTUAL", "PROF", };
295 static DEFINE_STRARRAY(itimers);
297 static const char *whences[] = { "SET", "CUR", "END",
305 static DEFINE_STRARRAY(whences);
307 static 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",
313 static DEFINE_STRARRAY(fcntl_cmds);
315 static const char *rlimit_resources[] = {
316 "CPU", "FSIZE", "DATA", "STACK", "CORE", "RSS", "NPROC", "NOFILE",
317 "MEMLOCK", "AS", "LOCKS", "SIGPENDING", "MSGQUEUE", "NICE", "RTPRIO",
320 static DEFINE_STRARRAY(rlimit_resources);
322 static const char *sighow[] = { "BLOCK", "UNBLOCK", "SETMASK", };
323 static DEFINE_STRARRAY(sighow);
325 static const char *clockid[] = {
326 "REALTIME", "MONOTONIC", "PROCESS_CPUTIME_ID", "THREAD_CPUTIME_ID",
327 "MONOTONIC_RAW", "REALTIME_COARSE", "MONOTONIC_COARSE",
329 static DEFINE_STRARRAY(clockid);
331 static 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",
339 static DEFINE_STRARRAY(socket_families);
341 #ifndef SOCK_TYPE_MASK
342 #define SOCK_TYPE_MASK 0xf
345 static size_t syscall_arg__scnprintf_socket_type(char *bf, size_t size,
346 struct syscall_arg *arg)
350 flags = type & ~SOCK_TYPE_MASK;
352 type &= SOCK_TYPE_MASK;
354 * Can't use a strarray, MIPS may override for ABI reasons.
357 #define P_SK_TYPE(n) case SOCK_##n: printed = scnprintf(bf, size, #n); break;
362 P_SK_TYPE(SEQPACKET);
367 printed = scnprintf(bf, size, "%#x", type);
370 #define P_SK_FLAG(n) \
371 if (flags & SOCK_##n) { \
372 printed += scnprintf(bf + printed, size - printed, "|%s", #n); \
373 flags &= ~SOCK_##n; \
381 printed += scnprintf(bf + printed, size - printed, "|%#x", flags);
386 #define SCA_SK_TYPE syscall_arg__scnprintf_socket_type
389 #define MSG_PROBE 0x10
391 #ifndef MSG_WAITFORONE
392 #define MSG_WAITFORONE 0x10000
394 #ifndef MSG_SENDPAGE_NOTLAST
395 #define MSG_SENDPAGE_NOTLAST 0x20000
398 #define MSG_FASTOPEN 0x20000000
401 static size_t syscall_arg__scnprintf_msg_flags(char *bf, size_t size,
402 struct syscall_arg *arg)
404 int printed = 0, flags = arg->val;
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); \
416 P_MSG_FLAG(DONTROUTE);
421 P_MSG_FLAG(DONTWAIT);
428 P_MSG_FLAG(ERRQUEUE);
429 P_MSG_FLAG(NOSIGNAL);
431 P_MSG_FLAG(WAITFORONE);
432 P_MSG_FLAG(SENDPAGE_NOTLAST);
433 P_MSG_FLAG(FASTOPEN);
434 P_MSG_FLAG(CMSG_CLOEXEC);
438 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
443 #define SCA_MSG_FLAGS syscall_arg__scnprintf_msg_flags
445 static size_t syscall_arg__scnprintf_access_mode(char *bf, size_t size,
446 struct syscall_arg *arg)
451 if (mode == F_OK) /* 0 */
452 return scnprintf(bf, size, "F");
454 if (mode & n##_OK) { \
455 printed += scnprintf(bf + printed, size - printed, "%s", #n); \
465 printed += scnprintf(bf + printed, size - printed, "|%#x", mode);
470 #define SCA_ACCMODE syscall_arg__scnprintf_access_mode
472 static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
473 struct syscall_arg *arg)
475 int printed = 0, flags = arg->val;
477 if (!(flags & O_CREAT))
478 arg->mask |= 1 << (arg->idx + 1); /* Mask the mode parm */
481 return scnprintf(bf, size, "RDONLY");
483 if (flags & O_##n) { \
484 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
508 if ((flags & O_SYNC) == O_SYNC)
509 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", "SYNC");
521 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
526 #define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags
528 static size_t syscall_arg__scnprintf_eventfd_flags(char *bf, size_t size,
529 struct syscall_arg *arg)
531 int printed = 0, flags = arg->val;
534 return scnprintf(bf, size, "NONE");
536 if (flags & EFD_##n) { \
537 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
547 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
552 #define SCA_EFD_FLAGS syscall_arg__scnprintf_eventfd_flags
554 static size_t syscall_arg__scnprintf_pipe_flags(char *bf, size_t size,
555 struct syscall_arg *arg)
557 int printed = 0, flags = arg->val;
560 if (flags & O_##n) { \
561 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
570 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
575 #define SCA_PIPE_FLAGS syscall_arg__scnprintf_pipe_flags
577 static size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscall_arg *arg)
582 #define P_SIGNUM(n) case SIG##n: return scnprintf(bf, size, #n)
617 return scnprintf(bf, size, "%#x", sig);
620 #define SCA_SIGNUM syscall_arg__scnprintf_signum
622 #define STRARRAY(arg, name, array) \
623 .arg_scnprintf = { [arg] = SCA_STRARRAY, }, \
624 .arg_parm = { [arg] = &strarray__##array, }
626 static struct syscall_fmt {
629 size_t (*arg_scnprintf[6])(char *bf, size_t size, struct syscall_arg *arg);
635 { .name = "access", .errmsg = true,
636 .arg_scnprintf = { [1] = SCA_ACCMODE, /* mode */ }, },
637 { .name = "arch_prctl", .errmsg = true, .alias = "prctl", },
638 { .name = "brk", .hexret = true,
639 .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, },
640 { .name = "clock_gettime", .errmsg = true, STRARRAY(0, clk_id, clockid), },
641 { .name = "close", .errmsg = true,
642 .arg_scnprintf = { [0] = SCA_CLOSE_FD, /* fd */ }, },
643 { .name = "connect", .errmsg = true, },
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 */ }, },
650 { .name = "epoll_ctl", .errmsg = true, STRARRAY(1, op, epoll_ctl_ops), },
651 { .name = "eventfd2", .errmsg = true,
652 .arg_scnprintf = { [1] = SCA_EFD_FLAGS, /* flags */ }, },
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 */ }, },
675 { .name = "flock", .errmsg = true,
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 */ }, },
690 { .name = "futex", .errmsg = true,
691 .arg_scnprintf = { [1] = SCA_FUTEX_OP, /* op */ }, },
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 */ }, },
698 { .name = "getitimer", .errmsg = true, STRARRAY(0, which, itimers), },
699 { .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
700 { .name = "ioctl", .errmsg = true,
701 .arg_scnprintf = { [0] = SCA_FD, /* fd */
702 [2] = SCA_HEX, /* arg */ }, },
703 { .name = "kill", .errmsg = true,
704 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
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 */ }, },
711 { .name = "lstat", .errmsg = true, .alias = "newlstat", },
712 { .name = "madvise", .errmsg = true,
713 .arg_scnprintf = { [0] = SCA_HEX, /* start */
714 [2] = SCA_MADV_BHV, /* behavior */ }, },
715 { .name = "mkdirat", .errmsg = true,
716 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
717 { .name = "mknodat", .errmsg = true,
718 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
719 { .name = "mlock", .errmsg = true,
720 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
721 { .name = "mlockall", .errmsg = true,
722 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
723 { .name = "mmap", .hexret = true,
724 .arg_scnprintf = { [0] = SCA_HEX, /* addr */
725 [2] = SCA_MMAP_PROT, /* prot */
726 [3] = SCA_MMAP_FLAGS, /* flags */ }, },
727 { .name = "mprotect", .errmsg = true,
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 */ }, },
733 { .name = "munlock", .errmsg = true,
734 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
735 { .name = "munmap", .errmsg = true,
736 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
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 */ }, },
741 { .name = "open", .errmsg = true,
742 .arg_scnprintf = { [1] = SCA_OPEN_FLAGS, /* flags */ }, },
743 { .name = "open_by_handle_at", .errmsg = true,
744 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
745 [2] = SCA_OPEN_FLAGS, /* flags */ }, },
746 { .name = "openat", .errmsg = true,
747 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
748 [2] = SCA_OPEN_FLAGS, /* flags */ }, },
749 { .name = "pipe2", .errmsg = true,
750 .arg_scnprintf = { [1] = SCA_PIPE_FLAGS, /* flags */ }, },
751 { .name = "poll", .errmsg = true, .timeout = true, },
752 { .name = "ppoll", .errmsg = true, .timeout = true, },
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 */ }, },
757 { .name = "prlimit64", .errmsg = true, STRARRAY(1, resource, rlimit_resources), },
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 */ }, },
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 */ }, },
774 { .name = "renameat", .errmsg = true,
775 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
776 { .name = "rt_sigaction", .errmsg = true,
777 .arg_scnprintf = { [0] = SCA_SIGNUM, /* sig */ }, },
778 { .name = "rt_sigprocmask", .errmsg = true, STRARRAY(0, how, sighow), },
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 */ }, },
783 { .name = "select", .errmsg = true, .timeout = true, },
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 */ }, },
790 { .name = "setitimer", .errmsg = true, STRARRAY(0, which, itimers), },
791 { .name = "setrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
792 { .name = "shutdown", .errmsg = true,
793 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
794 { .name = "socket", .errmsg = true,
795 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
796 [1] = SCA_SK_TYPE, /* type */ },
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 */ },
801 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, },
802 { .name = "stat", .errmsg = true, .alias = "newstat", },
803 { .name = "symlinkat", .errmsg = true,
804 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
805 { .name = "tgkill", .errmsg = true,
806 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
807 { .name = "tkill", .errmsg = true,
808 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
809 { .name = "uname", .errmsg = true, .alias = "newuname", },
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 */ }, },
820 static int syscall_fmt__cmp(const void *name, const void *fmtp)
822 const struct syscall_fmt *fmt = fmtp;
823 return strcmp(name, fmt->name);
826 static struct syscall_fmt *syscall_fmt__find(const char *name)
828 const int nmemb = ARRAY_SIZE(syscall_fmts);
829 return bsearch(name, syscall_fmts, nmemb, sizeof(struct syscall_fmt), syscall_fmt__cmp);
833 struct event_format *tp_format;
836 struct syscall_fmt *fmt;
837 size_t (**arg_scnprintf)(char *bf, size_t size, struct syscall_arg *arg);
841 static size_t fprintf_duration(unsigned long t, FILE *fp)
843 double duration = (double)t / NSEC_PER_MSEC;
844 size_t printed = fprintf(fp, "(");
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);
851 printed += color_fprintf(fp, PERF_COLOR_NORMAL, "%6.3f ms", duration);
852 return printed + fprintf(fp, "): ");
855 struct thread_trace {
859 unsigned long nr_events;
868 static struct thread_trace *thread_trace__new(void)
870 struct thread_trace *ttrace = zalloc(sizeof(struct thread_trace));
873 ttrace->paths.max = -1;
878 static struct thread_trace *thread__trace(struct thread *thread, FILE *fp)
880 struct thread_trace *ttrace;
885 if (thread->priv == NULL)
886 thread->priv = thread_trace__new();
888 if (thread->priv == NULL)
891 ttrace = thread->priv;
896 color_fprintf(fp, PERF_COLOR_RED,
897 "WARNING: not enough memory, dropping samples!\n");
902 struct perf_tool tool;
906 struct syscall *table;
908 struct perf_record_opts opts;
909 struct machine *host;
913 unsigned long nr_events;
914 struct strlist *ev_qualifier;
915 bool not_ev_qualifier;
917 struct intlist *tid_list;
918 struct intlist *pid_list;
920 bool multiple_threads;
922 double duration_filter;
926 static int thread__read_fd_path(struct thread *thread, int fd)
928 struct thread_trace *ttrace = thread->priv;
929 char linkname[PATH_MAX], pathname[PATH_MAX];
933 if (thread->pid_ == thread->tid) {
934 scnprintf(linkname, sizeof(linkname),
935 "/proc/%d/fd/%d", thread->pid_, fd);
937 scnprintf(linkname, sizeof(linkname),
938 "/proc/%d/task/%d/fd/%d", thread->pid_, thread->tid, fd);
941 if (lstat(linkname, &st) < 0 || st.st_size + 1 > (off_t)sizeof(pathname))
944 ret = readlink(linkname, pathname, sizeof(pathname));
946 if (ret < 0 || ret > st.st_size)
949 pathname[ret] = '\0';
951 if (fd > ttrace->paths.max) {
952 char **npath = realloc(ttrace->paths.table, (fd + 1) * sizeof(char *));
957 if (ttrace->paths.max != -1) {
958 memset(npath + ttrace->paths.max + 1, 0,
959 (fd - ttrace->paths.max) * sizeof(char *));
961 memset(npath, 0, (fd + 1) * sizeof(char *));
964 ttrace->paths.table = npath;
965 ttrace->paths.max = fd;
968 ttrace->paths.table[fd] = strdup(pathname);
970 return ttrace->paths.table[fd] != NULL ? 0 : -1;
973 static const char *thread__fd_path(struct thread *thread, int fd, bool live)
975 struct thread_trace *ttrace = thread->priv;
983 if ((fd > ttrace->paths.max || ttrace->paths.table[fd] == NULL) &&
984 (!live || thread__read_fd_path(thread, fd)))
987 return ttrace->paths.table[fd];
990 static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
991 struct syscall_arg *arg)
994 size_t printed = scnprintf(bf, size, "%d", fd);
995 const char *path = thread__fd_path(arg->thread, fd, arg->trace->live);
998 printed += scnprintf(bf + printed, size - printed, "<%s>", path);
1003 static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
1004 struct syscall_arg *arg)
1007 size_t printed = syscall_arg__scnprintf_fd(bf, size, arg);
1008 struct thread_trace *ttrace = arg->thread->priv;
1010 if (ttrace && fd >= 0 && fd <= ttrace->paths.max) {
1011 free(ttrace->paths.table[fd]);
1012 ttrace->paths.table[fd] = NULL;
1018 static bool trace__filter_duration(struct trace *trace, double t)
1020 return t < (trace->duration_filter * NSEC_PER_MSEC);
1023 static size_t trace__fprintf_tstamp(struct trace *trace, u64 tstamp, FILE *fp)
1025 double ts = (double)(tstamp - trace->base_time) / NSEC_PER_MSEC;
1027 return fprintf(fp, "%10.3f ", ts);
1030 static bool done = false;
1032 static void sig_handler(int sig __maybe_unused)
1037 static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thread,
1038 u64 duration, u64 tstamp, FILE *fp)
1040 size_t printed = trace__fprintf_tstamp(trace, tstamp, fp);
1041 printed += fprintf_duration(duration, fp);
1043 if (trace->multiple_threads) {
1044 if (trace->show_comm)
1045 printed += fprintf(fp, "%.14s/", thread->comm);
1046 printed += fprintf(fp, "%d ", thread->tid);
1052 static int trace__process_event(struct trace *trace, struct machine *machine,
1053 union perf_event *event)
1057 switch (event->header.type) {
1058 case PERF_RECORD_LOST:
1059 color_fprintf(trace->output, PERF_COLOR_RED,
1060 "LOST %" PRIu64 " events!\n", event->lost.lost);
1061 ret = machine__process_lost_event(machine, event);
1063 ret = machine__process_event(machine, event);
1070 static int trace__tool_process(struct perf_tool *tool,
1071 union perf_event *event,
1072 struct perf_sample *sample __maybe_unused,
1073 struct machine *machine)
1075 struct trace *trace = container_of(tool, struct trace, tool);
1076 return trace__process_event(trace, machine, event);
1079 static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
1081 int err = symbol__init();
1086 trace->host = machine__new_host();
1087 if (trace->host == NULL)
1090 if (perf_target__has_task(&trace->opts.target)) {
1091 err = perf_event__synthesize_thread_map(&trace->tool, evlist->threads,
1092 trace__tool_process,
1095 err = perf_event__synthesize_threads(&trace->tool, trace__tool_process,
1105 static int syscall__set_arg_fmts(struct syscall *sc)
1107 struct format_field *field;
1110 sc->arg_scnprintf = calloc(sc->tp_format->format.nr_fields - 1, sizeof(void *));
1111 if (sc->arg_scnprintf == NULL)
1115 sc->arg_parm = sc->fmt->arg_parm;
1117 for (field = sc->tp_format->format.fields->next; field; field = field->next) {
1118 if (sc->fmt && sc->fmt->arg_scnprintf[idx])
1119 sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx];
1120 else if (field->flags & FIELD_IS_POINTER)
1121 sc->arg_scnprintf[idx] = syscall_arg__scnprintf_hex;
1128 static int trace__read_syscall_info(struct trace *trace, int id)
1132 const char *name = audit_syscall_to_name(id, trace->audit_machine);
1137 if (id > trace->syscalls.max) {
1138 struct syscall *nsyscalls = realloc(trace->syscalls.table, (id + 1) * sizeof(*sc));
1140 if (nsyscalls == NULL)
1143 if (trace->syscalls.max != -1) {
1144 memset(nsyscalls + trace->syscalls.max + 1, 0,
1145 (id - trace->syscalls.max) * sizeof(*sc));
1147 memset(nsyscalls, 0, (id + 1) * sizeof(*sc));
1150 trace->syscalls.table = nsyscalls;
1151 trace->syscalls.max = id;
1154 sc = trace->syscalls.table + id;
1157 if (trace->ev_qualifier) {
1158 bool in = strlist__find(trace->ev_qualifier, name) != NULL;
1160 if (!(in ^ trace->not_ev_qualifier)) {
1161 sc->filtered = true;
1163 * No need to do read tracepoint information since this will be
1170 sc->fmt = syscall_fmt__find(sc->name);
1172 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name);
1173 sc->tp_format = event_format__new("syscalls", tp_name);
1175 if (sc->tp_format == NULL && sc->fmt && sc->fmt->alias) {
1176 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->fmt->alias);
1177 sc->tp_format = event_format__new("syscalls", tp_name);
1180 if (sc->tp_format == NULL)
1183 return syscall__set_arg_fmts(sc);
1186 static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
1187 unsigned long *args, struct trace *trace,
1188 struct thread *thread)
1192 if (sc->tp_format != NULL) {
1193 struct format_field *field;
1195 struct syscall_arg arg = {
1202 for (field = sc->tp_format->format.fields->next; field;
1203 field = field->next, ++arg.idx, bit <<= 1) {
1207 * Suppress this argument if its value is zero and
1208 * and we don't have a string associated in an
1211 if (args[arg.idx] == 0 &&
1212 !(sc->arg_scnprintf &&
1213 sc->arg_scnprintf[arg.idx] == SCA_STRARRAY &&
1214 sc->arg_parm[arg.idx]))
1217 printed += scnprintf(bf + printed, size - printed,
1218 "%s%s: ", printed ? ", " : "", field->name);
1219 if (sc->arg_scnprintf && sc->arg_scnprintf[arg.idx]) {
1220 arg.val = args[arg.idx];
1222 arg.parm = sc->arg_parm[arg.idx];
1223 printed += sc->arg_scnprintf[arg.idx](bf + printed,
1224 size - printed, &arg);
1226 printed += scnprintf(bf + printed, size - printed,
1227 "%ld", args[arg.idx]);
1234 printed += scnprintf(bf + printed, size - printed,
1236 printed ? ", " : "", i, args[i]);
1244 typedef int (*tracepoint_handler)(struct trace *trace, struct perf_evsel *evsel,
1245 struct perf_sample *sample);
1247 static struct syscall *trace__syscall_info(struct trace *trace,
1248 struct perf_evsel *evsel,
1249 struct perf_sample *sample)
1251 int id = perf_evsel__intval(evsel, sample, "id");
1256 * XXX: Noticed on x86_64, reproduced as far back as 3.0.36, haven't tried
1257 * before that, leaving at a higher verbosity level till that is
1258 * explained. Reproduced with plain ftrace with:
1260 * echo 1 > /t/events/raw_syscalls/sys_exit/enable
1261 * grep "NR -1 " /t/trace_pipe
1263 * After generating some load on the machine.
1267 fprintf(trace->output, "Invalid syscall %d id, skipping (%s, %" PRIu64 ") ...\n",
1268 id, perf_evsel__name(evsel), ++n);
1273 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL) &&
1274 trace__read_syscall_info(trace, id))
1277 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL))
1280 return &trace->syscalls.table[id];
1284 fprintf(trace->output, "Problems reading syscall %d", id);
1285 if (id <= trace->syscalls.max && trace->syscalls.table[id].name != NULL)
1286 fprintf(trace->output, "(%s)", trace->syscalls.table[id].name);
1287 fputs(" information\n", trace->output);
1292 static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
1293 struct perf_sample *sample)
1298 struct thread *thread;
1299 struct syscall *sc = trace__syscall_info(trace, evsel, sample);
1300 struct thread_trace *ttrace;
1308 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
1309 ttrace = thread__trace(thread, trace->output);
1313 args = perf_evsel__rawptr(evsel, sample, "args");
1315 fprintf(trace->output, "Problems reading syscall arguments\n");
1319 ttrace = thread->priv;
1321 if (ttrace->entry_str == NULL) {
1322 ttrace->entry_str = malloc(1024);
1323 if (!ttrace->entry_str)
1327 ttrace->entry_time = sample->time;
1328 msg = ttrace->entry_str;
1329 printed += scnprintf(msg + printed, 1024 - printed, "%s(", sc->name);
1331 printed += syscall__scnprintf_args(sc, msg + printed, 1024 - printed,
1332 args, trace, thread);
1334 if (!strcmp(sc->name, "exit_group") || !strcmp(sc->name, "exit")) {
1335 if (!trace->duration_filter) {
1336 trace__fprintf_entry_head(trace, thread, 1, sample->time, trace->output);
1337 fprintf(trace->output, "%-70s\n", ttrace->entry_str);
1340 ttrace->entry_pending = true;
1345 static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
1346 struct perf_sample *sample)
1350 struct thread *thread;
1351 struct syscall *sc = trace__syscall_info(trace, evsel, sample);
1352 struct thread_trace *ttrace;
1360 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
1361 ttrace = thread__trace(thread, trace->output);
1365 ret = perf_evsel__intval(evsel, sample, "ret");
1367 ttrace = thread->priv;
1369 ttrace->exit_time = sample->time;
1371 if (ttrace->entry_time) {
1372 duration = sample->time - ttrace->entry_time;
1373 if (trace__filter_duration(trace, duration))
1375 } else if (trace->duration_filter)
1378 trace__fprintf_entry_head(trace, thread, duration, sample->time, trace->output);
1380 if (ttrace->entry_pending) {
1381 fprintf(trace->output, "%-70s", ttrace->entry_str);
1383 fprintf(trace->output, " ... [");
1384 color_fprintf(trace->output, PERF_COLOR_YELLOW, "continued");
1385 fprintf(trace->output, "]: %s()", sc->name);
1388 if (sc->fmt == NULL) {
1390 fprintf(trace->output, ") = %d", ret);
1391 } else if (ret < 0 && sc->fmt->errmsg) {
1393 const char *emsg = strerror_r(-ret, bf, sizeof(bf)),
1394 *e = audit_errno_to_name(-ret);
1396 fprintf(trace->output, ") = -1 %s %s", e, emsg);
1397 } else if (ret == 0 && sc->fmt->timeout)
1398 fprintf(trace->output, ") = 0 Timeout");
1399 else if (sc->fmt->hexret)
1400 fprintf(trace->output, ") = %#x", ret);
1404 fputc('\n', trace->output);
1406 ttrace->entry_pending = false;
1411 static int trace__sched_stat_runtime(struct trace *trace, struct perf_evsel *evsel,
1412 struct perf_sample *sample)
1414 u64 runtime = perf_evsel__intval(evsel, sample, "runtime");
1415 double runtime_ms = (double)runtime / NSEC_PER_MSEC;
1416 struct thread *thread = machine__findnew_thread(trace->host,
1419 struct thread_trace *ttrace = thread__trace(thread, trace->output);
1424 ttrace->runtime_ms += runtime_ms;
1425 trace->runtime_ms += runtime_ms;
1429 fprintf(trace->output, "%s: comm=%s,pid=%u,runtime=%" PRIu64 ",vruntime=%" PRIu64 ")\n",
1431 perf_evsel__strval(evsel, sample, "comm"),
1432 (pid_t)perf_evsel__intval(evsel, sample, "pid"),
1434 perf_evsel__intval(evsel, sample, "vruntime"));
1438 static bool skip_sample(struct trace *trace, struct perf_sample *sample)
1440 if ((trace->pid_list && intlist__find(trace->pid_list, sample->pid)) ||
1441 (trace->tid_list && intlist__find(trace->tid_list, sample->tid)))
1444 if (trace->pid_list || trace->tid_list)
1450 static int trace__process_sample(struct perf_tool *tool,
1451 union perf_event *event __maybe_unused,
1452 struct perf_sample *sample,
1453 struct perf_evsel *evsel,
1454 struct machine *machine __maybe_unused)
1456 struct trace *trace = container_of(tool, struct trace, tool);
1459 tracepoint_handler handler = evsel->handler.func;
1461 if (skip_sample(trace, sample))
1464 if (!trace->full_time && trace->base_time == 0)
1465 trace->base_time = sample->time;
1468 handler(trace, evsel, sample);
1474 perf_session__has_tp(struct perf_session *session, const char *name)
1476 struct perf_evsel *evsel;
1478 evsel = perf_evlist__find_tracepoint_by_name(session->evlist, name);
1480 return evsel != NULL;
1483 static int parse_target_str(struct trace *trace)
1485 if (trace->opts.target.pid) {
1486 trace->pid_list = intlist__new(trace->opts.target.pid);
1487 if (trace->pid_list == NULL) {
1488 pr_err("Error parsing process id string\n");
1493 if (trace->opts.target.tid) {
1494 trace->tid_list = intlist__new(trace->opts.target.tid);
1495 if (trace->tid_list == NULL) {
1496 pr_err("Error parsing thread id string\n");
1504 static int trace__record(int argc, const char **argv)
1506 unsigned int rec_argc, i, j;
1507 const char **rec_argv;
1508 const char * const record_args[] = {
1513 "-e", "raw_syscalls:sys_enter,raw_syscalls:sys_exit",
1516 rec_argc = ARRAY_SIZE(record_args) + argc;
1517 rec_argv = calloc(rec_argc + 1, sizeof(char *));
1519 if (rec_argv == NULL)
1522 for (i = 0; i < ARRAY_SIZE(record_args); i++)
1523 rec_argv[i] = record_args[i];
1525 for (j = 0; j < (unsigned int)argc; j++, i++)
1526 rec_argv[i] = argv[j];
1528 return cmd_record(i, rec_argv, NULL);
1531 static int trace__run(struct trace *trace, int argc, const char **argv)
1533 struct perf_evlist *evlist = perf_evlist__new();
1534 struct perf_evsel *evsel;
1536 unsigned long before;
1537 const bool forks = argc > 0;
1541 if (evlist == NULL) {
1542 fprintf(trace->output, "Not enough memory to run!\n");
1546 if (perf_evlist__add_newtp(evlist, "raw_syscalls", "sys_enter", trace__sys_enter) ||
1547 perf_evlist__add_newtp(evlist, "raw_syscalls", "sys_exit", trace__sys_exit)) {
1548 fprintf(trace->output, "Couldn't read the raw_syscalls tracepoints information!\n");
1549 goto out_delete_evlist;
1553 perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime",
1554 trace__sched_stat_runtime)) {
1555 fprintf(trace->output, "Couldn't read the sched_stat_runtime tracepoint information!\n");
1556 goto out_delete_evlist;
1559 err = perf_evlist__create_maps(evlist, &trace->opts.target);
1561 fprintf(trace->output, "Problems parsing the target to trace, check your options!\n");
1562 goto out_delete_evlist;
1565 err = trace__symbols_init(trace, evlist);
1567 fprintf(trace->output, "Problems initializing symbol libraries!\n");
1568 goto out_delete_maps;
1571 perf_evlist__config(evlist, &trace->opts);
1573 signal(SIGCHLD, sig_handler);
1574 signal(SIGINT, sig_handler);
1577 err = perf_evlist__prepare_workload(evlist, &trace->opts.target,
1578 argv, false, false);
1580 fprintf(trace->output, "Couldn't run the workload!\n");
1581 goto out_delete_maps;
1585 err = perf_evlist__open(evlist);
1587 fprintf(trace->output, "Couldn't create the events: %s\n", strerror(errno));
1588 goto out_delete_maps;
1591 err = perf_evlist__mmap(evlist, UINT_MAX, false);
1593 fprintf(trace->output, "Couldn't mmap the events: %s\n", strerror(errno));
1594 goto out_close_evlist;
1597 perf_evlist__enable(evlist);
1600 perf_evlist__start_workload(evlist);
1602 trace->multiple_threads = evlist->threads->map[0] == -1 || evlist->threads->nr > 1;
1604 before = trace->nr_events;
1606 for (i = 0; i < evlist->nr_mmaps; i++) {
1607 union perf_event *event;
1609 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
1610 const u32 type = event->header.type;
1611 tracepoint_handler handler;
1612 struct perf_sample sample;
1616 err = perf_evlist__parse_sample(evlist, event, &sample);
1618 fprintf(trace->output, "Can't parse sample, err = %d, skipping...\n", err);
1622 if (!trace->full_time && trace->base_time == 0)
1623 trace->base_time = sample.time;
1625 if (type != PERF_RECORD_SAMPLE) {
1626 trace__process_event(trace, trace->host, event);
1630 evsel = perf_evlist__id2evsel(evlist, sample.id);
1631 if (evsel == NULL) {
1632 fprintf(trace->output, "Unknown tp ID %" PRIu64 ", skipping...\n", sample.id);
1636 if (sample.raw_data == NULL) {
1637 fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n",
1638 perf_evsel__name(evsel), sample.tid,
1639 sample.cpu, sample.raw_size);
1643 handler = evsel->handler.func;
1644 handler(trace, evsel, &sample);
1647 goto out_unmap_evlist;
1651 if (trace->nr_events == before) {
1653 goto out_unmap_evlist;
1655 poll(evlist->pollfd, evlist->nr_fds, -1);
1659 perf_evlist__disable(evlist);
1664 perf_evlist__munmap(evlist);
1666 perf_evlist__close(evlist);
1668 perf_evlist__delete_maps(evlist);
1670 perf_evlist__delete(evlist);
1672 trace->live = false;
1676 static int trace__replay(struct trace *trace)
1678 const struct perf_evsel_str_handler handlers[] = {
1679 { "raw_syscalls:sys_enter", trace__sys_enter, },
1680 { "raw_syscalls:sys_exit", trace__sys_exit, },
1683 struct perf_session *session;
1686 trace->tool.sample = trace__process_sample;
1687 trace->tool.mmap = perf_event__process_mmap;
1688 trace->tool.mmap2 = perf_event__process_mmap2;
1689 trace->tool.comm = perf_event__process_comm;
1690 trace->tool.exit = perf_event__process_exit;
1691 trace->tool.fork = perf_event__process_fork;
1692 trace->tool.attr = perf_event__process_attr;
1693 trace->tool.tracing_data = perf_event__process_tracing_data;
1694 trace->tool.build_id = perf_event__process_build_id;
1696 trace->tool.ordered_samples = true;
1697 trace->tool.ordering_requires_timestamps = true;
1699 /* add tid to output */
1700 trace->multiple_threads = true;
1702 if (symbol__init() < 0)
1705 session = perf_session__new(input_name, O_RDONLY, 0, false,
1707 if (session == NULL)
1710 trace->host = &session->machines.host;
1712 err = perf_session__set_tracepoints_handlers(session, handlers);
1716 if (!perf_session__has_tp(session, "raw_syscalls:sys_enter")) {
1717 pr_err("Data file does not have raw_syscalls:sys_enter events\n");
1721 if (!perf_session__has_tp(session, "raw_syscalls:sys_exit")) {
1722 pr_err("Data file does not have raw_syscalls:sys_exit events\n");
1726 err = parse_target_str(trace);
1732 err = perf_session__process_events(session, &trace->tool);
1734 pr_err("Failed to process events, error %d", err);
1737 perf_session__delete(session);
1742 static size_t trace__fprintf_threads_header(FILE *fp)
1746 printed = fprintf(fp, "\n _____________________________________________________________________\n");
1747 printed += fprintf(fp," __) Summary of events (__\n\n");
1748 printed += fprintf(fp," [ task - pid ] [ events ] [ ratio ] [ runtime ]\n");
1749 printed += fprintf(fp," _____________________________________________________________________\n\n");
1754 static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp)
1756 size_t printed = trace__fprintf_threads_header(fp);
1759 for (nd = rb_first(&trace->host->threads); nd; nd = rb_next(nd)) {
1760 struct thread *thread = rb_entry(nd, struct thread, rb_node);
1761 struct thread_trace *ttrace = thread->priv;
1768 ratio = (double)ttrace->nr_events / trace->nr_events * 100.0;
1770 color = PERF_COLOR_NORMAL;
1772 color = PERF_COLOR_RED;
1773 else if (ratio > 25.0)
1774 color = PERF_COLOR_GREEN;
1775 else if (ratio > 5.0)
1776 color = PERF_COLOR_YELLOW;
1778 printed += color_fprintf(fp, color, "%20s", thread->comm);
1779 printed += fprintf(fp, " - %-5d :%11lu [", thread->tid, ttrace->nr_events);
1780 printed += color_fprintf(fp, color, "%5.1f%%", ratio);
1781 printed += fprintf(fp, " ] %10.3f ms\n", ttrace->runtime_ms);
1787 static int trace__set_duration(const struct option *opt, const char *str,
1788 int unset __maybe_unused)
1790 struct trace *trace = opt->value;
1792 trace->duration_filter = atof(str);
1796 static int trace__open_output(struct trace *trace, const char *filename)
1800 if (!stat(filename, &st) && st.st_size) {
1801 char oldname[PATH_MAX];
1803 scnprintf(oldname, sizeof(oldname), "%s.old", filename);
1805 rename(filename, oldname);
1808 trace->output = fopen(filename, "w");
1810 return trace->output == NULL ? -errno : 0;
1813 int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
1815 const char * const trace_usage[] = {
1816 "perf trace [<options>] [<command>]",
1817 "perf trace [<options>] -- <command> [<options>]",
1818 "perf trace record [<options>] [<command>]",
1819 "perf trace record [<options>] -- <command> [<options>]",
1822 struct trace trace = {
1823 .audit_machine = audit_detect_machine(),
1832 .user_freq = UINT_MAX,
1833 .user_interval = ULLONG_MAX,
1840 const char *output_name = NULL;
1841 const char *ev_qualifier_str = NULL;
1842 const struct option trace_options[] = {
1843 OPT_BOOLEAN(0, "comm", &trace.show_comm,
1844 "show the thread COMM next to its id"),
1845 OPT_STRING('e', "expr", &ev_qualifier_str, "expr",
1846 "list of events to trace"),
1847 OPT_STRING('o', "output", &output_name, "file", "output file name"),
1848 OPT_STRING('i', "input", &input_name, "file", "Analyze events in file"),
1849 OPT_STRING('p', "pid", &trace.opts.target.pid, "pid",
1850 "trace events on existing process id"),
1851 OPT_STRING('t', "tid", &trace.opts.target.tid, "tid",
1852 "trace events on existing thread id"),
1853 OPT_BOOLEAN('a', "all-cpus", &trace.opts.target.system_wide,
1854 "system-wide collection from all CPUs"),
1855 OPT_STRING('C', "cpu", &trace.opts.target.cpu_list, "cpu",
1856 "list of cpus to monitor"),
1857 OPT_BOOLEAN(0, "no-inherit", &trace.opts.no_inherit,
1858 "child tasks do not inherit counters"),
1859 OPT_CALLBACK('m', "mmap-pages", &trace.opts.mmap_pages, "pages",
1860 "number of mmap data pages",
1861 perf_evlist__parse_mmap_pages),
1862 OPT_STRING('u', "uid", &trace.opts.target.uid_str, "user",
1864 OPT_CALLBACK(0, "duration", &trace, "float",
1865 "show only events with duration > N.M ms",
1866 trace__set_duration),
1867 OPT_BOOLEAN(0, "sched", &trace.sched, "show blocking scheduler events"),
1868 OPT_INCR('v', "verbose", &verbose, "be more verbose"),
1869 OPT_BOOLEAN('T', "time", &trace.full_time,
1870 "Show full timestamp, not time relative to first start"),
1876 if ((argc > 1) && (strcmp(argv[1], "record") == 0))
1877 return trace__record(argc-2, &argv[2]);
1879 argc = parse_options(argc, argv, trace_options, trace_usage, 0);
1881 if (output_name != NULL) {
1882 err = trace__open_output(&trace, output_name);
1884 perror("failed to create output file");
1889 if (ev_qualifier_str != NULL) {
1890 const char *s = ev_qualifier_str;
1892 trace.not_ev_qualifier = *s == '!';
1893 if (trace.not_ev_qualifier)
1895 trace.ev_qualifier = strlist__new(true, s);
1896 if (trace.ev_qualifier == NULL) {
1897 fputs("Not enough memory to parse event qualifier",
1904 err = perf_target__validate(&trace.opts.target);
1906 perf_target__strerror(&trace.opts.target, err, bf, sizeof(bf));
1907 fprintf(trace.output, "%s", bf);
1911 err = perf_target__parse_uid(&trace.opts.target);
1913 perf_target__strerror(&trace.opts.target, err, bf, sizeof(bf));
1914 fprintf(trace.output, "%s", bf);
1918 if (!argc && perf_target__none(&trace.opts.target))
1919 trace.opts.target.system_wide = true;
1922 err = trace__replay(&trace);
1924 err = trace__run(&trace, argc, argv);
1926 if (trace.sched && !err)
1927 trace__fprintf_thread_summary(&trace, trace.output);
1930 if (output_name != NULL)
1931 fclose(trace.output);