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