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