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