iio: imu: mpu6050: Move config entry into IMU menu
[linux-2.6/btrfs-unstable.git] / tools / perf / builtin-trace.c
blob8be17fc462baff466a6aa25682f804c4b5fdd1dc
1 #include <traceevent/event-parse.h>
2 #include "builtin.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"
13 #include "util/stat.h"
15 #include <libaudit.h>
16 #include <stdlib.h>
17 #include <sys/eventfd.h>
18 #include <sys/mman.h>
19 #include <linux/futex.h>
21 /* For older distros: */
22 #ifndef MAP_STACK
23 # define MAP_STACK 0x20000
24 #endif
26 #ifndef MADV_HWPOISON
27 # define MADV_HWPOISON 100
28 #endif
30 #ifndef MADV_MERGEABLE
31 # define MADV_MERGEABLE 12
32 #endif
34 #ifndef MADV_UNMERGEABLE
35 # define MADV_UNMERGEABLE 13
36 #endif
38 struct tp_field {
39 int offset;
40 union {
41 u64 (*integer)(struct tp_field *field, struct perf_sample *sample);
42 void *(*pointer)(struct tp_field *field, struct perf_sample *sample);
46 #define TP_UINT_FIELD(bits) \
47 static u64 tp_field__u##bits(struct tp_field *field, struct perf_sample *sample) \
48 { \
49 return *(u##bits *)(sample->raw_data + field->offset); \
52 TP_UINT_FIELD(8);
53 TP_UINT_FIELD(16);
54 TP_UINT_FIELD(32);
55 TP_UINT_FIELD(64);
57 #define TP_UINT_FIELD__SWAPPED(bits) \
58 static u64 tp_field__swapped_u##bits(struct tp_field *field, struct perf_sample *sample) \
59 { \
60 u##bits value = *(u##bits *)(sample->raw_data + field->offset); \
61 return bswap_##bits(value);\
64 TP_UINT_FIELD__SWAPPED(16);
65 TP_UINT_FIELD__SWAPPED(32);
66 TP_UINT_FIELD__SWAPPED(64);
68 static int tp_field__init_uint(struct tp_field *field,
69 struct format_field *format_field,
70 bool needs_swap)
72 field->offset = format_field->offset;
74 switch (format_field->size) {
75 case 1:
76 field->integer = tp_field__u8;
77 break;
78 case 2:
79 field->integer = needs_swap ? tp_field__swapped_u16 : tp_field__u16;
80 break;
81 case 4:
82 field->integer = needs_swap ? tp_field__swapped_u32 : tp_field__u32;
83 break;
84 case 8:
85 field->integer = needs_swap ? tp_field__swapped_u64 : tp_field__u64;
86 break;
87 default:
88 return -1;
91 return 0;
94 static void *tp_field__ptr(struct tp_field *field, struct perf_sample *sample)
96 return sample->raw_data + field->offset;
99 static int tp_field__init_ptr(struct tp_field *field, struct format_field *format_field)
101 field->offset = format_field->offset;
102 field->pointer = tp_field__ptr;
103 return 0;
106 struct syscall_tp {
107 struct tp_field id;
108 union {
109 struct tp_field args, ret;
113 static int perf_evsel__init_tp_uint_field(struct perf_evsel *evsel,
114 struct tp_field *field,
115 const char *name)
117 struct format_field *format_field = perf_evsel__field(evsel, name);
119 if (format_field == NULL)
120 return -1;
122 return tp_field__init_uint(field, format_field, evsel->needs_swap);
125 #define perf_evsel__init_sc_tp_uint_field(evsel, name) \
126 ({ struct syscall_tp *sc = evsel->priv;\
127 perf_evsel__init_tp_uint_field(evsel, &sc->name, #name); })
129 static int perf_evsel__init_tp_ptr_field(struct perf_evsel *evsel,
130 struct tp_field *field,
131 const char *name)
133 struct format_field *format_field = perf_evsel__field(evsel, name);
135 if (format_field == NULL)
136 return -1;
138 return tp_field__init_ptr(field, format_field);
141 #define perf_evsel__init_sc_tp_ptr_field(evsel, name) \
142 ({ struct syscall_tp *sc = evsel->priv;\
143 perf_evsel__init_tp_ptr_field(evsel, &sc->name, #name); })
145 static void perf_evsel__delete_priv(struct perf_evsel *evsel)
147 free(evsel->priv);
148 evsel->priv = NULL;
149 perf_evsel__delete(evsel);
152 static int perf_evsel__init_syscall_tp(struct perf_evsel *evsel, void *handler)
154 evsel->priv = malloc(sizeof(struct syscall_tp));
155 if (evsel->priv != NULL) {
156 if (perf_evsel__init_sc_tp_uint_field(evsel, id))
157 goto out_delete;
159 evsel->handler = handler;
160 return 0;
163 return -ENOMEM;
165 out_delete:
166 free(evsel->priv);
167 evsel->priv = NULL;
168 return -ENOENT;
171 static struct perf_evsel *perf_evsel__syscall_newtp(const char *direction, void *handler)
173 struct perf_evsel *evsel = perf_evsel__newtp("raw_syscalls", direction);
175 if (evsel) {
176 if (perf_evsel__init_syscall_tp(evsel, handler))
177 goto out_delete;
180 return evsel;
182 out_delete:
183 perf_evsel__delete_priv(evsel);
184 return NULL;
187 #define perf_evsel__sc_tp_uint(evsel, name, sample) \
188 ({ struct syscall_tp *fields = evsel->priv; \
189 fields->name.integer(&fields->name, sample); })
191 #define perf_evsel__sc_tp_ptr(evsel, name, sample) \
192 ({ struct syscall_tp *fields = evsel->priv; \
193 fields->name.pointer(&fields->name, sample); })
195 static int perf_evlist__add_syscall_newtp(struct perf_evlist *evlist,
196 void *sys_enter_handler,
197 void *sys_exit_handler)
199 int ret = -1;
200 struct perf_evsel *sys_enter, *sys_exit;
202 sys_enter = perf_evsel__syscall_newtp("sys_enter", sys_enter_handler);
203 if (sys_enter == NULL)
204 goto out;
206 if (perf_evsel__init_sc_tp_ptr_field(sys_enter, args))
207 goto out_delete_sys_enter;
209 sys_exit = perf_evsel__syscall_newtp("sys_exit", sys_exit_handler);
210 if (sys_exit == NULL)
211 goto out_delete_sys_enter;
213 if (perf_evsel__init_sc_tp_uint_field(sys_exit, ret))
214 goto out_delete_sys_exit;
216 perf_evlist__add(evlist, sys_enter);
217 perf_evlist__add(evlist, sys_exit);
219 ret = 0;
220 out:
221 return ret;
223 out_delete_sys_exit:
224 perf_evsel__delete_priv(sys_exit);
225 out_delete_sys_enter:
226 perf_evsel__delete_priv(sys_enter);
227 goto out;
231 struct syscall_arg {
232 unsigned long val;
233 struct thread *thread;
234 struct trace *trace;
235 void *parm;
236 u8 idx;
237 u8 mask;
240 struct strarray {
241 int offset;
242 int nr_entries;
243 const char **entries;
246 #define DEFINE_STRARRAY(array) struct strarray strarray__##array = { \
247 .nr_entries = ARRAY_SIZE(array), \
248 .entries = array, \
251 #define DEFINE_STRARRAY_OFFSET(array, off) struct strarray strarray__##array = { \
252 .offset = off, \
253 .nr_entries = ARRAY_SIZE(array), \
254 .entries = array, \
257 static size_t __syscall_arg__scnprintf_strarray(char *bf, size_t size,
258 const char *intfmt,
259 struct syscall_arg *arg)
261 struct strarray *sa = arg->parm;
262 int idx = arg->val - sa->offset;
264 if (idx < 0 || idx >= sa->nr_entries)
265 return scnprintf(bf, size, intfmt, arg->val);
267 return scnprintf(bf, size, "%s", sa->entries[idx]);
270 static size_t syscall_arg__scnprintf_strarray(char *bf, size_t size,
271 struct syscall_arg *arg)
273 return __syscall_arg__scnprintf_strarray(bf, size, "%d", arg);
276 #define SCA_STRARRAY syscall_arg__scnprintf_strarray
278 static size_t syscall_arg__scnprintf_strhexarray(char *bf, size_t size,
279 struct syscall_arg *arg)
281 return __syscall_arg__scnprintf_strarray(bf, size, "%#x", arg);
284 #define SCA_STRHEXARRAY syscall_arg__scnprintf_strhexarray
286 static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
287 struct syscall_arg *arg);
289 #define SCA_FD syscall_arg__scnprintf_fd
291 static size_t syscall_arg__scnprintf_fd_at(char *bf, size_t size,
292 struct syscall_arg *arg)
294 int fd = arg->val;
296 if (fd == AT_FDCWD)
297 return scnprintf(bf, size, "CWD");
299 return syscall_arg__scnprintf_fd(bf, size, arg);
302 #define SCA_FDAT syscall_arg__scnprintf_fd_at
304 static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
305 struct syscall_arg *arg);
307 #define SCA_CLOSE_FD syscall_arg__scnprintf_close_fd
309 static size_t syscall_arg__scnprintf_hex(char *bf, size_t size,
310 struct syscall_arg *arg)
312 return scnprintf(bf, size, "%#lx", arg->val);
315 #define SCA_HEX syscall_arg__scnprintf_hex
317 static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size,
318 struct syscall_arg *arg)
320 int printed = 0, prot = arg->val;
322 if (prot == PROT_NONE)
323 return scnprintf(bf, size, "NONE");
324 #define P_MMAP_PROT(n) \
325 if (prot & PROT_##n) { \
326 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
327 prot &= ~PROT_##n; \
330 P_MMAP_PROT(EXEC);
331 P_MMAP_PROT(READ);
332 P_MMAP_PROT(WRITE);
333 #ifdef PROT_SEM
334 P_MMAP_PROT(SEM);
335 #endif
336 P_MMAP_PROT(GROWSDOWN);
337 P_MMAP_PROT(GROWSUP);
338 #undef P_MMAP_PROT
340 if (prot)
341 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", prot);
343 return printed;
346 #define SCA_MMAP_PROT syscall_arg__scnprintf_mmap_prot
348 static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size,
349 struct syscall_arg *arg)
351 int printed = 0, flags = arg->val;
353 #define P_MMAP_FLAG(n) \
354 if (flags & MAP_##n) { \
355 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
356 flags &= ~MAP_##n; \
359 P_MMAP_FLAG(SHARED);
360 P_MMAP_FLAG(PRIVATE);
361 #ifdef MAP_32BIT
362 P_MMAP_FLAG(32BIT);
363 #endif
364 P_MMAP_FLAG(ANONYMOUS);
365 P_MMAP_FLAG(DENYWRITE);
366 P_MMAP_FLAG(EXECUTABLE);
367 P_MMAP_FLAG(FILE);
368 P_MMAP_FLAG(FIXED);
369 P_MMAP_FLAG(GROWSDOWN);
370 #ifdef MAP_HUGETLB
371 P_MMAP_FLAG(HUGETLB);
372 #endif
373 P_MMAP_FLAG(LOCKED);
374 P_MMAP_FLAG(NONBLOCK);
375 P_MMAP_FLAG(NORESERVE);
376 P_MMAP_FLAG(POPULATE);
377 P_MMAP_FLAG(STACK);
378 #ifdef MAP_UNINITIALIZED
379 P_MMAP_FLAG(UNINITIALIZED);
380 #endif
381 #undef P_MMAP_FLAG
383 if (flags)
384 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
386 return printed;
389 #define SCA_MMAP_FLAGS syscall_arg__scnprintf_mmap_flags
391 static size_t syscall_arg__scnprintf_madvise_behavior(char *bf, size_t size,
392 struct syscall_arg *arg)
394 int behavior = arg->val;
396 switch (behavior) {
397 #define P_MADV_BHV(n) case MADV_##n: return scnprintf(bf, size, #n)
398 P_MADV_BHV(NORMAL);
399 P_MADV_BHV(RANDOM);
400 P_MADV_BHV(SEQUENTIAL);
401 P_MADV_BHV(WILLNEED);
402 P_MADV_BHV(DONTNEED);
403 P_MADV_BHV(REMOVE);
404 P_MADV_BHV(DONTFORK);
405 P_MADV_BHV(DOFORK);
406 P_MADV_BHV(HWPOISON);
407 #ifdef MADV_SOFT_OFFLINE
408 P_MADV_BHV(SOFT_OFFLINE);
409 #endif
410 P_MADV_BHV(MERGEABLE);
411 P_MADV_BHV(UNMERGEABLE);
412 #ifdef MADV_HUGEPAGE
413 P_MADV_BHV(HUGEPAGE);
414 #endif
415 #ifdef MADV_NOHUGEPAGE
416 P_MADV_BHV(NOHUGEPAGE);
417 #endif
418 #ifdef MADV_DONTDUMP
419 P_MADV_BHV(DONTDUMP);
420 #endif
421 #ifdef MADV_DODUMP
422 P_MADV_BHV(DODUMP);
423 #endif
424 #undef P_MADV_PHV
425 default: break;
428 return scnprintf(bf, size, "%#x", behavior);
431 #define SCA_MADV_BHV syscall_arg__scnprintf_madvise_behavior
433 static size_t syscall_arg__scnprintf_flock(char *bf, size_t size,
434 struct syscall_arg *arg)
436 int printed = 0, op = arg->val;
438 if (op == 0)
439 return scnprintf(bf, size, "NONE");
440 #define P_CMD(cmd) \
441 if ((op & LOCK_##cmd) == LOCK_##cmd) { \
442 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #cmd); \
443 op &= ~LOCK_##cmd; \
446 P_CMD(SH);
447 P_CMD(EX);
448 P_CMD(NB);
449 P_CMD(UN);
450 P_CMD(MAND);
451 P_CMD(RW);
452 P_CMD(READ);
453 P_CMD(WRITE);
454 #undef P_OP
456 if (op)
457 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", op);
459 return printed;
462 #define SCA_FLOCK syscall_arg__scnprintf_flock
464 static size_t syscall_arg__scnprintf_futex_op(char *bf, size_t size, struct syscall_arg *arg)
466 enum syscall_futex_args {
467 SCF_UADDR = (1 << 0),
468 SCF_OP = (1 << 1),
469 SCF_VAL = (1 << 2),
470 SCF_TIMEOUT = (1 << 3),
471 SCF_UADDR2 = (1 << 4),
472 SCF_VAL3 = (1 << 5),
474 int op = arg->val;
475 int cmd = op & FUTEX_CMD_MASK;
476 size_t printed = 0;
478 switch (cmd) {
479 #define P_FUTEX_OP(n) case FUTEX_##n: printed = scnprintf(bf, size, #n);
480 P_FUTEX_OP(WAIT); arg->mask |= SCF_VAL3|SCF_UADDR2; break;
481 P_FUTEX_OP(WAKE); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
482 P_FUTEX_OP(FD); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
483 P_FUTEX_OP(REQUEUE); arg->mask |= SCF_VAL3|SCF_TIMEOUT; break;
484 P_FUTEX_OP(CMP_REQUEUE); arg->mask |= SCF_TIMEOUT; break;
485 P_FUTEX_OP(CMP_REQUEUE_PI); arg->mask |= SCF_TIMEOUT; break;
486 P_FUTEX_OP(WAKE_OP); break;
487 P_FUTEX_OP(LOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
488 P_FUTEX_OP(UNLOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
489 P_FUTEX_OP(TRYLOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2; break;
490 P_FUTEX_OP(WAIT_BITSET); arg->mask |= SCF_UADDR2; break;
491 P_FUTEX_OP(WAKE_BITSET); arg->mask |= SCF_UADDR2; break;
492 P_FUTEX_OP(WAIT_REQUEUE_PI); break;
493 default: printed = scnprintf(bf, size, "%#x", cmd); break;
496 if (op & FUTEX_PRIVATE_FLAG)
497 printed += scnprintf(bf + printed, size - printed, "|PRIV");
499 if (op & FUTEX_CLOCK_REALTIME)
500 printed += scnprintf(bf + printed, size - printed, "|CLKRT");
502 return printed;
505 #define SCA_FUTEX_OP syscall_arg__scnprintf_futex_op
507 static const char *epoll_ctl_ops[] = { "ADD", "DEL", "MOD", };
508 static DEFINE_STRARRAY_OFFSET(epoll_ctl_ops, 1);
510 static const char *itimers[] = { "REAL", "VIRTUAL", "PROF", };
511 static DEFINE_STRARRAY(itimers);
513 static const char *whences[] = { "SET", "CUR", "END",
514 #ifdef SEEK_DATA
515 "DATA",
516 #endif
517 #ifdef SEEK_HOLE
518 "HOLE",
519 #endif
521 static DEFINE_STRARRAY(whences);
523 static const char *fcntl_cmds[] = {
524 "DUPFD", "GETFD", "SETFD", "GETFL", "SETFL", "GETLK", "SETLK",
525 "SETLKW", "SETOWN", "GETOWN", "SETSIG", "GETSIG", "F_GETLK64",
526 "F_SETLK64", "F_SETLKW64", "F_SETOWN_EX", "F_GETOWN_EX",
527 "F_GETOWNER_UIDS",
529 static DEFINE_STRARRAY(fcntl_cmds);
531 static const char *rlimit_resources[] = {
532 "CPU", "FSIZE", "DATA", "STACK", "CORE", "RSS", "NPROC", "NOFILE",
533 "MEMLOCK", "AS", "LOCKS", "SIGPENDING", "MSGQUEUE", "NICE", "RTPRIO",
534 "RTTIME",
536 static DEFINE_STRARRAY(rlimit_resources);
538 static const char *sighow[] = { "BLOCK", "UNBLOCK", "SETMASK", };
539 static DEFINE_STRARRAY(sighow);
541 static const char *clockid[] = {
542 "REALTIME", "MONOTONIC", "PROCESS_CPUTIME_ID", "THREAD_CPUTIME_ID",
543 "MONOTONIC_RAW", "REALTIME_COARSE", "MONOTONIC_COARSE",
545 static DEFINE_STRARRAY(clockid);
547 static const char *socket_families[] = {
548 "UNSPEC", "LOCAL", "INET", "AX25", "IPX", "APPLETALK", "NETROM",
549 "BRIDGE", "ATMPVC", "X25", "INET6", "ROSE", "DECnet", "NETBEUI",
550 "SECURITY", "KEY", "NETLINK", "PACKET", "ASH", "ECONET", "ATMSVC",
551 "RDS", "SNA", "IRDA", "PPPOX", "WANPIPE", "LLC", "IB", "CAN", "TIPC",
552 "BLUETOOTH", "IUCV", "RXRPC", "ISDN", "PHONET", "IEEE802154", "CAIF",
553 "ALG", "NFC", "VSOCK",
555 static DEFINE_STRARRAY(socket_families);
557 #ifndef SOCK_TYPE_MASK
558 #define SOCK_TYPE_MASK 0xf
559 #endif
561 static size_t syscall_arg__scnprintf_socket_type(char *bf, size_t size,
562 struct syscall_arg *arg)
564 size_t printed;
565 int type = arg->val,
566 flags = type & ~SOCK_TYPE_MASK;
568 type &= SOCK_TYPE_MASK;
570 * Can't use a strarray, MIPS may override for ABI reasons.
572 switch (type) {
573 #define P_SK_TYPE(n) case SOCK_##n: printed = scnprintf(bf, size, #n); break;
574 P_SK_TYPE(STREAM);
575 P_SK_TYPE(DGRAM);
576 P_SK_TYPE(RAW);
577 P_SK_TYPE(RDM);
578 P_SK_TYPE(SEQPACKET);
579 P_SK_TYPE(DCCP);
580 P_SK_TYPE(PACKET);
581 #undef P_SK_TYPE
582 default:
583 printed = scnprintf(bf, size, "%#x", type);
586 #define P_SK_FLAG(n) \
587 if (flags & SOCK_##n) { \
588 printed += scnprintf(bf + printed, size - printed, "|%s", #n); \
589 flags &= ~SOCK_##n; \
592 P_SK_FLAG(CLOEXEC);
593 P_SK_FLAG(NONBLOCK);
594 #undef P_SK_FLAG
596 if (flags)
597 printed += scnprintf(bf + printed, size - printed, "|%#x", flags);
599 return printed;
602 #define SCA_SK_TYPE syscall_arg__scnprintf_socket_type
604 #ifndef MSG_PROBE
605 #define MSG_PROBE 0x10
606 #endif
607 #ifndef MSG_WAITFORONE
608 #define MSG_WAITFORONE 0x10000
609 #endif
610 #ifndef MSG_SENDPAGE_NOTLAST
611 #define MSG_SENDPAGE_NOTLAST 0x20000
612 #endif
613 #ifndef MSG_FASTOPEN
614 #define MSG_FASTOPEN 0x20000000
615 #endif
617 static size_t syscall_arg__scnprintf_msg_flags(char *bf, size_t size,
618 struct syscall_arg *arg)
620 int printed = 0, flags = arg->val;
622 if (flags == 0)
623 return scnprintf(bf, size, "NONE");
624 #define P_MSG_FLAG(n) \
625 if (flags & MSG_##n) { \
626 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
627 flags &= ~MSG_##n; \
630 P_MSG_FLAG(OOB);
631 P_MSG_FLAG(PEEK);
632 P_MSG_FLAG(DONTROUTE);
633 P_MSG_FLAG(TRYHARD);
634 P_MSG_FLAG(CTRUNC);
635 P_MSG_FLAG(PROBE);
636 P_MSG_FLAG(TRUNC);
637 P_MSG_FLAG(DONTWAIT);
638 P_MSG_FLAG(EOR);
639 P_MSG_FLAG(WAITALL);
640 P_MSG_FLAG(FIN);
641 P_MSG_FLAG(SYN);
642 P_MSG_FLAG(CONFIRM);
643 P_MSG_FLAG(RST);
644 P_MSG_FLAG(ERRQUEUE);
645 P_MSG_FLAG(NOSIGNAL);
646 P_MSG_FLAG(MORE);
647 P_MSG_FLAG(WAITFORONE);
648 P_MSG_FLAG(SENDPAGE_NOTLAST);
649 P_MSG_FLAG(FASTOPEN);
650 P_MSG_FLAG(CMSG_CLOEXEC);
651 #undef P_MSG_FLAG
653 if (flags)
654 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
656 return printed;
659 #define SCA_MSG_FLAGS syscall_arg__scnprintf_msg_flags
661 static size_t syscall_arg__scnprintf_access_mode(char *bf, size_t size,
662 struct syscall_arg *arg)
664 size_t printed = 0;
665 int mode = arg->val;
667 if (mode == F_OK) /* 0 */
668 return scnprintf(bf, size, "F");
669 #define P_MODE(n) \
670 if (mode & n##_OK) { \
671 printed += scnprintf(bf + printed, size - printed, "%s", #n); \
672 mode &= ~n##_OK; \
675 P_MODE(R);
676 P_MODE(W);
677 P_MODE(X);
678 #undef P_MODE
680 if (mode)
681 printed += scnprintf(bf + printed, size - printed, "|%#x", mode);
683 return printed;
686 #define SCA_ACCMODE syscall_arg__scnprintf_access_mode
688 static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
689 struct syscall_arg *arg)
691 int printed = 0, flags = arg->val;
693 if (!(flags & O_CREAT))
694 arg->mask |= 1 << (arg->idx + 1); /* Mask the mode parm */
696 if (flags == 0)
697 return scnprintf(bf, size, "RDONLY");
698 #define P_FLAG(n) \
699 if (flags & O_##n) { \
700 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
701 flags &= ~O_##n; \
704 P_FLAG(APPEND);
705 P_FLAG(ASYNC);
706 P_FLAG(CLOEXEC);
707 P_FLAG(CREAT);
708 P_FLAG(DIRECT);
709 P_FLAG(DIRECTORY);
710 P_FLAG(EXCL);
711 P_FLAG(LARGEFILE);
712 P_FLAG(NOATIME);
713 P_FLAG(NOCTTY);
714 #ifdef O_NONBLOCK
715 P_FLAG(NONBLOCK);
716 #elif O_NDELAY
717 P_FLAG(NDELAY);
718 #endif
719 #ifdef O_PATH
720 P_FLAG(PATH);
721 #endif
722 P_FLAG(RDWR);
723 #ifdef O_DSYNC
724 if ((flags & O_SYNC) == O_SYNC)
725 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", "SYNC");
726 else {
727 P_FLAG(DSYNC);
729 #else
730 P_FLAG(SYNC);
731 #endif
732 P_FLAG(TRUNC);
733 P_FLAG(WRONLY);
734 #undef P_FLAG
736 if (flags)
737 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
739 return printed;
742 #define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags
744 static size_t syscall_arg__scnprintf_eventfd_flags(char *bf, size_t size,
745 struct syscall_arg *arg)
747 int printed = 0, flags = arg->val;
749 if (flags == 0)
750 return scnprintf(bf, size, "NONE");
751 #define P_FLAG(n) \
752 if (flags & EFD_##n) { \
753 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
754 flags &= ~EFD_##n; \
757 P_FLAG(SEMAPHORE);
758 P_FLAG(CLOEXEC);
759 P_FLAG(NONBLOCK);
760 #undef P_FLAG
762 if (flags)
763 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
765 return printed;
768 #define SCA_EFD_FLAGS syscall_arg__scnprintf_eventfd_flags
770 static size_t syscall_arg__scnprintf_pipe_flags(char *bf, size_t size,
771 struct syscall_arg *arg)
773 int printed = 0, flags = arg->val;
775 #define P_FLAG(n) \
776 if (flags & O_##n) { \
777 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
778 flags &= ~O_##n; \
781 P_FLAG(CLOEXEC);
782 P_FLAG(NONBLOCK);
783 #undef P_FLAG
785 if (flags)
786 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
788 return printed;
791 #define SCA_PIPE_FLAGS syscall_arg__scnprintf_pipe_flags
793 static size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscall_arg *arg)
795 int sig = arg->val;
797 switch (sig) {
798 #define P_SIGNUM(n) case SIG##n: return scnprintf(bf, size, #n)
799 P_SIGNUM(HUP);
800 P_SIGNUM(INT);
801 P_SIGNUM(QUIT);
802 P_SIGNUM(ILL);
803 P_SIGNUM(TRAP);
804 P_SIGNUM(ABRT);
805 P_SIGNUM(BUS);
806 P_SIGNUM(FPE);
807 P_SIGNUM(KILL);
808 P_SIGNUM(USR1);
809 P_SIGNUM(SEGV);
810 P_SIGNUM(USR2);
811 P_SIGNUM(PIPE);
812 P_SIGNUM(ALRM);
813 P_SIGNUM(TERM);
814 P_SIGNUM(STKFLT);
815 P_SIGNUM(CHLD);
816 P_SIGNUM(CONT);
817 P_SIGNUM(STOP);
818 P_SIGNUM(TSTP);
819 P_SIGNUM(TTIN);
820 P_SIGNUM(TTOU);
821 P_SIGNUM(URG);
822 P_SIGNUM(XCPU);
823 P_SIGNUM(XFSZ);
824 P_SIGNUM(VTALRM);
825 P_SIGNUM(PROF);
826 P_SIGNUM(WINCH);
827 P_SIGNUM(IO);
828 P_SIGNUM(PWR);
829 P_SIGNUM(SYS);
830 default: break;
833 return scnprintf(bf, size, "%#x", sig);
836 #define SCA_SIGNUM syscall_arg__scnprintf_signum
838 #define TCGETS 0x5401
840 static const char *tioctls[] = {
841 "TCGETS", "TCSETS", "TCSETSW", "TCSETSF", "TCGETA", "TCSETA", "TCSETAW",
842 "TCSETAF", "TCSBRK", "TCXONC", "TCFLSH", "TIOCEXCL", "TIOCNXCL",
843 "TIOCSCTTY", "TIOCGPGRP", "TIOCSPGRP", "TIOCOUTQ", "TIOCSTI",
844 "TIOCGWINSZ", "TIOCSWINSZ", "TIOCMGET", "TIOCMBIS", "TIOCMBIC",
845 "TIOCMSET", "TIOCGSOFTCAR", "TIOCSSOFTCAR", "FIONREAD", "TIOCLINUX",
846 "TIOCCONS", "TIOCGSERIAL", "TIOCSSERIAL", "TIOCPKT", "FIONBIO",
847 "TIOCNOTTY", "TIOCSETD", "TIOCGETD", "TCSBRKP", [0x27] = "TIOCSBRK",
848 "TIOCCBRK", "TIOCGSID", "TCGETS2", "TCSETS2", "TCSETSW2", "TCSETSF2",
849 "TIOCGRS485", "TIOCSRS485", "TIOCGPTN", "TIOCSPTLCK",
850 "TIOCGDEV||TCGETX", "TCSETX", "TCSETXF", "TCSETXW", "TIOCSIG",
851 "TIOCVHANGUP", "TIOCGPKT", "TIOCGPTLCK", "TIOCGEXCL",
852 [0x50] = "FIONCLEX", "FIOCLEX", "FIOASYNC", "TIOCSERCONFIG",
853 "TIOCSERGWILD", "TIOCSERSWILD", "TIOCGLCKTRMIOS", "TIOCSLCKTRMIOS",
854 "TIOCSERGSTRUCT", "TIOCSERGETLSR", "TIOCSERGETMULTI", "TIOCSERSETMULTI",
855 "TIOCMIWAIT", "TIOCGICOUNT", [0x60] = "FIOQSIZE",
858 static DEFINE_STRARRAY_OFFSET(tioctls, 0x5401);
860 #define STRARRAY(arg, name, array) \
861 .arg_scnprintf = { [arg] = SCA_STRARRAY, }, \
862 .arg_parm = { [arg] = &strarray__##array, }
864 static struct syscall_fmt {
865 const char *name;
866 const char *alias;
867 size_t (*arg_scnprintf[6])(char *bf, size_t size, struct syscall_arg *arg);
868 void *arg_parm[6];
869 bool errmsg;
870 bool timeout;
871 bool hexret;
872 } syscall_fmts[] = {
873 { .name = "access", .errmsg = true,
874 .arg_scnprintf = { [1] = SCA_ACCMODE, /* mode */ }, },
875 { .name = "arch_prctl", .errmsg = true, .alias = "prctl", },
876 { .name = "brk", .hexret = true,
877 .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, },
878 { .name = "clock_gettime", .errmsg = true, STRARRAY(0, clk_id, clockid), },
879 { .name = "close", .errmsg = true,
880 .arg_scnprintf = { [0] = SCA_CLOSE_FD, /* fd */ }, },
881 { .name = "connect", .errmsg = true, },
882 { .name = "dup", .errmsg = true,
883 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
884 { .name = "dup2", .errmsg = true,
885 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
886 { .name = "dup3", .errmsg = true,
887 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
888 { .name = "epoll_ctl", .errmsg = true, STRARRAY(1, op, epoll_ctl_ops), },
889 { .name = "eventfd2", .errmsg = true,
890 .arg_scnprintf = { [1] = SCA_EFD_FLAGS, /* flags */ }, },
891 { .name = "faccessat", .errmsg = true,
892 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
893 { .name = "fadvise64", .errmsg = true,
894 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
895 { .name = "fallocate", .errmsg = true,
896 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
897 { .name = "fchdir", .errmsg = true,
898 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
899 { .name = "fchmod", .errmsg = true,
900 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
901 { .name = "fchmodat", .errmsg = true,
902 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
903 { .name = "fchown", .errmsg = true,
904 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
905 { .name = "fchownat", .errmsg = true,
906 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
907 { .name = "fcntl", .errmsg = true,
908 .arg_scnprintf = { [0] = SCA_FD, /* fd */
909 [1] = SCA_STRARRAY, /* cmd */ },
910 .arg_parm = { [1] = &strarray__fcntl_cmds, /* cmd */ }, },
911 { .name = "fdatasync", .errmsg = true,
912 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
913 { .name = "flock", .errmsg = true,
914 .arg_scnprintf = { [0] = SCA_FD, /* fd */
915 [1] = SCA_FLOCK, /* cmd */ }, },
916 { .name = "fsetxattr", .errmsg = true,
917 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
918 { .name = "fstat", .errmsg = true, .alias = "newfstat",
919 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
920 { .name = "fstatat", .errmsg = true, .alias = "newfstatat",
921 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
922 { .name = "fstatfs", .errmsg = true,
923 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
924 { .name = "fsync", .errmsg = true,
925 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
926 { .name = "ftruncate", .errmsg = true,
927 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
928 { .name = "futex", .errmsg = true,
929 .arg_scnprintf = { [1] = SCA_FUTEX_OP, /* op */ }, },
930 { .name = "futimesat", .errmsg = true,
931 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
932 { .name = "getdents", .errmsg = true,
933 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
934 { .name = "getdents64", .errmsg = true,
935 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
936 { .name = "getitimer", .errmsg = true, STRARRAY(0, which, itimers), },
937 { .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
938 { .name = "ioctl", .errmsg = true,
939 .arg_scnprintf = { [0] = SCA_FD, /* fd */
940 [1] = SCA_STRHEXARRAY, /* cmd */
941 [2] = SCA_HEX, /* arg */ },
942 .arg_parm = { [1] = &strarray__tioctls, /* cmd */ }, },
943 { .name = "kill", .errmsg = true,
944 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
945 { .name = "linkat", .errmsg = true,
946 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
947 { .name = "lseek", .errmsg = true,
948 .arg_scnprintf = { [0] = SCA_FD, /* fd */
949 [2] = SCA_STRARRAY, /* whence */ },
950 .arg_parm = { [2] = &strarray__whences, /* whence */ }, },
951 { .name = "lstat", .errmsg = true, .alias = "newlstat", },
952 { .name = "madvise", .errmsg = true,
953 .arg_scnprintf = { [0] = SCA_HEX, /* start */
954 [2] = SCA_MADV_BHV, /* behavior */ }, },
955 { .name = "mkdirat", .errmsg = true,
956 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
957 { .name = "mknodat", .errmsg = true,
958 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
959 { .name = "mlock", .errmsg = true,
960 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
961 { .name = "mlockall", .errmsg = true,
962 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
963 { .name = "mmap", .hexret = true,
964 .arg_scnprintf = { [0] = SCA_HEX, /* addr */
965 [2] = SCA_MMAP_PROT, /* prot */
966 [3] = SCA_MMAP_FLAGS, /* flags */
967 [4] = SCA_FD, /* fd */ }, },
968 { .name = "mprotect", .errmsg = true,
969 .arg_scnprintf = { [0] = SCA_HEX, /* start */
970 [2] = SCA_MMAP_PROT, /* prot */ }, },
971 { .name = "mremap", .hexret = true,
972 .arg_scnprintf = { [0] = SCA_HEX, /* addr */
973 [4] = SCA_HEX, /* new_addr */ }, },
974 { .name = "munlock", .errmsg = true,
975 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
976 { .name = "munmap", .errmsg = true,
977 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
978 { .name = "name_to_handle_at", .errmsg = true,
979 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
980 { .name = "newfstatat", .errmsg = true,
981 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
982 { .name = "open", .errmsg = true,
983 .arg_scnprintf = { [1] = SCA_OPEN_FLAGS, /* flags */ }, },
984 { .name = "open_by_handle_at", .errmsg = true,
985 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
986 [2] = SCA_OPEN_FLAGS, /* flags */ }, },
987 { .name = "openat", .errmsg = true,
988 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
989 [2] = SCA_OPEN_FLAGS, /* flags */ }, },
990 { .name = "pipe2", .errmsg = true,
991 .arg_scnprintf = { [1] = SCA_PIPE_FLAGS, /* flags */ }, },
992 { .name = "poll", .errmsg = true, .timeout = true, },
993 { .name = "ppoll", .errmsg = true, .timeout = true, },
994 { .name = "pread", .errmsg = true, .alias = "pread64",
995 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
996 { .name = "preadv", .errmsg = true, .alias = "pread",
997 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
998 { .name = "prlimit64", .errmsg = true, STRARRAY(1, resource, rlimit_resources), },
999 { .name = "pwrite", .errmsg = true, .alias = "pwrite64",
1000 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1001 { .name = "pwritev", .errmsg = true,
1002 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1003 { .name = "read", .errmsg = true,
1004 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1005 { .name = "readlinkat", .errmsg = true,
1006 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
1007 { .name = "readv", .errmsg = true,
1008 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1009 { .name = "recvfrom", .errmsg = true,
1010 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
1011 { .name = "recvmmsg", .errmsg = true,
1012 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
1013 { .name = "recvmsg", .errmsg = true,
1014 .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, },
1015 { .name = "renameat", .errmsg = true,
1016 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
1017 { .name = "rt_sigaction", .errmsg = true,
1018 .arg_scnprintf = { [0] = SCA_SIGNUM, /* sig */ }, },
1019 { .name = "rt_sigprocmask", .errmsg = true, STRARRAY(0, how, sighow), },
1020 { .name = "rt_sigqueueinfo", .errmsg = true,
1021 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
1022 { .name = "rt_tgsigqueueinfo", .errmsg = true,
1023 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
1024 { .name = "select", .errmsg = true, .timeout = true, },
1025 { .name = "sendmmsg", .errmsg = true,
1026 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
1027 { .name = "sendmsg", .errmsg = true,
1028 .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, },
1029 { .name = "sendto", .errmsg = true,
1030 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
1031 { .name = "setitimer", .errmsg = true, STRARRAY(0, which, itimers), },
1032 { .name = "setrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
1033 { .name = "shutdown", .errmsg = true,
1034 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1035 { .name = "socket", .errmsg = true,
1036 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
1037 [1] = SCA_SK_TYPE, /* type */ },
1038 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, },
1039 { .name = "socketpair", .errmsg = true,
1040 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
1041 [1] = SCA_SK_TYPE, /* type */ },
1042 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, },
1043 { .name = "stat", .errmsg = true, .alias = "newstat", },
1044 { .name = "symlinkat", .errmsg = true,
1045 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
1046 { .name = "tgkill", .errmsg = true,
1047 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
1048 { .name = "tkill", .errmsg = true,
1049 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
1050 { .name = "uname", .errmsg = true, .alias = "newuname", },
1051 { .name = "unlinkat", .errmsg = true,
1052 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
1053 { .name = "utimensat", .errmsg = true,
1054 .arg_scnprintf = { [0] = SCA_FDAT, /* dirfd */ }, },
1055 { .name = "write", .errmsg = true,
1056 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1057 { .name = "writev", .errmsg = true,
1058 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1061 static int syscall_fmt__cmp(const void *name, const void *fmtp)
1063 const struct syscall_fmt *fmt = fmtp;
1064 return strcmp(name, fmt->name);
1067 static struct syscall_fmt *syscall_fmt__find(const char *name)
1069 const int nmemb = ARRAY_SIZE(syscall_fmts);
1070 return bsearch(name, syscall_fmts, nmemb, sizeof(struct syscall_fmt), syscall_fmt__cmp);
1073 struct syscall {
1074 struct event_format *tp_format;
1075 const char *name;
1076 bool filtered;
1077 struct syscall_fmt *fmt;
1078 size_t (**arg_scnprintf)(char *bf, size_t size, struct syscall_arg *arg);
1079 void **arg_parm;
1082 static size_t fprintf_duration(unsigned long t, FILE *fp)
1084 double duration = (double)t / NSEC_PER_MSEC;
1085 size_t printed = fprintf(fp, "(");
1087 if (duration >= 1.0)
1088 printed += color_fprintf(fp, PERF_COLOR_RED, "%6.3f ms", duration);
1089 else if (duration >= 0.01)
1090 printed += color_fprintf(fp, PERF_COLOR_YELLOW, "%6.3f ms", duration);
1091 else
1092 printed += color_fprintf(fp, PERF_COLOR_NORMAL, "%6.3f ms", duration);
1093 return printed + fprintf(fp, "): ");
1096 struct thread_trace {
1097 u64 entry_time;
1098 u64 exit_time;
1099 bool entry_pending;
1100 unsigned long nr_events;
1101 char *entry_str;
1102 double runtime_ms;
1103 struct {
1104 int max;
1105 char **table;
1106 } paths;
1108 struct intlist *syscall_stats;
1111 static struct thread_trace *thread_trace__new(void)
1113 struct thread_trace *ttrace = zalloc(sizeof(struct thread_trace));
1115 if (ttrace)
1116 ttrace->paths.max = -1;
1118 ttrace->syscall_stats = intlist__new(NULL);
1120 return ttrace;
1123 static struct thread_trace *thread__trace(struct thread *thread, FILE *fp)
1125 struct thread_trace *ttrace;
1127 if (thread == NULL)
1128 goto fail;
1130 if (thread->priv == NULL)
1131 thread->priv = thread_trace__new();
1133 if (thread->priv == NULL)
1134 goto fail;
1136 ttrace = thread->priv;
1137 ++ttrace->nr_events;
1139 return ttrace;
1140 fail:
1141 color_fprintf(fp, PERF_COLOR_RED,
1142 "WARNING: not enough memory, dropping samples!\n");
1143 return NULL;
1146 struct trace {
1147 struct perf_tool tool;
1148 struct {
1149 int machine;
1150 int open_id;
1151 } audit;
1152 struct {
1153 int max;
1154 struct syscall *table;
1155 } syscalls;
1156 struct perf_record_opts opts;
1157 struct machine *host;
1158 u64 base_time;
1159 bool full_time;
1160 FILE *output;
1161 unsigned long nr_events;
1162 struct strlist *ev_qualifier;
1163 bool not_ev_qualifier;
1164 bool live;
1165 const char *last_vfs_getname;
1166 struct intlist *tid_list;
1167 struct intlist *pid_list;
1168 bool sched;
1169 bool multiple_threads;
1170 bool summary;
1171 bool summary_only;
1172 bool show_comm;
1173 bool show_tool_stats;
1174 double duration_filter;
1175 double runtime_ms;
1176 struct {
1177 u64 vfs_getname, proc_getname;
1178 } stats;
1181 static int trace__set_fd_pathname(struct thread *thread, int fd, const char *pathname)
1183 struct thread_trace *ttrace = thread->priv;
1185 if (fd > ttrace->paths.max) {
1186 char **npath = realloc(ttrace->paths.table, (fd + 1) * sizeof(char *));
1188 if (npath == NULL)
1189 return -1;
1191 if (ttrace->paths.max != -1) {
1192 memset(npath + ttrace->paths.max + 1, 0,
1193 (fd - ttrace->paths.max) * sizeof(char *));
1194 } else {
1195 memset(npath, 0, (fd + 1) * sizeof(char *));
1198 ttrace->paths.table = npath;
1199 ttrace->paths.max = fd;
1202 ttrace->paths.table[fd] = strdup(pathname);
1204 return ttrace->paths.table[fd] != NULL ? 0 : -1;
1207 static int thread__read_fd_path(struct thread *thread, int fd)
1209 char linkname[PATH_MAX], pathname[PATH_MAX];
1210 struct stat st;
1211 int ret;
1213 if (thread->pid_ == thread->tid) {
1214 scnprintf(linkname, sizeof(linkname),
1215 "/proc/%d/fd/%d", thread->pid_, fd);
1216 } else {
1217 scnprintf(linkname, sizeof(linkname),
1218 "/proc/%d/task/%d/fd/%d", thread->pid_, thread->tid, fd);
1221 if (lstat(linkname, &st) < 0 || st.st_size + 1 > (off_t)sizeof(pathname))
1222 return -1;
1224 ret = readlink(linkname, pathname, sizeof(pathname));
1226 if (ret < 0 || ret > st.st_size)
1227 return -1;
1229 pathname[ret] = '\0';
1230 return trace__set_fd_pathname(thread, fd, pathname);
1233 static const char *thread__fd_path(struct thread *thread, int fd,
1234 struct trace *trace)
1236 struct thread_trace *ttrace = thread->priv;
1238 if (ttrace == NULL)
1239 return NULL;
1241 if (fd < 0)
1242 return NULL;
1244 if ((fd > ttrace->paths.max || ttrace->paths.table[fd] == NULL))
1245 if (!trace->live)
1246 return NULL;
1247 ++trace->stats.proc_getname;
1248 if (thread__read_fd_path(thread, fd)) {
1249 return NULL;
1252 return ttrace->paths.table[fd];
1255 static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
1256 struct syscall_arg *arg)
1258 int fd = arg->val;
1259 size_t printed = scnprintf(bf, size, "%d", fd);
1260 const char *path = thread__fd_path(arg->thread, fd, arg->trace);
1262 if (path)
1263 printed += scnprintf(bf + printed, size - printed, "<%s>", path);
1265 return printed;
1268 static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
1269 struct syscall_arg *arg)
1271 int fd = arg->val;
1272 size_t printed = syscall_arg__scnprintf_fd(bf, size, arg);
1273 struct thread_trace *ttrace = arg->thread->priv;
1275 if (ttrace && fd >= 0 && fd <= ttrace->paths.max) {
1276 free(ttrace->paths.table[fd]);
1277 ttrace->paths.table[fd] = NULL;
1280 return printed;
1283 static bool trace__filter_duration(struct trace *trace, double t)
1285 return t < (trace->duration_filter * NSEC_PER_MSEC);
1288 static size_t trace__fprintf_tstamp(struct trace *trace, u64 tstamp, FILE *fp)
1290 double ts = (double)(tstamp - trace->base_time) / NSEC_PER_MSEC;
1292 return fprintf(fp, "%10.3f ", ts);
1295 static bool done = false;
1296 static bool interrupted = false;
1298 static void sig_handler(int sig)
1300 done = true;
1301 interrupted = sig == SIGINT;
1304 static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thread,
1305 u64 duration, u64 tstamp, FILE *fp)
1307 size_t printed = trace__fprintf_tstamp(trace, tstamp, fp);
1308 printed += fprintf_duration(duration, fp);
1310 if (trace->multiple_threads) {
1311 if (trace->show_comm)
1312 printed += fprintf(fp, "%.14s/", thread__comm_str(thread));
1313 printed += fprintf(fp, "%d ", thread->tid);
1316 return printed;
1319 static int trace__process_event(struct trace *trace, struct machine *machine,
1320 union perf_event *event, struct perf_sample *sample)
1322 int ret = 0;
1324 switch (event->header.type) {
1325 case PERF_RECORD_LOST:
1326 color_fprintf(trace->output, PERF_COLOR_RED,
1327 "LOST %" PRIu64 " events!\n", event->lost.lost);
1328 ret = machine__process_lost_event(machine, event, sample);
1329 default:
1330 ret = machine__process_event(machine, event, sample);
1331 break;
1334 return ret;
1337 static int trace__tool_process(struct perf_tool *tool,
1338 union perf_event *event,
1339 struct perf_sample *sample,
1340 struct machine *machine)
1342 struct trace *trace = container_of(tool, struct trace, tool);
1343 return trace__process_event(trace, machine, event, sample);
1346 static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
1348 int err = symbol__init();
1350 if (err)
1351 return err;
1353 trace->host = machine__new_host();
1354 if (trace->host == NULL)
1355 return -ENOMEM;
1357 err = __machine__synthesize_threads(trace->host, &trace->tool, &trace->opts.target,
1358 evlist->threads, trace__tool_process, false);
1359 if (err)
1360 symbol__exit();
1362 return err;
1365 static int syscall__set_arg_fmts(struct syscall *sc)
1367 struct format_field *field;
1368 int idx = 0;
1370 sc->arg_scnprintf = calloc(sc->tp_format->format.nr_fields - 1, sizeof(void *));
1371 if (sc->arg_scnprintf == NULL)
1372 return -1;
1374 if (sc->fmt)
1375 sc->arg_parm = sc->fmt->arg_parm;
1377 for (field = sc->tp_format->format.fields->next; field; field = field->next) {
1378 if (sc->fmt && sc->fmt->arg_scnprintf[idx])
1379 sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx];
1380 else if (field->flags & FIELD_IS_POINTER)
1381 sc->arg_scnprintf[idx] = syscall_arg__scnprintf_hex;
1382 ++idx;
1385 return 0;
1388 static int trace__read_syscall_info(struct trace *trace, int id)
1390 char tp_name[128];
1391 struct syscall *sc;
1392 const char *name = audit_syscall_to_name(id, trace->audit.machine);
1394 if (name == NULL)
1395 return -1;
1397 if (id > trace->syscalls.max) {
1398 struct syscall *nsyscalls = realloc(trace->syscalls.table, (id + 1) * sizeof(*sc));
1400 if (nsyscalls == NULL)
1401 return -1;
1403 if (trace->syscalls.max != -1) {
1404 memset(nsyscalls + trace->syscalls.max + 1, 0,
1405 (id - trace->syscalls.max) * sizeof(*sc));
1406 } else {
1407 memset(nsyscalls, 0, (id + 1) * sizeof(*sc));
1410 trace->syscalls.table = nsyscalls;
1411 trace->syscalls.max = id;
1414 sc = trace->syscalls.table + id;
1415 sc->name = name;
1417 if (trace->ev_qualifier) {
1418 bool in = strlist__find(trace->ev_qualifier, name) != NULL;
1420 if (!(in ^ trace->not_ev_qualifier)) {
1421 sc->filtered = true;
1423 * No need to do read tracepoint information since this will be
1424 * filtered out.
1426 return 0;
1430 sc->fmt = syscall_fmt__find(sc->name);
1432 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name);
1433 sc->tp_format = event_format__new("syscalls", tp_name);
1435 if (sc->tp_format == NULL && sc->fmt && sc->fmt->alias) {
1436 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->fmt->alias);
1437 sc->tp_format = event_format__new("syscalls", tp_name);
1440 if (sc->tp_format == NULL)
1441 return -1;
1443 return syscall__set_arg_fmts(sc);
1446 static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
1447 unsigned long *args, struct trace *trace,
1448 struct thread *thread)
1450 size_t printed = 0;
1452 if (sc->tp_format != NULL) {
1453 struct format_field *field;
1454 u8 bit = 1;
1455 struct syscall_arg arg = {
1456 .idx = 0,
1457 .mask = 0,
1458 .trace = trace,
1459 .thread = thread,
1462 for (field = sc->tp_format->format.fields->next; field;
1463 field = field->next, ++arg.idx, bit <<= 1) {
1464 if (arg.mask & bit)
1465 continue;
1467 * Suppress this argument if its value is zero and
1468 * and we don't have a string associated in an
1469 * strarray for it.
1471 if (args[arg.idx] == 0 &&
1472 !(sc->arg_scnprintf &&
1473 sc->arg_scnprintf[arg.idx] == SCA_STRARRAY &&
1474 sc->arg_parm[arg.idx]))
1475 continue;
1477 printed += scnprintf(bf + printed, size - printed,
1478 "%s%s: ", printed ? ", " : "", field->name);
1479 if (sc->arg_scnprintf && sc->arg_scnprintf[arg.idx]) {
1480 arg.val = args[arg.idx];
1481 if (sc->arg_parm)
1482 arg.parm = sc->arg_parm[arg.idx];
1483 printed += sc->arg_scnprintf[arg.idx](bf + printed,
1484 size - printed, &arg);
1485 } else {
1486 printed += scnprintf(bf + printed, size - printed,
1487 "%ld", args[arg.idx]);
1490 } else {
1491 int i = 0;
1493 while (i < 6) {
1494 printed += scnprintf(bf + printed, size - printed,
1495 "%sarg%d: %ld",
1496 printed ? ", " : "", i, args[i]);
1497 ++i;
1501 return printed;
1504 typedef int (*tracepoint_handler)(struct trace *trace, struct perf_evsel *evsel,
1505 struct perf_sample *sample);
1507 static struct syscall *trace__syscall_info(struct trace *trace,
1508 struct perf_evsel *evsel, int id)
1511 if (id < 0) {
1514 * XXX: Noticed on x86_64, reproduced as far back as 3.0.36, haven't tried
1515 * before that, leaving at a higher verbosity level till that is
1516 * explained. Reproduced with plain ftrace with:
1518 * echo 1 > /t/events/raw_syscalls/sys_exit/enable
1519 * grep "NR -1 " /t/trace_pipe
1521 * After generating some load on the machine.
1523 if (verbose > 1) {
1524 static u64 n;
1525 fprintf(trace->output, "Invalid syscall %d id, skipping (%s, %" PRIu64 ") ...\n",
1526 id, perf_evsel__name(evsel), ++n);
1528 return NULL;
1531 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL) &&
1532 trace__read_syscall_info(trace, id))
1533 goto out_cant_read;
1535 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL))
1536 goto out_cant_read;
1538 return &trace->syscalls.table[id];
1540 out_cant_read:
1541 if (verbose) {
1542 fprintf(trace->output, "Problems reading syscall %d", id);
1543 if (id <= trace->syscalls.max && trace->syscalls.table[id].name != NULL)
1544 fprintf(trace->output, "(%s)", trace->syscalls.table[id].name);
1545 fputs(" information\n", trace->output);
1547 return NULL;
1550 static void thread__update_stats(struct thread_trace *ttrace,
1551 int id, struct perf_sample *sample)
1553 struct int_node *inode;
1554 struct stats *stats;
1555 u64 duration = 0;
1557 inode = intlist__findnew(ttrace->syscall_stats, id);
1558 if (inode == NULL)
1559 return;
1561 stats = inode->priv;
1562 if (stats == NULL) {
1563 stats = malloc(sizeof(struct stats));
1564 if (stats == NULL)
1565 return;
1566 init_stats(stats);
1567 inode->priv = stats;
1570 if (ttrace->entry_time && sample->time > ttrace->entry_time)
1571 duration = sample->time - ttrace->entry_time;
1573 update_stats(stats, duration);
1576 static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
1577 struct perf_sample *sample)
1579 char *msg;
1580 void *args;
1581 size_t printed = 0;
1582 struct thread *thread;
1583 int id = perf_evsel__sc_tp_uint(evsel, id, sample);
1584 struct syscall *sc = trace__syscall_info(trace, evsel, id);
1585 struct thread_trace *ttrace;
1587 if (sc == NULL)
1588 return -1;
1590 if (sc->filtered)
1591 return 0;
1593 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
1594 ttrace = thread__trace(thread, trace->output);
1595 if (ttrace == NULL)
1596 return -1;
1598 args = perf_evsel__sc_tp_ptr(evsel, args, sample);
1599 ttrace = thread->priv;
1601 if (ttrace->entry_str == NULL) {
1602 ttrace->entry_str = malloc(1024);
1603 if (!ttrace->entry_str)
1604 return -1;
1607 ttrace->entry_time = sample->time;
1608 msg = ttrace->entry_str;
1609 printed += scnprintf(msg + printed, 1024 - printed, "%s(", sc->name);
1611 printed += syscall__scnprintf_args(sc, msg + printed, 1024 - printed,
1612 args, trace, thread);
1614 if (!strcmp(sc->name, "exit_group") || !strcmp(sc->name, "exit")) {
1615 if (!trace->duration_filter && !trace->summary_only) {
1616 trace__fprintf_entry_head(trace, thread, 1, sample->time, trace->output);
1617 fprintf(trace->output, "%-70s\n", ttrace->entry_str);
1619 } else
1620 ttrace->entry_pending = true;
1622 return 0;
1625 static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
1626 struct perf_sample *sample)
1628 int ret;
1629 u64 duration = 0;
1630 struct thread *thread;
1631 int id = perf_evsel__sc_tp_uint(evsel, id, sample);
1632 struct syscall *sc = trace__syscall_info(trace, evsel, id);
1633 struct thread_trace *ttrace;
1635 if (sc == NULL)
1636 return -1;
1638 if (sc->filtered)
1639 return 0;
1641 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
1642 ttrace = thread__trace(thread, trace->output);
1643 if (ttrace == NULL)
1644 return -1;
1646 if (trace->summary)
1647 thread__update_stats(ttrace, id, sample);
1649 ret = perf_evsel__sc_tp_uint(evsel, ret, sample);
1651 if (id == trace->audit.open_id && ret >= 0 && trace->last_vfs_getname) {
1652 trace__set_fd_pathname(thread, ret, trace->last_vfs_getname);
1653 trace->last_vfs_getname = NULL;
1654 ++trace->stats.vfs_getname;
1657 ttrace = thread->priv;
1659 ttrace->exit_time = sample->time;
1661 if (ttrace->entry_time) {
1662 duration = sample->time - ttrace->entry_time;
1663 if (trace__filter_duration(trace, duration))
1664 goto out;
1665 } else if (trace->duration_filter)
1666 goto out;
1668 if (trace->summary_only)
1669 goto out;
1671 trace__fprintf_entry_head(trace, thread, duration, sample->time, trace->output);
1673 if (ttrace->entry_pending) {
1674 fprintf(trace->output, "%-70s", ttrace->entry_str);
1675 } else {
1676 fprintf(trace->output, " ... [");
1677 color_fprintf(trace->output, PERF_COLOR_YELLOW, "continued");
1678 fprintf(trace->output, "]: %s()", sc->name);
1681 if (sc->fmt == NULL) {
1682 signed_print:
1683 fprintf(trace->output, ") = %d", ret);
1684 } else if (ret < 0 && sc->fmt->errmsg) {
1685 char bf[256];
1686 const char *emsg = strerror_r(-ret, bf, sizeof(bf)),
1687 *e = audit_errno_to_name(-ret);
1689 fprintf(trace->output, ") = -1 %s %s", e, emsg);
1690 } else if (ret == 0 && sc->fmt->timeout)
1691 fprintf(trace->output, ") = 0 Timeout");
1692 else if (sc->fmt->hexret)
1693 fprintf(trace->output, ") = %#x", ret);
1694 else
1695 goto signed_print;
1697 fputc('\n', trace->output);
1698 out:
1699 ttrace->entry_pending = false;
1701 return 0;
1704 static int trace__vfs_getname(struct trace *trace, struct perf_evsel *evsel,
1705 struct perf_sample *sample)
1707 trace->last_vfs_getname = perf_evsel__rawptr(evsel, sample, "pathname");
1708 return 0;
1711 static int trace__sched_stat_runtime(struct trace *trace, struct perf_evsel *evsel,
1712 struct perf_sample *sample)
1714 u64 runtime = perf_evsel__intval(evsel, sample, "runtime");
1715 double runtime_ms = (double)runtime / NSEC_PER_MSEC;
1716 struct thread *thread = machine__findnew_thread(trace->host,
1717 sample->pid,
1718 sample->tid);
1719 struct thread_trace *ttrace = thread__trace(thread, trace->output);
1721 if (ttrace == NULL)
1722 goto out_dump;
1724 ttrace->runtime_ms += runtime_ms;
1725 trace->runtime_ms += runtime_ms;
1726 return 0;
1728 out_dump:
1729 fprintf(trace->output, "%s: comm=%s,pid=%u,runtime=%" PRIu64 ",vruntime=%" PRIu64 ")\n",
1730 evsel->name,
1731 perf_evsel__strval(evsel, sample, "comm"),
1732 (pid_t)perf_evsel__intval(evsel, sample, "pid"),
1733 runtime,
1734 perf_evsel__intval(evsel, sample, "vruntime"));
1735 return 0;
1738 static bool skip_sample(struct trace *trace, struct perf_sample *sample)
1740 if ((trace->pid_list && intlist__find(trace->pid_list, sample->pid)) ||
1741 (trace->tid_list && intlist__find(trace->tid_list, sample->tid)))
1742 return false;
1744 if (trace->pid_list || trace->tid_list)
1745 return true;
1747 return false;
1750 static int trace__process_sample(struct perf_tool *tool,
1751 union perf_event *event __maybe_unused,
1752 struct perf_sample *sample,
1753 struct perf_evsel *evsel,
1754 struct machine *machine __maybe_unused)
1756 struct trace *trace = container_of(tool, struct trace, tool);
1757 int err = 0;
1759 tracepoint_handler handler = evsel->handler;
1761 if (skip_sample(trace, sample))
1762 return 0;
1764 if (!trace->full_time && trace->base_time == 0)
1765 trace->base_time = sample->time;
1767 if (handler)
1768 handler(trace, evsel, sample);
1770 return err;
1773 static int parse_target_str(struct trace *trace)
1775 if (trace->opts.target.pid) {
1776 trace->pid_list = intlist__new(trace->opts.target.pid);
1777 if (trace->pid_list == NULL) {
1778 pr_err("Error parsing process id string\n");
1779 return -EINVAL;
1783 if (trace->opts.target.tid) {
1784 trace->tid_list = intlist__new(trace->opts.target.tid);
1785 if (trace->tid_list == NULL) {
1786 pr_err("Error parsing thread id string\n");
1787 return -EINVAL;
1791 return 0;
1794 static int trace__record(int argc, const char **argv)
1796 unsigned int rec_argc, i, j;
1797 const char **rec_argv;
1798 const char * const record_args[] = {
1799 "record",
1800 "-R",
1801 "-m", "1024",
1802 "-c", "1",
1803 "-e", "raw_syscalls:sys_enter,raw_syscalls:sys_exit",
1806 rec_argc = ARRAY_SIZE(record_args) + argc;
1807 rec_argv = calloc(rec_argc + 1, sizeof(char *));
1809 if (rec_argv == NULL)
1810 return -ENOMEM;
1812 for (i = 0; i < ARRAY_SIZE(record_args); i++)
1813 rec_argv[i] = record_args[i];
1815 for (j = 0; j < (unsigned int)argc; j++, i++)
1816 rec_argv[i] = argv[j];
1818 return cmd_record(i, rec_argv, NULL);
1821 static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp);
1823 static void perf_evlist__add_vfs_getname(struct perf_evlist *evlist)
1825 struct perf_evsel *evsel = perf_evsel__newtp("probe", "vfs_getname");
1826 if (evsel == NULL)
1827 return;
1829 if (perf_evsel__field(evsel, "pathname") == NULL) {
1830 perf_evsel__delete(evsel);
1831 return;
1834 evsel->handler = trace__vfs_getname;
1835 perf_evlist__add(evlist, evsel);
1838 static int trace__run(struct trace *trace, int argc, const char **argv)
1840 struct perf_evlist *evlist = perf_evlist__new();
1841 struct perf_evsel *evsel;
1842 int err = -1, i;
1843 unsigned long before;
1844 const bool forks = argc > 0;
1846 trace->live = true;
1848 if (evlist == NULL) {
1849 fprintf(trace->output, "Not enough memory to run!\n");
1850 goto out;
1853 if (perf_evlist__add_syscall_newtp(evlist, trace__sys_enter, trace__sys_exit))
1854 goto out_error_tp;
1856 perf_evlist__add_vfs_getname(evlist);
1858 if (trace->sched &&
1859 perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime",
1860 trace__sched_stat_runtime))
1861 goto out_error_tp;
1863 err = perf_evlist__create_maps(evlist, &trace->opts.target);
1864 if (err < 0) {
1865 fprintf(trace->output, "Problems parsing the target to trace, check your options!\n");
1866 goto out_delete_evlist;
1869 err = trace__symbols_init(trace, evlist);
1870 if (err < 0) {
1871 fprintf(trace->output, "Problems initializing symbol libraries!\n");
1872 goto out_delete_maps;
1875 perf_evlist__config(evlist, &trace->opts);
1877 signal(SIGCHLD, sig_handler);
1878 signal(SIGINT, sig_handler);
1880 if (forks) {
1881 err = perf_evlist__prepare_workload(evlist, &trace->opts.target,
1882 argv, false, false);
1883 if (err < 0) {
1884 fprintf(trace->output, "Couldn't run the workload!\n");
1885 goto out_delete_maps;
1889 err = perf_evlist__open(evlist);
1890 if (err < 0)
1891 goto out_error_open;
1893 err = perf_evlist__mmap(evlist, UINT_MAX, false);
1894 if (err < 0) {
1895 fprintf(trace->output, "Couldn't mmap the events: %s\n", strerror(errno));
1896 goto out_close_evlist;
1899 perf_evlist__enable(evlist);
1901 if (forks)
1902 perf_evlist__start_workload(evlist);
1904 trace->multiple_threads = evlist->threads->map[0] == -1 || evlist->threads->nr > 1;
1905 again:
1906 before = trace->nr_events;
1908 for (i = 0; i < evlist->nr_mmaps; i++) {
1909 union perf_event *event;
1911 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
1912 const u32 type = event->header.type;
1913 tracepoint_handler handler;
1914 struct perf_sample sample;
1916 ++trace->nr_events;
1918 err = perf_evlist__parse_sample(evlist, event, &sample);
1919 if (err) {
1920 fprintf(trace->output, "Can't parse sample, err = %d, skipping...\n", err);
1921 goto next_event;
1924 if (!trace->full_time && trace->base_time == 0)
1925 trace->base_time = sample.time;
1927 if (type != PERF_RECORD_SAMPLE) {
1928 trace__process_event(trace, trace->host, event, &sample);
1929 continue;
1932 evsel = perf_evlist__id2evsel(evlist, sample.id);
1933 if (evsel == NULL) {
1934 fprintf(trace->output, "Unknown tp ID %" PRIu64 ", skipping...\n", sample.id);
1935 goto next_event;
1938 if (sample.raw_data == NULL) {
1939 fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n",
1940 perf_evsel__name(evsel), sample.tid,
1941 sample.cpu, sample.raw_size);
1942 goto next_event;
1945 handler = evsel->handler;
1946 handler(trace, evsel, &sample);
1947 next_event:
1948 perf_evlist__mmap_consume(evlist, i);
1950 if (interrupted)
1951 goto out_disable;
1955 if (trace->nr_events == before) {
1956 int timeout = done ? 100 : -1;
1958 if (poll(evlist->pollfd, evlist->nr_fds, timeout) > 0)
1959 goto again;
1960 } else {
1961 goto again;
1964 out_disable:
1965 perf_evlist__disable(evlist);
1967 if (!err) {
1968 if (trace->summary)
1969 trace__fprintf_thread_summary(trace, trace->output);
1971 if (trace->show_tool_stats) {
1972 fprintf(trace->output, "Stats:\n "
1973 " vfs_getname : %" PRIu64 "\n"
1974 " proc_getname: %" PRIu64 "\n",
1975 trace->stats.vfs_getname,
1976 trace->stats.proc_getname);
1980 perf_evlist__munmap(evlist);
1981 out_close_evlist:
1982 perf_evlist__close(evlist);
1983 out_delete_maps:
1984 perf_evlist__delete_maps(evlist);
1985 out_delete_evlist:
1986 perf_evlist__delete(evlist);
1987 out:
1988 trace->live = false;
1989 return err;
1991 char errbuf[BUFSIZ];
1993 out_error_tp:
1994 perf_evlist__strerror_tp(evlist, errno, errbuf, sizeof(errbuf));
1995 goto out_error;
1997 out_error_open:
1998 perf_evlist__strerror_open(evlist, errno, errbuf, sizeof(errbuf));
2000 out_error:
2001 fprintf(trace->output, "%s\n", errbuf);
2002 goto out_delete_evlist;
2006 static int trace__replay(struct trace *trace)
2008 const struct perf_evsel_str_handler handlers[] = {
2009 { "probe:vfs_getname", trace__vfs_getname, },
2011 struct perf_data_file file = {
2012 .path = input_name,
2013 .mode = PERF_DATA_MODE_READ,
2015 struct perf_session *session;
2016 struct perf_evsel *evsel;
2017 int err = -1;
2019 trace->tool.sample = trace__process_sample;
2020 trace->tool.mmap = perf_event__process_mmap;
2021 trace->tool.mmap2 = perf_event__process_mmap2;
2022 trace->tool.comm = perf_event__process_comm;
2023 trace->tool.exit = perf_event__process_exit;
2024 trace->tool.fork = perf_event__process_fork;
2025 trace->tool.attr = perf_event__process_attr;
2026 trace->tool.tracing_data = perf_event__process_tracing_data;
2027 trace->tool.build_id = perf_event__process_build_id;
2029 trace->tool.ordered_samples = true;
2030 trace->tool.ordering_requires_timestamps = true;
2032 /* add tid to output */
2033 trace->multiple_threads = true;
2035 if (symbol__init() < 0)
2036 return -1;
2038 session = perf_session__new(&file, false, &trace->tool);
2039 if (session == NULL)
2040 return -ENOMEM;
2042 trace->host = &session->machines.host;
2044 err = perf_session__set_tracepoints_handlers(session, handlers);
2045 if (err)
2046 goto out;
2048 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2049 "raw_syscalls:sys_enter");
2050 if (evsel == NULL) {
2051 pr_err("Data file does not have raw_syscalls:sys_enter event\n");
2052 goto out;
2055 if (perf_evsel__init_syscall_tp(evsel, trace__sys_enter) < 0 ||
2056 perf_evsel__init_sc_tp_ptr_field(evsel, args)) {
2057 pr_err("Error during initialize raw_syscalls:sys_enter event\n");
2058 goto out;
2061 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2062 "raw_syscalls:sys_exit");
2063 if (evsel == NULL) {
2064 pr_err("Data file does not have raw_syscalls:sys_exit event\n");
2065 goto out;
2068 if (perf_evsel__init_syscall_tp(evsel, trace__sys_exit) < 0 ||
2069 perf_evsel__init_sc_tp_uint_field(evsel, ret)) {
2070 pr_err("Error during initialize raw_syscalls:sys_exit event\n");
2071 goto out;
2074 err = parse_target_str(trace);
2075 if (err != 0)
2076 goto out;
2078 setup_pager();
2080 err = perf_session__process_events(session, &trace->tool);
2081 if (err)
2082 pr_err("Failed to process events, error %d", err);
2084 else if (trace->summary)
2085 trace__fprintf_thread_summary(trace, trace->output);
2087 out:
2088 perf_session__delete(session);
2090 return err;
2093 static size_t trace__fprintf_threads_header(FILE *fp)
2095 size_t printed;
2097 printed = fprintf(fp, "\n Summary of events:\n\n");
2099 return printed;
2102 static size_t thread__dump_stats(struct thread_trace *ttrace,
2103 struct trace *trace, FILE *fp)
2105 struct stats *stats;
2106 size_t printed = 0;
2107 struct syscall *sc;
2108 struct int_node *inode = intlist__first(ttrace->syscall_stats);
2110 if (inode == NULL)
2111 return 0;
2113 printed += fprintf(fp, "\n");
2115 printed += fprintf(fp, " syscall calls min avg max stddev\n");
2116 printed += fprintf(fp, " (msec) (msec) (msec) (%%)\n");
2117 printed += fprintf(fp, " --------------- -------- --------- --------- --------- ------\n");
2119 /* each int_node is a syscall */
2120 while (inode) {
2121 stats = inode->priv;
2122 if (stats) {
2123 double min = (double)(stats->min) / NSEC_PER_MSEC;
2124 double max = (double)(stats->max) / NSEC_PER_MSEC;
2125 double avg = avg_stats(stats);
2126 double pct;
2127 u64 n = (u64) stats->n;
2129 pct = avg ? 100.0 * stddev_stats(stats)/avg : 0.0;
2130 avg /= NSEC_PER_MSEC;
2132 sc = &trace->syscalls.table[inode->i];
2133 printed += fprintf(fp, " %-15s", sc->name);
2134 printed += fprintf(fp, " %8" PRIu64 " %9.3f %9.3f",
2135 n, min, avg);
2136 printed += fprintf(fp, " %9.3f %9.2f%%\n", max, pct);
2139 inode = intlist__next(inode);
2142 printed += fprintf(fp, "\n\n");
2144 return printed;
2147 /* struct used to pass data to per-thread function */
2148 struct summary_data {
2149 FILE *fp;
2150 struct trace *trace;
2151 size_t printed;
2154 static int trace__fprintf_one_thread(struct thread *thread, void *priv)
2156 struct summary_data *data = priv;
2157 FILE *fp = data->fp;
2158 size_t printed = data->printed;
2159 struct trace *trace = data->trace;
2160 struct thread_trace *ttrace = thread->priv;
2161 const char *color;
2162 double ratio;
2164 if (ttrace == NULL)
2165 return 0;
2167 ratio = (double)ttrace->nr_events / trace->nr_events * 100.0;
2169 color = PERF_COLOR_NORMAL;
2170 if (ratio > 50.0)
2171 color = PERF_COLOR_RED;
2172 else if (ratio > 25.0)
2173 color = PERF_COLOR_GREEN;
2174 else if (ratio > 5.0)
2175 color = PERF_COLOR_YELLOW;
2177 printed += color_fprintf(fp, color, " %s (%d), ", thread__comm_str(thread), thread->tid);
2178 printed += fprintf(fp, "%lu events, ", ttrace->nr_events);
2179 printed += color_fprintf(fp, color, "%.1f%%", ratio);
2180 printed += fprintf(fp, ", %.3f msec\n", ttrace->runtime_ms);
2181 printed += thread__dump_stats(ttrace, trace, fp);
2183 data->printed += printed;
2185 return 0;
2188 static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp)
2190 struct summary_data data = {
2191 .fp = fp,
2192 .trace = trace
2194 data.printed = trace__fprintf_threads_header(fp);
2196 machine__for_each_thread(trace->host, trace__fprintf_one_thread, &data);
2198 return data.printed;
2201 static int trace__set_duration(const struct option *opt, const char *str,
2202 int unset __maybe_unused)
2204 struct trace *trace = opt->value;
2206 trace->duration_filter = atof(str);
2207 return 0;
2210 static int trace__open_output(struct trace *trace, const char *filename)
2212 struct stat st;
2214 if (!stat(filename, &st) && st.st_size) {
2215 char oldname[PATH_MAX];
2217 scnprintf(oldname, sizeof(oldname), "%s.old", filename);
2218 unlink(oldname);
2219 rename(filename, oldname);
2222 trace->output = fopen(filename, "w");
2224 return trace->output == NULL ? -errno : 0;
2227 int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
2229 const char * const trace_usage[] = {
2230 "perf trace [<options>] [<command>]",
2231 "perf trace [<options>] -- <command> [<options>]",
2232 "perf trace record [<options>] [<command>]",
2233 "perf trace record [<options>] -- <command> [<options>]",
2234 NULL
2236 struct trace trace = {
2237 .audit = {
2238 .machine = audit_detect_machine(),
2239 .open_id = audit_name_to_syscall("open", trace.audit.machine),
2241 .syscalls = {
2242 . max = -1,
2244 .opts = {
2245 .target = {
2246 .uid = UINT_MAX,
2247 .uses_mmap = true,
2249 .user_freq = UINT_MAX,
2250 .user_interval = ULLONG_MAX,
2251 .no_delay = true,
2252 .mmap_pages = 1024,
2254 .output = stdout,
2255 .show_comm = true,
2257 const char *output_name = NULL;
2258 const char *ev_qualifier_str = NULL;
2259 const struct option trace_options[] = {
2260 OPT_BOOLEAN(0, "comm", &trace.show_comm,
2261 "show the thread COMM next to its id"),
2262 OPT_BOOLEAN(0, "tool_stats", &trace.show_tool_stats, "show tool stats"),
2263 OPT_STRING('e', "expr", &ev_qualifier_str, "expr",
2264 "list of events to trace"),
2265 OPT_STRING('o', "output", &output_name, "file", "output file name"),
2266 OPT_STRING('i', "input", &input_name, "file", "Analyze events in file"),
2267 OPT_STRING('p', "pid", &trace.opts.target.pid, "pid",
2268 "trace events on existing process id"),
2269 OPT_STRING('t', "tid", &trace.opts.target.tid, "tid",
2270 "trace events on existing thread id"),
2271 OPT_BOOLEAN('a', "all-cpus", &trace.opts.target.system_wide,
2272 "system-wide collection from all CPUs"),
2273 OPT_STRING('C', "cpu", &trace.opts.target.cpu_list, "cpu",
2274 "list of cpus to monitor"),
2275 OPT_BOOLEAN(0, "no-inherit", &trace.opts.no_inherit,
2276 "child tasks do not inherit counters"),
2277 OPT_CALLBACK('m', "mmap-pages", &trace.opts.mmap_pages, "pages",
2278 "number of mmap data pages",
2279 perf_evlist__parse_mmap_pages),
2280 OPT_STRING('u', "uid", &trace.opts.target.uid_str, "user",
2281 "user to profile"),
2282 OPT_CALLBACK(0, "duration", &trace, "float",
2283 "show only events with duration > N.M ms",
2284 trace__set_duration),
2285 OPT_BOOLEAN(0, "sched", &trace.sched, "show blocking scheduler events"),
2286 OPT_INCR('v', "verbose", &verbose, "be more verbose"),
2287 OPT_BOOLEAN('T', "time", &trace.full_time,
2288 "Show full timestamp, not time relative to first start"),
2289 OPT_BOOLEAN('s', "summary", &trace.summary_only,
2290 "Show only syscall summary with statistics"),
2291 OPT_BOOLEAN('S', "with-summary", &trace.summary,
2292 "Show all syscalls and summary with statistics"),
2293 OPT_END()
2295 int err;
2296 char bf[BUFSIZ];
2298 if ((argc > 1) && (strcmp(argv[1], "record") == 0))
2299 return trace__record(argc-2, &argv[2]);
2301 argc = parse_options(argc, argv, trace_options, trace_usage, 0);
2303 /* summary_only implies summary option, but don't overwrite summary if set */
2304 if (trace.summary_only)
2305 trace.summary = trace.summary_only;
2307 if (output_name != NULL) {
2308 err = trace__open_output(&trace, output_name);
2309 if (err < 0) {
2310 perror("failed to create output file");
2311 goto out;
2315 if (ev_qualifier_str != NULL) {
2316 const char *s = ev_qualifier_str;
2318 trace.not_ev_qualifier = *s == '!';
2319 if (trace.not_ev_qualifier)
2320 ++s;
2321 trace.ev_qualifier = strlist__new(true, s);
2322 if (trace.ev_qualifier == NULL) {
2323 fputs("Not enough memory to parse event qualifier",
2324 trace.output);
2325 err = -ENOMEM;
2326 goto out_close;
2330 err = target__validate(&trace.opts.target);
2331 if (err) {
2332 target__strerror(&trace.opts.target, err, bf, sizeof(bf));
2333 fprintf(trace.output, "%s", bf);
2334 goto out_close;
2337 err = target__parse_uid(&trace.opts.target);
2338 if (err) {
2339 target__strerror(&trace.opts.target, err, bf, sizeof(bf));
2340 fprintf(trace.output, "%s", bf);
2341 goto out_close;
2344 if (!argc && target__none(&trace.opts.target))
2345 trace.opts.target.system_wide = true;
2347 if (input_name)
2348 err = trace__replay(&trace);
2349 else
2350 err = trace__run(&trace, argc, argv);
2352 out_close:
2353 if (output_name != NULL)
2354 fclose(trace.output);
2355 out:
2356 return err;