perf util: Add findnew method to intlist
[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 1592 if (perf_evlist__add_newtp(evlist, "raw_syscalls", "sys_enter", trace__sys_enter) ||
87f91868
RR
1593 perf_evlist__add_newtp(evlist, "raw_syscalls", "sys_exit", trace__sys_exit))
1594 goto out_error_tp;
514f1c67 1595
1302d88e 1596 if (trace->sched &&
87f91868
RR
1597 perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime",
1598 trace__sched_stat_runtime))
1599 goto out_error_tp;
1302d88e 1600
514f1c67
ACM
1601 err = perf_evlist__create_maps(evlist, &trace->opts.target);
1602 if (err < 0) {
c24ff998 1603 fprintf(trace->output, "Problems parsing the target to trace, check your options!\n");
514f1c67
ACM
1604 goto out_delete_evlist;
1605 }
1606
752fde44
ACM
1607 err = trace__symbols_init(trace, evlist);
1608 if (err < 0) {
c24ff998 1609 fprintf(trace->output, "Problems initializing symbol libraries!\n");
3beb0861 1610 goto out_delete_maps;
752fde44
ACM
1611 }
1612
f77a9518 1613 perf_evlist__config(evlist, &trace->opts);
514f1c67 1614
f15eb531
NK
1615 signal(SIGCHLD, sig_handler);
1616 signal(SIGINT, sig_handler);
1617
1618 if (forks) {
6ef73ec4 1619 err = perf_evlist__prepare_workload(evlist, &trace->opts.target,
55e162ea 1620 argv, false, false);
f15eb531 1621 if (err < 0) {
c24ff998 1622 fprintf(trace->output, "Couldn't run the workload!\n");
3beb0861 1623 goto out_delete_maps;
f15eb531
NK
1624 }
1625 }
1626
514f1c67
ACM
1627 err = perf_evlist__open(evlist);
1628 if (err < 0) {
c24ff998 1629 fprintf(trace->output, "Couldn't create the events: %s\n", strerror(errno));
3beb0861 1630 goto out_delete_maps;
514f1c67
ACM
1631 }
1632
1633 err = perf_evlist__mmap(evlist, UINT_MAX, false);
1634 if (err < 0) {
c24ff998 1635 fprintf(trace->output, "Couldn't mmap the events: %s\n", strerror(errno));
3beb0861 1636 goto out_close_evlist;
514f1c67
ACM
1637 }
1638
1639 perf_evlist__enable(evlist);
f15eb531
NK
1640
1641 if (forks)
1642 perf_evlist__start_workload(evlist);
1643
752fde44 1644 trace->multiple_threads = evlist->threads->map[0] == -1 || evlist->threads->nr > 1;
514f1c67 1645again:
efd5745e 1646 before = trace->nr_events;
514f1c67
ACM
1647
1648 for (i = 0; i < evlist->nr_mmaps; i++) {
1649 union perf_event *event;
1650
1651 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
1652 const u32 type = event->header.type;
ba3d7dee 1653 tracepoint_handler handler;
514f1c67 1654 struct perf_sample sample;
514f1c67 1655
efd5745e 1656 ++trace->nr_events;
514f1c67 1657
514f1c67
ACM
1658 err = perf_evlist__parse_sample(evlist, event, &sample);
1659 if (err) {
c24ff998 1660 fprintf(trace->output, "Can't parse sample, err = %d, skipping...\n", err);
514f1c67
ACM
1661 continue;
1662 }
1663
4bb09192 1664 if (!trace->full_time && trace->base_time == 0)
752fde44
ACM
1665 trace->base_time = sample.time;
1666
1667 if (type != PERF_RECORD_SAMPLE) {
8fb598e5 1668 trace__process_event(trace, trace->host, event);
752fde44
ACM
1669 continue;
1670 }
1671
514f1c67
ACM
1672 evsel = perf_evlist__id2evsel(evlist, sample.id);
1673 if (evsel == NULL) {
c24ff998 1674 fprintf(trace->output, "Unknown tp ID %" PRIu64 ", skipping...\n", sample.id);
514f1c67
ACM
1675 continue;
1676 }
1677
fc551f8d 1678 if (sample.raw_data == NULL) {
c24ff998 1679 fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n",
fc551f8d
ACM
1680 perf_evsel__name(evsel), sample.tid,
1681 sample.cpu, sample.raw_size);
1682 continue;
1683 }
1684
ba3d7dee
ACM
1685 handler = evsel->handler.func;
1686 handler(trace, evsel, &sample);
20c5f10e
ACM
1687
1688 if (done)
1689 goto out_unmap_evlist;
514f1c67
ACM
1690 }
1691 }
1692
efd5745e 1693 if (trace->nr_events == before) {
f15eb531 1694 if (done)
3beb0861 1695 goto out_unmap_evlist;
f15eb531 1696
514f1c67 1697 poll(evlist->pollfd, evlist->nr_fds, -1);
f15eb531
NK
1698 }
1699
1700 if (done)
1701 perf_evlist__disable(evlist);
514f1c67
ACM
1702
1703 goto again;
1704
3beb0861
NK
1705out_unmap_evlist:
1706 perf_evlist__munmap(evlist);
1707out_close_evlist:
1708 perf_evlist__close(evlist);
1709out_delete_maps:
1710 perf_evlist__delete_maps(evlist);
514f1c67
ACM
1711out_delete_evlist:
1712 perf_evlist__delete(evlist);
1713out:
75b757ca 1714 trace->live = false;
514f1c67 1715 return err;
87f91868
RR
1716out_error_tp:
1717 switch(errno) {
1718 case ENOENT:
1719 fputs("Error:\tUnable to find debugfs\n"
1720 "Hint:\tWas your kernel was compiled with debugfs support?\n"
1721 "Hint:\tIs the debugfs filesystem mounted?\n"
1722 "Hint:\tTry 'sudo mount -t debugfs nodev /sys/kernel/debug'\n",
1723 trace->output);
1724 break;
1725 case EACCES:
1726 fprintf(trace->output,
1727 "Error:\tNo permissions to read %s/tracing/events/raw_syscalls\n"
1728 "Hint:\tTry 'sudo mount -o remount,mode=755 %s'\n",
1729 debugfs_mountpoint, debugfs_mountpoint);
1730 break;
1731 default: {
1732 char bf[256];
1733 fprintf(trace->output, "Can't trace: %s\n",
1734 strerror_r(errno, bf, sizeof(bf)));
1735 }
1736 break;
1737 }
1738 goto out_delete_evlist;
514f1c67
ACM
1739}
1740
6810fc91
DA
1741static int trace__replay(struct trace *trace)
1742{
1743 const struct perf_evsel_str_handler handlers[] = {
1744 { "raw_syscalls:sys_enter", trace__sys_enter, },
1745 { "raw_syscalls:sys_exit", trace__sys_exit, },
1746 };
1747
1748 struct perf_session *session;
1749 int err = -1;
1750
1751 trace->tool.sample = trace__process_sample;
1752 trace->tool.mmap = perf_event__process_mmap;
384c671e 1753 trace->tool.mmap2 = perf_event__process_mmap2;
6810fc91
DA
1754 trace->tool.comm = perf_event__process_comm;
1755 trace->tool.exit = perf_event__process_exit;
1756 trace->tool.fork = perf_event__process_fork;
1757 trace->tool.attr = perf_event__process_attr;
1758 trace->tool.tracing_data = perf_event__process_tracing_data;
1759 trace->tool.build_id = perf_event__process_build_id;
1760
1761 trace->tool.ordered_samples = true;
1762 trace->tool.ordering_requires_timestamps = true;
1763
1764 /* add tid to output */
1765 trace->multiple_threads = true;
1766
1767 if (symbol__init() < 0)
1768 return -1;
1769
1770 session = perf_session__new(input_name, O_RDONLY, 0, false,
1771 &trace->tool);
1772 if (session == NULL)
1773 return -ENOMEM;
1774
8fb598e5
DA
1775 trace->host = &session->machines.host;
1776
6810fc91
DA
1777 err = perf_session__set_tracepoints_handlers(session, handlers);
1778 if (err)
1779 goto out;
1780
1781 if (!perf_session__has_tp(session, "raw_syscalls:sys_enter")) {
1782 pr_err("Data file does not have raw_syscalls:sys_enter events\n");
1783 goto out;
1784 }
1785
1786 if (!perf_session__has_tp(session, "raw_syscalls:sys_exit")) {
1787 pr_err("Data file does not have raw_syscalls:sys_exit events\n");
1788 goto out;
1789 }
1790
bdc89661
DA
1791 err = parse_target_str(trace);
1792 if (err != 0)
1793 goto out;
1794
6810fc91
DA
1795 setup_pager();
1796
1797 err = perf_session__process_events(session, &trace->tool);
1798 if (err)
1799 pr_err("Failed to process events, error %d", err);
1800
1801out:
1802 perf_session__delete(session);
1803
1804 return err;
1805}
1806
1302d88e
ACM
1807static size_t trace__fprintf_threads_header(FILE *fp)
1808{
1809 size_t printed;
1810
1811 printed = fprintf(fp, "\n _____________________________________________________________________\n");
1812 printed += fprintf(fp," __) Summary of events (__\n\n");
1813 printed += fprintf(fp," [ task - pid ] [ events ] [ ratio ] [ runtime ]\n");
1814 printed += fprintf(fp," _____________________________________________________________________\n\n");
1815
1816 return printed;
1817}
1818
896cbb56
DA
1819/* struct used to pass data to per-thread function */
1820struct summary_data {
1821 FILE *fp;
1822 struct trace *trace;
1823 size_t printed;
1824};
1825
1826static int trace__fprintf_one_thread(struct thread *thread, void *priv)
1827{
1828 struct summary_data *data = priv;
1829 FILE *fp = data->fp;
1830 size_t printed = data->printed;
1831 struct trace *trace = data->trace;
1832 struct thread_trace *ttrace = thread->priv;
1833 const char *color;
1834 double ratio;
1835
1836 if (ttrace == NULL)
1837 return 0;
1838
1839 ratio = (double)ttrace->nr_events / trace->nr_events * 100.0;
1840
1841 color = PERF_COLOR_NORMAL;
1842 if (ratio > 50.0)
1843 color = PERF_COLOR_RED;
1844 else if (ratio > 25.0)
1845 color = PERF_COLOR_GREEN;
1846 else if (ratio > 5.0)
1847 color = PERF_COLOR_YELLOW;
1848
1849 printed += color_fprintf(fp, color, "%20s", thread->comm);
1850 printed += fprintf(fp, " - %-5d :%11lu [", thread->tid, ttrace->nr_events);
1851 printed += color_fprintf(fp, color, "%5.1f%%", ratio);
1852 printed += fprintf(fp, " ] %10.3f ms\n", ttrace->runtime_ms);
1853
1854 data->printed += printed;
1855
1856 return 0;
1857}
1858
1302d88e
ACM
1859static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp)
1860{
896cbb56
DA
1861 struct summary_data data = {
1862 .fp = fp,
1863 .trace = trace
1864 };
1865 data.printed = trace__fprintf_threads_header(fp);
1302d88e 1866
896cbb56
DA
1867 machine__for_each_thread(trace->host, trace__fprintf_one_thread, &data);
1868
1869 return data.printed;
1302d88e
ACM
1870}
1871
ae9ed035
ACM
1872static int trace__set_duration(const struct option *opt, const char *str,
1873 int unset __maybe_unused)
1874{
1875 struct trace *trace = opt->value;
1876
1877 trace->duration_filter = atof(str);
1878 return 0;
1879}
1880
c24ff998
ACM
1881static int trace__open_output(struct trace *trace, const char *filename)
1882{
1883 struct stat st;
1884
1885 if (!stat(filename, &st) && st.st_size) {
1886 char oldname[PATH_MAX];
1887
1888 scnprintf(oldname, sizeof(oldname), "%s.old", filename);
1889 unlink(oldname);
1890 rename(filename, oldname);
1891 }
1892
1893 trace->output = fopen(filename, "w");
1894
1895 return trace->output == NULL ? -errno : 0;
1896}
1897
514f1c67
ACM
1898int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
1899{
1900 const char * const trace_usage[] = {
f15eb531
NK
1901 "perf trace [<options>] [<command>]",
1902 "perf trace [<options>] -- <command> [<options>]",
5e2485b1
DA
1903 "perf trace record [<options>] [<command>]",
1904 "perf trace record [<options>] -- <command> [<options>]",
514f1c67
ACM
1905 NULL
1906 };
1907 struct trace trace = {
1908 .audit_machine = audit_detect_machine(),
1909 .syscalls = {
1910 . max = -1,
1911 },
1912 .opts = {
1913 .target = {
1914 .uid = UINT_MAX,
1915 .uses_mmap = true,
1916 },
1917 .user_freq = UINT_MAX,
1918 .user_interval = ULLONG_MAX,
1919 .no_delay = true,
1920 .mmap_pages = 1024,
1921 },
c24ff998 1922 .output = stdout,
50c95cbd 1923 .show_comm = true,
514f1c67 1924 };
c24ff998 1925 const char *output_name = NULL;
2ae3a312 1926 const char *ev_qualifier_str = NULL;
514f1c67 1927 const struct option trace_options[] = {
50c95cbd
ACM
1928 OPT_BOOLEAN(0, "comm", &trace.show_comm,
1929 "show the thread COMM next to its id"),
2ae3a312
ACM
1930 OPT_STRING('e', "expr", &ev_qualifier_str, "expr",
1931 "list of events to trace"),
c24ff998 1932 OPT_STRING('o', "output", &output_name, "file", "output file name"),
6810fc91 1933 OPT_STRING('i', "input", &input_name, "file", "Analyze events in file"),
514f1c67
ACM
1934 OPT_STRING('p', "pid", &trace.opts.target.pid, "pid",
1935 "trace events on existing process id"),
ac9be8ee 1936 OPT_STRING('t', "tid", &trace.opts.target.tid, "tid",
514f1c67 1937 "trace events on existing thread id"),
ac9be8ee 1938 OPT_BOOLEAN('a', "all-cpus", &trace.opts.target.system_wide,
514f1c67 1939 "system-wide collection from all CPUs"),
ac9be8ee 1940 OPT_STRING('C', "cpu", &trace.opts.target.cpu_list, "cpu",
514f1c67 1941 "list of cpus to monitor"),
6810fc91 1942 OPT_BOOLEAN(0, "no-inherit", &trace.opts.no_inherit,
514f1c67 1943 "child tasks do not inherit counters"),
994a1f78
JO
1944 OPT_CALLBACK('m', "mmap-pages", &trace.opts.mmap_pages, "pages",
1945 "number of mmap data pages",
1946 perf_evlist__parse_mmap_pages),
ac9be8ee 1947 OPT_STRING('u', "uid", &trace.opts.target.uid_str, "user",
514f1c67 1948 "user to profile"),
ae9ed035
ACM
1949 OPT_CALLBACK(0, "duration", &trace, "float",
1950 "show only events with duration > N.M ms",
1951 trace__set_duration),
1302d88e 1952 OPT_BOOLEAN(0, "sched", &trace.sched, "show blocking scheduler events"),
7c304ee0 1953 OPT_INCR('v', "verbose", &verbose, "be more verbose"),
4bb09192
DA
1954 OPT_BOOLEAN('T', "time", &trace.full_time,
1955 "Show full timestamp, not time relative to first start"),
514f1c67
ACM
1956 OPT_END()
1957 };
1958 int err;
32caf0d1 1959 char bf[BUFSIZ];
514f1c67 1960
5e2485b1
DA
1961 if ((argc > 1) && (strcmp(argv[1], "record") == 0))
1962 return trace__record(argc-2, &argv[2]);
1963
514f1c67 1964 argc = parse_options(argc, argv, trace_options, trace_usage, 0);
514f1c67 1965
c24ff998
ACM
1966 if (output_name != NULL) {
1967 err = trace__open_output(&trace, output_name);
1968 if (err < 0) {
1969 perror("failed to create output file");
1970 goto out;
1971 }
1972 }
1973
2ae3a312 1974 if (ev_qualifier_str != NULL) {
b059efdf
ACM
1975 const char *s = ev_qualifier_str;
1976
1977 trace.not_ev_qualifier = *s == '!';
1978 if (trace.not_ev_qualifier)
1979 ++s;
1980 trace.ev_qualifier = strlist__new(true, s);
2ae3a312 1981 if (trace.ev_qualifier == NULL) {
c24ff998
ACM
1982 fputs("Not enough memory to parse event qualifier",
1983 trace.output);
1984 err = -ENOMEM;
1985 goto out_close;
2ae3a312
ACM
1986 }
1987 }
1988
32caf0d1
NK
1989 err = perf_target__validate(&trace.opts.target);
1990 if (err) {
1991 perf_target__strerror(&trace.opts.target, err, bf, sizeof(bf));
c24ff998
ACM
1992 fprintf(trace.output, "%s", bf);
1993 goto out_close;
32caf0d1
NK
1994 }
1995
514f1c67
ACM
1996 err = perf_target__parse_uid(&trace.opts.target);
1997 if (err) {
514f1c67 1998 perf_target__strerror(&trace.opts.target, err, bf, sizeof(bf));
c24ff998
ACM
1999 fprintf(trace.output, "%s", bf);
2000 goto out_close;
514f1c67
ACM
2001 }
2002
f15eb531 2003 if (!argc && perf_target__none(&trace.opts.target))
ee76120e
NK
2004 trace.opts.target.system_wide = true;
2005
6810fc91
DA
2006 if (input_name)
2007 err = trace__replay(&trace);
2008 else
2009 err = trace__run(&trace, argc, argv);
1302d88e
ACM
2010
2011 if (trace.sched && !err)
c24ff998 2012 trace__fprintf_thread_summary(&trace, trace.output);
1302d88e 2013
c24ff998
ACM
2014out_close:
2015 if (output_name != NULL)
2016 fclose(trace.output);
2017out:
1302d88e 2018 return err;
514f1c67 2019}
This page took 0.148208 seconds and 5 git commands to generate.