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;
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 machine__init(&trace->host, "", HOST_KERNEL_ID);
1087 machine__create_kernel_maps(&trace->host);
1089 if (perf_target__has_task(&trace->opts.target)) {
1090 err = perf_event__synthesize_thread_map(&trace->tool, evlist->threads,
1091 trace__tool_process,
1094 err = perf_event__synthesize_threads(&trace->tool, trace__tool_process,
1104 static int syscall__set_arg_fmts(struct syscall *sc)
1106 struct format_field *field;
1109 sc->arg_scnprintf = calloc(sc->tp_format->format.nr_fields - 1, sizeof(void *));
1110 if (sc->arg_scnprintf == NULL)
1114 sc->arg_parm = sc->fmt->arg_parm;
1116 for (field = sc->tp_format->format.fields->next; field; field = field->next) {
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)
1120 sc->arg_scnprintf[idx] = syscall_arg__scnprintf_hex;
1127 static int trace__read_syscall_info(struct trace *trace, int id)
1131 const char *name = audit_syscall_to_name(id, trace->audit_machine);
1136 if (id > trace->syscalls.max) {
1137 struct syscall *nsyscalls = realloc(trace->syscalls.table, (id + 1) * sizeof(*sc));
1139 if (nsyscalls == NULL)
1142 if (trace->syscalls.max != -1) {
1143 memset(nsyscalls + trace->syscalls.max + 1, 0,
1144 (id - trace->syscalls.max) * sizeof(*sc));
1146 memset(nsyscalls, 0, (id + 1) * sizeof(*sc));
1149 trace->syscalls.table = nsyscalls;
1150 trace->syscalls.max = id;
1153 sc = trace->syscalls.table + id;
1156 if (trace->ev_qualifier) {
1157 bool in = strlist__find(trace->ev_qualifier, name) != NULL;
1159 if (!(in ^ trace->not_ev_qualifier)) {
1160 sc->filtered = true;
1162 * No need to do read tracepoint information since this will be
1169 sc->fmt = syscall_fmt__find(sc->name);
1171 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name);
1172 sc->tp_format = event_format__new("syscalls", tp_name);
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);
1179 if (sc->tp_format == NULL)
1182 return syscall__set_arg_fmts(sc);
1185 static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
1186 unsigned long *args, struct trace *trace,
1187 struct thread *thread)
1191 if (sc->tp_format != NULL) {
1192 struct format_field *field;
1194 struct syscall_arg arg = {
1201 for (field = sc->tp_format->format.fields->next; field;
1202 field = field->next, ++arg.idx, bit <<= 1) {
1206 * Suppress this argument if its value is zero and
1207 * and we don't have a string associated in an
1210 if (args[arg.idx] == 0 &&
1211 !(sc->arg_scnprintf &&
1212 sc->arg_scnprintf[arg.idx] == SCA_STRARRAY &&
1213 sc->arg_parm[arg.idx]))
1216 printed += scnprintf(bf + printed, size - printed,
1217 "%s%s: ", printed ? ", " : "", field->name);
1218 if (sc->arg_scnprintf && sc->arg_scnprintf[arg.idx]) {
1219 arg.val = args[arg.idx];
1221 arg.parm = sc->arg_parm[arg.idx];
1222 printed += sc->arg_scnprintf[arg.idx](bf + printed,
1223 size - printed, &arg);
1225 printed += scnprintf(bf + printed, size - printed,
1226 "%ld", args[arg.idx]);
1233 printed += scnprintf(bf + printed, size - printed,
1235 printed ? ", " : "", i, args[i]);
1243 typedef int (*tracepoint_handler)(struct trace *trace, struct perf_evsel *evsel,
1244 struct perf_sample *sample);
1246 static struct syscall *trace__syscall_info(struct trace *trace,
1247 struct perf_evsel *evsel,
1248 struct perf_sample *sample)
1250 int id = perf_evsel__intval(evsel, sample, "id");
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:
1259 * echo 1 > /t/events/raw_syscalls/sys_exit/enable
1260 * grep "NR -1 " /t/trace_pipe
1262 * After generating some load on the machine.
1266 fprintf(trace->output, "Invalid syscall %d id, skipping (%s, %" PRIu64 ") ...\n",
1267 id, perf_evsel__name(evsel), ++n);
1272 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL) &&
1273 trace__read_syscall_info(trace, id))
1276 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL))
1279 return &trace->syscalls.table[id];
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);
1291 static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
1292 struct perf_sample *sample)
1297 struct thread *thread;
1298 struct syscall *sc = trace__syscall_info(trace, evsel, sample);
1299 struct thread_trace *ttrace;
1307 thread = machine__findnew_thread(&trace->host, sample->pid,
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,
1362 ttrace = thread__trace(thread, trace->output);
1366 ret = perf_evsel__intval(evsel, sample, "ret");
1368 ttrace = thread->priv;
1370 ttrace->exit_time = sample->time;
1372 if (ttrace->entry_time) {
1373 duration = sample->time - ttrace->entry_time;
1374 if (trace__filter_duration(trace, duration))
1376 } else if (trace->duration_filter)
1379 trace__fprintf_entry_head(trace, thread, duration, sample->time, trace->output);
1381 if (ttrace->entry_pending) {
1382 fprintf(trace->output, "%-70s", ttrace->entry_str);
1384 fprintf(trace->output, " ... [");
1385 color_fprintf(trace->output, PERF_COLOR_YELLOW, "continued");
1386 fprintf(trace->output, "]: %s()", sc->name);
1389 if (sc->fmt == NULL) {
1391 fprintf(trace->output, ") = %d", ret);
1392 } else if (ret < 0 && sc->fmt->errmsg) {
1394 const char *emsg = strerror_r(-ret, bf, sizeof(bf)),
1395 *e = audit_errno_to_name(-ret);
1397 fprintf(trace->output, ") = -1 %s %s", e, emsg);
1398 } else if (ret == 0 && sc->fmt->timeout)
1399 fprintf(trace->output, ") = 0 Timeout");
1400 else if (sc->fmt->hexret)
1401 fprintf(trace->output, ") = %#x", ret);
1405 fputc('\n', trace->output);
1407 ttrace->entry_pending = false;
1412 static int trace__sched_stat_runtime(struct trace *trace, struct perf_evsel *evsel,
1413 struct perf_sample *sample)
1415 u64 runtime = perf_evsel__intval(evsel, sample, "runtime");
1416 double runtime_ms = (double)runtime / NSEC_PER_MSEC;
1417 struct thread *thread = machine__findnew_thread(&trace->host,
1420 struct thread_trace *ttrace = thread__trace(thread, trace->output);
1425 ttrace->runtime_ms += runtime_ms;
1426 trace->runtime_ms += runtime_ms;
1430 fprintf(trace->output, "%s: comm=%s,pid=%u,runtime=%" PRIu64 ",vruntime=%" PRIu64 ")\n",
1432 perf_evsel__strval(evsel, sample, "comm"),
1433 (pid_t)perf_evsel__intval(evsel, sample, "pid"),
1435 perf_evsel__intval(evsel, sample, "vruntime"));
1439 static bool skip_sample(struct trace *trace, struct perf_sample *sample)
1441 if ((trace->pid_list && intlist__find(trace->pid_list, sample->pid)) ||
1442 (trace->tid_list && intlist__find(trace->tid_list, sample->tid)))
1445 if (trace->pid_list || trace->tid_list)
1451 static 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)
1457 struct trace *trace = container_of(tool, struct trace, tool);
1460 tracepoint_handler handler = evsel->handler.func;
1462 if (skip_sample(trace, sample))
1465 if (!trace->full_time && trace->base_time == 0)
1466 trace->base_time = sample->time;
1469 handler(trace, evsel, sample);
1475 perf_session__has_tp(struct perf_session *session, const char *name)
1477 struct perf_evsel *evsel;
1479 evsel = perf_evlist__find_tracepoint_by_name(session->evlist, name);
1481 return evsel != NULL;
1484 static int parse_target_str(struct trace *trace)
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");
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");
1505 static int trace__run(struct trace *trace, int argc, const char **argv)
1507 struct perf_evlist *evlist = perf_evlist__new();
1508 struct perf_evsel *evsel;
1510 unsigned long before;
1511 const bool forks = argc > 0;
1515 if (evlist == NULL) {
1516 fprintf(trace->output, "Not enough memory to run!\n");
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)) {
1522 fprintf(trace->output, "Couldn't read the raw_syscalls tracepoints information!\n");
1523 goto out_delete_evlist;
1527 perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime",
1528 trace__sched_stat_runtime)) {
1529 fprintf(trace->output, "Couldn't read the sched_stat_runtime tracepoint information!\n");
1530 goto out_delete_evlist;
1533 err = perf_evlist__create_maps(evlist, &trace->opts.target);
1535 fprintf(trace->output, "Problems parsing the target to trace, check your options!\n");
1536 goto out_delete_evlist;
1539 err = trace__symbols_init(trace, evlist);
1541 fprintf(trace->output, "Problems initializing symbol libraries!\n");
1542 goto out_delete_maps;
1545 perf_evlist__config(evlist, &trace->opts);
1547 signal(SIGCHLD, sig_handler);
1548 signal(SIGINT, sig_handler);
1551 err = perf_evlist__prepare_workload(evlist, &trace->opts.target,
1552 argv, false, false);
1554 fprintf(trace->output, "Couldn't run the workload!\n");
1555 goto out_delete_maps;
1559 err = perf_evlist__open(evlist);
1561 fprintf(trace->output, "Couldn't create the events: %s\n", strerror(errno));
1562 goto out_delete_maps;
1565 err = perf_evlist__mmap(evlist, UINT_MAX, false);
1567 fprintf(trace->output, "Couldn't mmap the events: %s\n", strerror(errno));
1568 goto out_close_evlist;
1571 perf_evlist__enable(evlist);
1574 perf_evlist__start_workload(evlist);
1576 trace->multiple_threads = evlist->threads->map[0] == -1 || evlist->threads->nr > 1;
1578 before = trace->nr_events;
1580 for (i = 0; i < evlist->nr_mmaps; i++) {
1581 union perf_event *event;
1583 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
1584 const u32 type = event->header.type;
1585 tracepoint_handler handler;
1586 struct perf_sample sample;
1590 err = perf_evlist__parse_sample(evlist, event, &sample);
1592 fprintf(trace->output, "Can't parse sample, err = %d, skipping...\n", err);
1596 if (!trace->full_time && trace->base_time == 0)
1597 trace->base_time = sample.time;
1599 if (type != PERF_RECORD_SAMPLE) {
1600 trace__process_event(trace, &trace->host, event);
1604 evsel = perf_evlist__id2evsel(evlist, sample.id);
1605 if (evsel == NULL) {
1606 fprintf(trace->output, "Unknown tp ID %" PRIu64 ", skipping...\n", sample.id);
1610 if (sample.raw_data == NULL) {
1611 fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n",
1612 perf_evsel__name(evsel), sample.tid,
1613 sample.cpu, sample.raw_size);
1617 handler = evsel->handler.func;
1618 handler(trace, evsel, &sample);
1621 goto out_unmap_evlist;
1625 if (trace->nr_events == before) {
1627 goto out_unmap_evlist;
1629 poll(evlist->pollfd, evlist->nr_fds, -1);
1633 perf_evlist__disable(evlist);
1638 perf_evlist__munmap(evlist);
1640 perf_evlist__close(evlist);
1642 perf_evlist__delete_maps(evlist);
1644 perf_evlist__delete(evlist);
1646 trace->live = false;
1650 static int trace__replay(struct trace *trace)
1652 const struct perf_evsel_str_handler handlers[] = {
1653 { "raw_syscalls:sys_enter", trace__sys_enter, },
1654 { "raw_syscalls:sys_exit", trace__sys_exit, },
1657 struct perf_session *session;
1660 trace->tool.sample = trace__process_sample;
1661 trace->tool.mmap = perf_event__process_mmap;
1662 trace->tool.mmap2 = perf_event__process_mmap2;
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;
1670 trace->tool.ordered_samples = true;
1671 trace->tool.ordering_requires_timestamps = true;
1673 /* add tid to output */
1674 trace->multiple_threads = true;
1676 if (symbol__init() < 0)
1679 session = perf_session__new(input_name, O_RDONLY, 0, false,
1681 if (session == NULL)
1684 err = perf_session__set_tracepoints_handlers(session, handlers);
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");
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");
1698 err = parse_target_str(trace);
1704 err = perf_session__process_events(session, &trace->tool);
1706 pr_err("Failed to process events, error %d", err);
1709 perf_session__delete(session);
1714 static size_t trace__fprintf_threads_header(FILE *fp)
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");
1726 static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp)
1728 size_t printed = trace__fprintf_threads_header(fp);
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;
1740 ratio = (double)ttrace->nr_events / trace->nr_events * 100.0;
1742 color = PERF_COLOR_NORMAL;
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;
1750 printed += color_fprintf(fp, color, "%20s", thread->comm);
1751 printed += fprintf(fp, " - %-5d :%11lu [", thread->tid, ttrace->nr_events);
1752 printed += color_fprintf(fp, color, "%5.1f%%", ratio);
1753 printed += fprintf(fp, " ] %10.3f ms\n", ttrace->runtime_ms);
1759 static int trace__set_duration(const struct option *opt, const char *str,
1760 int unset __maybe_unused)
1762 struct trace *trace = opt->value;
1764 trace->duration_filter = atof(str);
1768 static int trace__open_output(struct trace *trace, const char *filename)
1772 if (!stat(filename, &st) && st.st_size) {
1773 char oldname[PATH_MAX];
1775 scnprintf(oldname, sizeof(oldname), "%s.old", filename);
1777 rename(filename, oldname);
1780 trace->output = fopen(filename, "w");
1782 return trace->output == NULL ? -errno : 0;
1785 int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
1787 const char * const trace_usage[] = {
1788 "perf trace [<options>] [<command>]",
1789 "perf trace [<options>] -- <command> [<options>]",
1792 struct trace trace = {
1793 .audit_machine = audit_detect_machine(),
1802 .user_freq = UINT_MAX,
1803 .user_interval = ULLONG_MAX,
1810 const char *output_name = NULL;
1811 const char *ev_qualifier_str = NULL;
1812 const struct option trace_options[] = {
1813 OPT_BOOLEAN(0, "comm", &trace.show_comm,
1814 "show the thread COMM next to its id"),
1815 OPT_STRING('e', "expr", &ev_qualifier_str, "expr",
1816 "list of events to trace"),
1817 OPT_STRING('o', "output", &output_name, "file", "output file name"),
1818 OPT_STRING('i', "input", &input_name, "file", "Analyze events in file"),
1819 OPT_STRING('p', "pid", &trace.opts.target.pid, "pid",
1820 "trace events on existing process id"),
1821 OPT_STRING('t', "tid", &trace.opts.target.tid, "tid",
1822 "trace events on existing thread id"),
1823 OPT_BOOLEAN('a', "all-cpus", &trace.opts.target.system_wide,
1824 "system-wide collection from all CPUs"),
1825 OPT_STRING('C', "cpu", &trace.opts.target.cpu_list, "cpu",
1826 "list of cpus to monitor"),
1827 OPT_BOOLEAN(0, "no-inherit", &trace.opts.no_inherit,
1828 "child tasks do not inherit counters"),
1829 OPT_CALLBACK('m', "mmap-pages", &trace.opts.mmap_pages, "pages",
1830 "number of mmap data pages",
1831 perf_evlist__parse_mmap_pages),
1832 OPT_STRING('u', "uid", &trace.opts.target.uid_str, "user",
1834 OPT_CALLBACK(0, "duration", &trace, "float",
1835 "show only events with duration > N.M ms",
1836 trace__set_duration),
1837 OPT_BOOLEAN(0, "sched", &trace.sched, "show blocking scheduler events"),
1838 OPT_INCR('v', "verbose", &verbose, "be more verbose"),
1839 OPT_BOOLEAN('T', "time", &trace.full_time,
1840 "Show full timestamp, not time relative to first start"),
1846 argc = parse_options(argc, argv, trace_options, trace_usage, 0);
1848 if (output_name != NULL) {
1849 err = trace__open_output(&trace, output_name);
1851 perror("failed to create output file");
1856 if (ev_qualifier_str != NULL) {
1857 const char *s = ev_qualifier_str;
1859 trace.not_ev_qualifier = *s == '!';
1860 if (trace.not_ev_qualifier)
1862 trace.ev_qualifier = strlist__new(true, s);
1863 if (trace.ev_qualifier == NULL) {
1864 fputs("Not enough memory to parse event qualifier",
1871 err = perf_target__validate(&trace.opts.target);
1873 perf_target__strerror(&trace.opts.target, err, bf, sizeof(bf));
1874 fprintf(trace.output, "%s", bf);
1878 err = perf_target__parse_uid(&trace.opts.target);
1880 perf_target__strerror(&trace.opts.target, err, bf, sizeof(bf));
1881 fprintf(trace.output, "%s", bf);
1885 if (!argc && perf_target__none(&trace.opts.target))
1886 trace.opts.target.system_wide = true;
1889 err = trace__replay(&trace);
1891 err = trace__run(&trace, argc, argv);
1893 if (trace.sched && !err)
1894 trace__fprintf_thread_summary(&trace, trace.output);
1897 if (output_name != NULL)
1898 fclose(trace.output);