perf trace: Don't print zeroed args
[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     = "connect",    .errmsg = true, },
465         { .name     = "fcntl",      .errmsg = true,
466           .arg_scnprintf = { [1] = SCA_STRARRAY, /* cmd */ },
467           .arg_parm      = { [1] = &strarray__fcntl_cmds, /* cmd */ }, },
468         { .name     = "fstat",      .errmsg = true, .alias = "newfstat", },
469         { .name     = "fstatat",    .errmsg = true, .alias = "newfstatat", },
470         { .name     = "futex",      .errmsg = true,
471           .arg_scnprintf = { [1] = SCA_FUTEX_OP, /* op */ }, },
472         { .name     = "getitimer",  .errmsg = true,
473           .arg_scnprintf = { [0] = SCA_STRARRAY, /* which */ },
474           .arg_parm      = { [0] = &strarray__itimers, /* which */ }, },
475         { .name     = "getrlimit",  .errmsg = true,
476           .arg_scnprintf = { [0] = SCA_STRARRAY, /* resource */ },
477           .arg_parm      = { [0] = &strarray__rlimit_resources, /* resource */ }, },
478         { .name     = "ioctl",      .errmsg = true,
479           .arg_scnprintf = { [2] = SCA_HEX, /* arg */ }, },
480         { .name     = "kill",       .errmsg = true,
481           .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
482         { .name     = "lseek",      .errmsg = true,
483           .arg_scnprintf = { [2] = SCA_STRARRAY, /* whence */ },
484           .arg_parm      = { [2] = &strarray__whences, /* whence */ }, },
485         { .name     = "lstat",      .errmsg = true, .alias = "newlstat", },
486         { .name     = "madvise",    .errmsg = true,
487           .arg_scnprintf = { [0] = SCA_HEX,      /* start */
488                              [2] = SCA_MADV_BHV, /* behavior */ }, },
489         { .name     = "mmap",       .hexret = true,
490           .arg_scnprintf = { [0] = SCA_HEX,       /* addr */
491                              [2] = SCA_MMAP_PROT, /* prot */
492                              [3] = SCA_MMAP_FLAGS, /* flags */ }, },
493         { .name     = "mprotect",   .errmsg = true,
494           .arg_scnprintf = { [0] = SCA_HEX, /* start */
495                              [2] = SCA_MMAP_PROT, /* prot */ }, },
496         { .name     = "mremap",     .hexret = true,
497           .arg_scnprintf = { [0] = SCA_HEX, /* addr */
498                              [4] = SCA_HEX, /* new_addr */ }, },
499         { .name     = "munmap",     .errmsg = true,
500           .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
501         { .name     = "open",       .errmsg = true,
502           .arg_scnprintf = { [1] = SCA_OPEN_FLAGS, /* flags */ }, },
503         { .name     = "open_by_handle_at", .errmsg = true,
504           .arg_scnprintf = { [2] = SCA_OPEN_FLAGS, /* flags */ }, },
505         { .name     = "openat",     .errmsg = true,
506           .arg_scnprintf = { [2] = SCA_OPEN_FLAGS, /* flags */ }, },
507         { .name     = "poll",       .errmsg = true, .timeout = true, },
508         { .name     = "ppoll",      .errmsg = true, .timeout = true, },
509         { .name     = "pread",      .errmsg = true, .alias = "pread64", },
510         { .name     = "prlimit64",  .errmsg = true,
511           .arg_scnprintf = { [1] = SCA_STRARRAY, /* resource */ },
512           .arg_parm      = { [1] = &strarray__rlimit_resources, /* resource */ }, },
513         { .name     = "pwrite",     .errmsg = true, .alias = "pwrite64", },
514         { .name     = "read",       .errmsg = true, },
515         { .name     = "recvfrom",   .errmsg = true, },
516         { .name     = "rt_sigaction", .errmsg = true,
517           .arg_scnprintf = { [0] = SCA_SIGNUM, /* sig */ }, },
518         { .name     = "rt_sigprocmask", .errmsg = true,
519           .arg_scnprintf = { [0] = SCA_STRARRAY, /* how */ },
520           .arg_parm      = { [0] = &strarray__sighow, /* how */ }, },
521         { .name     = "rt_sigqueueinfo", .errmsg = true,
522           .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
523         { .name     = "rt_tgsigqueueinfo", .errmsg = true,
524           .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
525         { .name     = "select",     .errmsg = true, .timeout = true, },
526         { .name     = "setitimer",  .errmsg = true,
527           .arg_scnprintf = { [0] = SCA_STRARRAY, /* which */ },
528           .arg_parm      = { [0] = &strarray__itimers, /* which */ }, },
529         { .name     = "setrlimit",  .errmsg = true,
530           .arg_scnprintf = { [0] = SCA_STRARRAY, /* resource */ },
531           .arg_parm      = { [0] = &strarray__rlimit_resources, /* resource */ }, },
532         { .name     = "socket",     .errmsg = true,
533           .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
534                              [1] = SCA_SK_TYPE, /* type */ },
535           .arg_parm      = { [0] = &strarray__socket_families, /* family */ }, },
536         { .name     = "stat",       .errmsg = true, .alias = "newstat", },
537         { .name     = "tgkill",     .errmsg = true,
538           .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
539         { .name     = "tkill",      .errmsg = true,
540           .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
541         { .name     = "uname",      .errmsg = true, .alias = "newuname", },
542 };
543
544 static int syscall_fmt__cmp(const void *name, const void *fmtp)
545 {
546         const struct syscall_fmt *fmt = fmtp;
547         return strcmp(name, fmt->name);
548 }
549
550 static struct syscall_fmt *syscall_fmt__find(const char *name)
551 {
552         const int nmemb = ARRAY_SIZE(syscall_fmts);
553         return bsearch(name, syscall_fmts, nmemb, sizeof(struct syscall_fmt), syscall_fmt__cmp);
554 }
555
556 struct syscall {
557         struct event_format *tp_format;
558         const char          *name;
559         bool                filtered;
560         struct syscall_fmt  *fmt;
561         size_t              (**arg_scnprintf)(char *bf, size_t size, struct syscall_arg *arg);
562         void                **arg_parm;
563 };
564
565 static size_t fprintf_duration(unsigned long t, FILE *fp)
566 {
567         double duration = (double)t / NSEC_PER_MSEC;
568         size_t printed = fprintf(fp, "(");
569
570         if (duration >= 1.0)
571                 printed += color_fprintf(fp, PERF_COLOR_RED, "%6.3f ms", duration);
572         else if (duration >= 0.01)
573                 printed += color_fprintf(fp, PERF_COLOR_YELLOW, "%6.3f ms", duration);
574         else
575                 printed += color_fprintf(fp, PERF_COLOR_NORMAL, "%6.3f ms", duration);
576         return printed + fprintf(fp, "): ");
577 }
578
579 struct thread_trace {
580         u64               entry_time;
581         u64               exit_time;
582         bool              entry_pending;
583         unsigned long     nr_events;
584         char              *entry_str;
585         double            runtime_ms;
586 };
587
588 static struct thread_trace *thread_trace__new(void)
589 {
590         return zalloc(sizeof(struct thread_trace));
591 }
592
593 static struct thread_trace *thread__trace(struct thread *thread, FILE *fp)
594 {
595         struct thread_trace *ttrace;
596
597         if (thread == NULL)
598                 goto fail;
599
600         if (thread->priv == NULL)
601                 thread->priv = thread_trace__new();
602                 
603         if (thread->priv == NULL)
604                 goto fail;
605
606         ttrace = thread->priv;
607         ++ttrace->nr_events;
608
609         return ttrace;
610 fail:
611         color_fprintf(fp, PERF_COLOR_RED,
612                       "WARNING: not enough memory, dropping samples!\n");
613         return NULL;
614 }
615
616 struct trace {
617         struct perf_tool        tool;
618         int                     audit_machine;
619         struct {
620                 int             max;
621                 struct syscall  *table;
622         } syscalls;
623         struct perf_record_opts opts;
624         struct machine          host;
625         u64                     base_time;
626         bool                    full_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                         if (args[arg.idx] == 0)
822                                 continue;
823
824                         printed += scnprintf(bf + printed, size - printed,
825                                              "%s%s: ", printed ? ", " : "", field->name);
826                         if (sc->arg_scnprintf && sc->arg_scnprintf[arg.idx]) {
827                                 arg.val = args[arg.idx];
828                                 if (sc->arg_parm)
829                                         arg.parm = sc->arg_parm[arg.idx];
830                                 printed += sc->arg_scnprintf[arg.idx](bf + printed,
831                                                                       size - printed, &arg);
832                         } else {
833                                 printed += scnprintf(bf + printed, size - printed,
834                                                      "%ld", args[arg.idx]);
835                         }
836                 }
837         } else {
838                 int i = 0;
839
840                 while (i < 6) {
841                         printed += scnprintf(bf + printed, size - printed,
842                                              "%sarg%d: %ld",
843                                              printed ? ", " : "", i, args[i]);
844                         ++i;
845                 }
846         }
847
848         return printed;
849 }
850
851 typedef int (*tracepoint_handler)(struct trace *trace, struct perf_evsel *evsel,
852                                   struct perf_sample *sample);
853
854 static struct syscall *trace__syscall_info(struct trace *trace,
855                                            struct perf_evsel *evsel,
856                                            struct perf_sample *sample)
857 {
858         int id = perf_evsel__intval(evsel, sample, "id");
859
860         if (id < 0) {
861
862                 /*
863                  * XXX: Noticed on x86_64, reproduced as far back as 3.0.36, haven't tried
864                  * before that, leaving at a higher verbosity level till that is
865                  * explained. Reproduced with plain ftrace with:
866                  *
867                  * echo 1 > /t/events/raw_syscalls/sys_exit/enable
868                  * grep "NR -1 " /t/trace_pipe
869                  *
870                  * After generating some load on the machine.
871                  */
872                 if (verbose > 1) {
873                         static u64 n;
874                         fprintf(trace->output, "Invalid syscall %d id, skipping (%s, %" PRIu64 ") ...\n",
875                                 id, perf_evsel__name(evsel), ++n);
876                 }
877                 return NULL;
878         }
879
880         if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL) &&
881             trace__read_syscall_info(trace, id))
882                 goto out_cant_read;
883
884         if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL))
885                 goto out_cant_read;
886
887         return &trace->syscalls.table[id];
888
889 out_cant_read:
890         if (verbose) {
891                 fprintf(trace->output, "Problems reading syscall %d", id);
892                 if (id <= trace->syscalls.max && trace->syscalls.table[id].name != NULL)
893                         fprintf(trace->output, "(%s)", trace->syscalls.table[id].name);
894                 fputs(" information\n", trace->output);
895         }
896         return NULL;
897 }
898
899 static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
900                             struct perf_sample *sample)
901 {
902         char *msg;
903         void *args;
904         size_t printed = 0;
905         struct thread *thread;
906         struct syscall *sc = trace__syscall_info(trace, evsel, sample);
907         struct thread_trace *ttrace;
908
909         if (sc == NULL)
910                 return -1;
911
912         if (sc->filtered)
913                 return 0;
914
915         thread = machine__findnew_thread(&trace->host, sample->pid,
916                                          sample->tid);
917         ttrace = thread__trace(thread, trace->output);
918         if (ttrace == NULL)
919                 return -1;
920
921         args = perf_evsel__rawptr(evsel, sample, "args");
922         if (args == NULL) {
923                 fprintf(trace->output, "Problems reading syscall arguments\n");
924                 return -1;
925         }
926
927         ttrace = thread->priv;
928
929         if (ttrace->entry_str == NULL) {
930                 ttrace->entry_str = malloc(1024);
931                 if (!ttrace->entry_str)
932                         return -1;
933         }
934
935         ttrace->entry_time = sample->time;
936         msg = ttrace->entry_str;
937         printed += scnprintf(msg + printed, 1024 - printed, "%s(", sc->name);
938
939         printed += syscall__scnprintf_args(sc, msg + printed, 1024 - printed,  args);
940
941         if (!strcmp(sc->name, "exit_group") || !strcmp(sc->name, "exit")) {
942                 if (!trace->duration_filter) {
943                         trace__fprintf_entry_head(trace, thread, 1, sample->time, trace->output);
944                         fprintf(trace->output, "%-70s\n", ttrace->entry_str);
945                 }
946         } else
947                 ttrace->entry_pending = true;
948
949         return 0;
950 }
951
952 static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
953                            struct perf_sample *sample)
954 {
955         int ret;
956         u64 duration = 0;
957         struct thread *thread;
958         struct syscall *sc = trace__syscall_info(trace, evsel, sample);
959         struct thread_trace *ttrace;
960
961         if (sc == NULL)
962                 return -1;
963
964         if (sc->filtered)
965                 return 0;
966
967         thread = machine__findnew_thread(&trace->host, sample->pid,
968                                          sample->tid);
969         ttrace = thread__trace(thread, trace->output);
970         if (ttrace == NULL)
971                 return -1;
972
973         ret = perf_evsel__intval(evsel, sample, "ret");
974
975         ttrace = thread->priv;
976
977         ttrace->exit_time = sample->time;
978
979         if (ttrace->entry_time) {
980                 duration = sample->time - ttrace->entry_time;
981                 if (trace__filter_duration(trace, duration))
982                         goto out;
983         } else if (trace->duration_filter)
984                 goto out;
985
986         trace__fprintf_entry_head(trace, thread, duration, sample->time, trace->output);
987
988         if (ttrace->entry_pending) {
989                 fprintf(trace->output, "%-70s", ttrace->entry_str);
990         } else {
991                 fprintf(trace->output, " ... [");
992                 color_fprintf(trace->output, PERF_COLOR_YELLOW, "continued");
993                 fprintf(trace->output, "]: %s()", sc->name);
994         }
995
996         if (sc->fmt == NULL) {
997 signed_print:
998                 fprintf(trace->output, ") = %d", ret);
999         } else if (ret < 0 && sc->fmt->errmsg) {
1000                 char bf[256];
1001                 const char *emsg = strerror_r(-ret, bf, sizeof(bf)),
1002                            *e = audit_errno_to_name(-ret);
1003
1004                 fprintf(trace->output, ") = -1 %s %s", e, emsg);
1005         } else if (ret == 0 && sc->fmt->timeout)
1006                 fprintf(trace->output, ") = 0 Timeout");
1007         else if (sc->fmt->hexret)
1008                 fprintf(trace->output, ") = %#x", ret);
1009         else
1010                 goto signed_print;
1011
1012         fputc('\n', trace->output);
1013 out:
1014         ttrace->entry_pending = false;
1015
1016         return 0;
1017 }
1018
1019 static int trace__sched_stat_runtime(struct trace *trace, struct perf_evsel *evsel,
1020                                      struct perf_sample *sample)
1021 {
1022         u64 runtime = perf_evsel__intval(evsel, sample, "runtime");
1023         double runtime_ms = (double)runtime / NSEC_PER_MSEC;
1024         struct thread *thread = machine__findnew_thread(&trace->host,
1025                                                         sample->pid,
1026                                                         sample->tid);
1027         struct thread_trace *ttrace = thread__trace(thread, trace->output);
1028
1029         if (ttrace == NULL)
1030                 goto out_dump;
1031
1032         ttrace->runtime_ms += runtime_ms;
1033         trace->runtime_ms += runtime_ms;
1034         return 0;
1035
1036 out_dump:
1037         fprintf(trace->output, "%s: comm=%s,pid=%u,runtime=%" PRIu64 ",vruntime=%" PRIu64 ")\n",
1038                evsel->name,
1039                perf_evsel__strval(evsel, sample, "comm"),
1040                (pid_t)perf_evsel__intval(evsel, sample, "pid"),
1041                runtime,
1042                perf_evsel__intval(evsel, sample, "vruntime"));
1043         return 0;
1044 }
1045
1046 static bool skip_sample(struct trace *trace, struct perf_sample *sample)
1047 {
1048         if ((trace->pid_list && intlist__find(trace->pid_list, sample->pid)) ||
1049             (trace->tid_list && intlist__find(trace->tid_list, sample->tid)))
1050                 return false;
1051
1052         if (trace->pid_list || trace->tid_list)
1053                 return true;
1054
1055         return false;
1056 }
1057
1058 static int trace__process_sample(struct perf_tool *tool,
1059                                  union perf_event *event __maybe_unused,
1060                                  struct perf_sample *sample,
1061                                  struct perf_evsel *evsel,
1062                                  struct machine *machine __maybe_unused)
1063 {
1064         struct trace *trace = container_of(tool, struct trace, tool);
1065         int err = 0;
1066
1067         tracepoint_handler handler = evsel->handler.func;
1068
1069         if (skip_sample(trace, sample))
1070                 return 0;
1071
1072         if (!trace->full_time && trace->base_time == 0)
1073                 trace->base_time = sample->time;
1074
1075         if (handler)
1076                 handler(trace, evsel, sample);
1077
1078         return err;
1079 }
1080
1081 static bool
1082 perf_session__has_tp(struct perf_session *session, const char *name)
1083 {
1084         struct perf_evsel *evsel;
1085
1086         evsel = perf_evlist__find_tracepoint_by_name(session->evlist, name);
1087
1088         return evsel != NULL;
1089 }
1090
1091 static int parse_target_str(struct trace *trace)
1092 {
1093         if (trace->opts.target.pid) {
1094                 trace->pid_list = intlist__new(trace->opts.target.pid);
1095                 if (trace->pid_list == NULL) {
1096                         pr_err("Error parsing process id string\n");
1097                         return -EINVAL;
1098                 }
1099         }
1100
1101         if (trace->opts.target.tid) {
1102                 trace->tid_list = intlist__new(trace->opts.target.tid);
1103                 if (trace->tid_list == NULL) {
1104                         pr_err("Error parsing thread id string\n");
1105                         return -EINVAL;
1106                 }
1107         }
1108
1109         return 0;
1110 }
1111
1112 static int trace__run(struct trace *trace, int argc, const char **argv)
1113 {
1114         struct perf_evlist *evlist = perf_evlist__new();
1115         struct perf_evsel *evsel;
1116         int err = -1, i;
1117         unsigned long before;
1118         const bool forks = argc > 0;
1119
1120         if (evlist == NULL) {
1121                 fprintf(trace->output, "Not enough memory to run!\n");
1122                 goto out;
1123         }
1124
1125         if (perf_evlist__add_newtp(evlist, "raw_syscalls", "sys_enter", trace__sys_enter) ||
1126             perf_evlist__add_newtp(evlist, "raw_syscalls", "sys_exit", trace__sys_exit)) {
1127                 fprintf(trace->output, "Couldn't read the raw_syscalls tracepoints information!\n");
1128                 goto out_delete_evlist;
1129         }
1130
1131         if (trace->sched &&
1132             perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime",
1133                                    trace__sched_stat_runtime)) {
1134                 fprintf(trace->output, "Couldn't read the sched_stat_runtime tracepoint information!\n");
1135                 goto out_delete_evlist;
1136         }
1137
1138         err = perf_evlist__create_maps(evlist, &trace->opts.target);
1139         if (err < 0) {
1140                 fprintf(trace->output, "Problems parsing the target to trace, check your options!\n");
1141                 goto out_delete_evlist;
1142         }
1143
1144         err = trace__symbols_init(trace, evlist);
1145         if (err < 0) {
1146                 fprintf(trace->output, "Problems initializing symbol libraries!\n");
1147                 goto out_delete_maps;
1148         }
1149
1150         perf_evlist__config(evlist, &trace->opts);
1151
1152         signal(SIGCHLD, sig_handler);
1153         signal(SIGINT, sig_handler);
1154
1155         if (forks) {
1156                 err = perf_evlist__prepare_workload(evlist, &trace->opts.target,
1157                                                     argv, false, false);
1158                 if (err < 0) {
1159                         fprintf(trace->output, "Couldn't run the workload!\n");
1160                         goto out_delete_maps;
1161                 }
1162         }
1163
1164         err = perf_evlist__open(evlist);
1165         if (err < 0) {
1166                 fprintf(trace->output, "Couldn't create the events: %s\n", strerror(errno));
1167                 goto out_delete_maps;
1168         }
1169
1170         err = perf_evlist__mmap(evlist, UINT_MAX, false);
1171         if (err < 0) {
1172                 fprintf(trace->output, "Couldn't mmap the events: %s\n", strerror(errno));
1173                 goto out_close_evlist;
1174         }
1175
1176         perf_evlist__enable(evlist);
1177
1178         if (forks)
1179                 perf_evlist__start_workload(evlist);
1180
1181         trace->multiple_threads = evlist->threads->map[0] == -1 || evlist->threads->nr > 1;
1182 again:
1183         before = trace->nr_events;
1184
1185         for (i = 0; i < evlist->nr_mmaps; i++) {
1186                 union perf_event *event;
1187
1188                 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
1189                         const u32 type = event->header.type;
1190                         tracepoint_handler handler;
1191                         struct perf_sample sample;
1192
1193                         ++trace->nr_events;
1194
1195                         err = perf_evlist__parse_sample(evlist, event, &sample);
1196                         if (err) {
1197                                 fprintf(trace->output, "Can't parse sample, err = %d, skipping...\n", err);
1198                                 continue;
1199                         }
1200
1201                         if (!trace->full_time && trace->base_time == 0)
1202                                 trace->base_time = sample.time;
1203
1204                         if (type != PERF_RECORD_SAMPLE) {
1205                                 trace__process_event(trace, &trace->host, event);
1206                                 continue;
1207                         }
1208
1209                         evsel = perf_evlist__id2evsel(evlist, sample.id);
1210                         if (evsel == NULL) {
1211                                 fprintf(trace->output, "Unknown tp ID %" PRIu64 ", skipping...\n", sample.id);
1212                                 continue;
1213                         }
1214
1215                         if (sample.raw_data == NULL) {
1216                                 fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n",
1217                                        perf_evsel__name(evsel), sample.tid,
1218                                        sample.cpu, sample.raw_size);
1219                                 continue;
1220                         }
1221
1222                         handler = evsel->handler.func;
1223                         handler(trace, evsel, &sample);
1224
1225                         if (done)
1226                                 goto out_unmap_evlist;
1227                 }
1228         }
1229
1230         if (trace->nr_events == before) {
1231                 if (done)
1232                         goto out_unmap_evlist;
1233
1234                 poll(evlist->pollfd, evlist->nr_fds, -1);
1235         }
1236
1237         if (done)
1238                 perf_evlist__disable(evlist);
1239
1240         goto again;
1241
1242 out_unmap_evlist:
1243         perf_evlist__munmap(evlist);
1244 out_close_evlist:
1245         perf_evlist__close(evlist);
1246 out_delete_maps:
1247         perf_evlist__delete_maps(evlist);
1248 out_delete_evlist:
1249         perf_evlist__delete(evlist);
1250 out:
1251         return err;
1252 }
1253
1254 static int trace__replay(struct trace *trace)
1255 {
1256         const struct perf_evsel_str_handler handlers[] = {
1257                 { "raw_syscalls:sys_enter",  trace__sys_enter, },
1258                 { "raw_syscalls:sys_exit",   trace__sys_exit, },
1259         };
1260
1261         struct perf_session *session;
1262         int err = -1;
1263
1264         trace->tool.sample        = trace__process_sample;
1265         trace->tool.mmap          = perf_event__process_mmap;
1266         trace->tool.mmap2         = perf_event__process_mmap2;
1267         trace->tool.comm          = perf_event__process_comm;
1268         trace->tool.exit          = perf_event__process_exit;
1269         trace->tool.fork          = perf_event__process_fork;
1270         trace->tool.attr          = perf_event__process_attr;
1271         trace->tool.tracing_data = perf_event__process_tracing_data;
1272         trace->tool.build_id      = perf_event__process_build_id;
1273
1274         trace->tool.ordered_samples = true;
1275         trace->tool.ordering_requires_timestamps = true;
1276
1277         /* add tid to output */
1278         trace->multiple_threads = true;
1279
1280         if (symbol__init() < 0)
1281                 return -1;
1282
1283         session = perf_session__new(input_name, O_RDONLY, 0, false,
1284                                     &trace->tool);
1285         if (session == NULL)
1286                 return -ENOMEM;
1287
1288         err = perf_session__set_tracepoints_handlers(session, handlers);
1289         if (err)
1290                 goto out;
1291
1292         if (!perf_session__has_tp(session, "raw_syscalls:sys_enter")) {
1293                 pr_err("Data file does not have raw_syscalls:sys_enter events\n");
1294                 goto out;
1295         }
1296
1297         if (!perf_session__has_tp(session, "raw_syscalls:sys_exit")) {
1298                 pr_err("Data file does not have raw_syscalls:sys_exit events\n");
1299                 goto out;
1300         }
1301
1302         err = parse_target_str(trace);
1303         if (err != 0)
1304                 goto out;
1305
1306         setup_pager();
1307
1308         err = perf_session__process_events(session, &trace->tool);
1309         if (err)
1310                 pr_err("Failed to process events, error %d", err);
1311
1312 out:
1313         perf_session__delete(session);
1314
1315         return err;
1316 }
1317
1318 static size_t trace__fprintf_threads_header(FILE *fp)
1319 {
1320         size_t printed;
1321
1322         printed  = fprintf(fp, "\n _____________________________________________________________________\n");
1323         printed += fprintf(fp," __)    Summary of events    (__\n\n");
1324         printed += fprintf(fp,"              [ task - pid ]     [ events ] [ ratio ]  [ runtime ]\n");
1325         printed += fprintf(fp," _____________________________________________________________________\n\n");
1326
1327         return printed;
1328 }
1329
1330 static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp)
1331 {
1332         size_t printed = trace__fprintf_threads_header(fp);
1333         struct rb_node *nd;
1334
1335         for (nd = rb_first(&trace->host.threads); nd; nd = rb_next(nd)) {
1336                 struct thread *thread = rb_entry(nd, struct thread, rb_node);
1337                 struct thread_trace *ttrace = thread->priv;
1338                 const char *color;
1339                 double ratio;
1340
1341                 if (ttrace == NULL)
1342                         continue;
1343
1344                 ratio = (double)ttrace->nr_events / trace->nr_events * 100.0;
1345
1346                 color = PERF_COLOR_NORMAL;
1347                 if (ratio > 50.0)
1348                         color = PERF_COLOR_RED;
1349                 else if (ratio > 25.0)
1350                         color = PERF_COLOR_GREEN;
1351                 else if (ratio > 5.0)
1352                         color = PERF_COLOR_YELLOW;
1353
1354                 printed += color_fprintf(fp, color, "%20s", thread->comm);
1355                 printed += fprintf(fp, " - %-5d :%11lu   [", thread->tid, ttrace->nr_events);
1356                 printed += color_fprintf(fp, color, "%5.1f%%", ratio);
1357                 printed += fprintf(fp, " ] %10.3f ms\n", ttrace->runtime_ms);
1358         }
1359
1360         return printed;
1361 }
1362
1363 static int trace__set_duration(const struct option *opt, const char *str,
1364                                int unset __maybe_unused)
1365 {
1366         struct trace *trace = opt->value;
1367
1368         trace->duration_filter = atof(str);
1369         return 0;
1370 }
1371
1372 static int trace__open_output(struct trace *trace, const char *filename)
1373 {
1374         struct stat st;
1375
1376         if (!stat(filename, &st) && st.st_size) {
1377                 char oldname[PATH_MAX];
1378
1379                 scnprintf(oldname, sizeof(oldname), "%s.old", filename);
1380                 unlink(oldname);
1381                 rename(filename, oldname);
1382         }
1383
1384         trace->output = fopen(filename, "w");
1385
1386         return trace->output == NULL ? -errno : 0;
1387 }
1388
1389 int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
1390 {
1391         const char * const trace_usage[] = {
1392                 "perf trace [<options>] [<command>]",
1393                 "perf trace [<options>] -- <command> [<options>]",
1394                 NULL
1395         };
1396         struct trace trace = {
1397                 .audit_machine = audit_detect_machine(),
1398                 .syscalls = {
1399                         . max = -1,
1400                 },
1401                 .opts = {
1402                         .target = {
1403                                 .uid       = UINT_MAX,
1404                                 .uses_mmap = true,
1405                         },
1406                         .user_freq     = UINT_MAX,
1407                         .user_interval = ULLONG_MAX,
1408                         .no_delay      = true,
1409                         .mmap_pages    = 1024,
1410                 },
1411                 .output = stdout,
1412         };
1413         const char *output_name = NULL;
1414         const char *ev_qualifier_str = NULL;
1415         const struct option trace_options[] = {
1416         OPT_STRING('e', "expr", &ev_qualifier_str, "expr",
1417                     "list of events to trace"),
1418         OPT_STRING('o', "output", &output_name, "file", "output file name"),
1419         OPT_STRING('i', "input", &input_name, "file", "Analyze events in file"),
1420         OPT_STRING('p', "pid", &trace.opts.target.pid, "pid",
1421                     "trace events on existing process id"),
1422         OPT_STRING('t', "tid", &trace.opts.target.tid, "tid",
1423                     "trace events on existing thread id"),
1424         OPT_BOOLEAN('a', "all-cpus", &trace.opts.target.system_wide,
1425                     "system-wide collection from all CPUs"),
1426         OPT_STRING('C', "cpu", &trace.opts.target.cpu_list, "cpu",
1427                     "list of cpus to monitor"),
1428         OPT_BOOLEAN(0, "no-inherit", &trace.opts.no_inherit,
1429                     "child tasks do not inherit counters"),
1430         OPT_UINTEGER('m', "mmap-pages", &trace.opts.mmap_pages,
1431                      "number of mmap data pages"),
1432         OPT_STRING('u', "uid", &trace.opts.target.uid_str, "user",
1433                    "user to profile"),
1434         OPT_CALLBACK(0, "duration", &trace, "float",
1435                      "show only events with duration > N.M ms",
1436                      trace__set_duration),
1437         OPT_BOOLEAN(0, "sched", &trace.sched, "show blocking scheduler events"),
1438         OPT_INCR('v', "verbose", &verbose, "be more verbose"),
1439         OPT_BOOLEAN('T', "time", &trace.full_time,
1440                     "Show full timestamp, not time relative to first start"),
1441         OPT_END()
1442         };
1443         int err;
1444         char bf[BUFSIZ];
1445
1446         argc = parse_options(argc, argv, trace_options, trace_usage, 0);
1447
1448         if (output_name != NULL) {
1449                 err = trace__open_output(&trace, output_name);
1450                 if (err < 0) {
1451                         perror("failed to create output file");
1452                         goto out;
1453                 }
1454         }
1455
1456         if (ev_qualifier_str != NULL) {
1457                 const char *s = ev_qualifier_str;
1458
1459                 trace.not_ev_qualifier = *s == '!';
1460                 if (trace.not_ev_qualifier)
1461                         ++s;
1462                 trace.ev_qualifier = strlist__new(true, s);
1463                 if (trace.ev_qualifier == NULL) {
1464                         fputs("Not enough memory to parse event qualifier",
1465                               trace.output);
1466                         err = -ENOMEM;
1467                         goto out_close;
1468                 }
1469         }
1470
1471         err = perf_target__validate(&trace.opts.target);
1472         if (err) {
1473                 perf_target__strerror(&trace.opts.target, err, bf, sizeof(bf));
1474                 fprintf(trace.output, "%s", bf);
1475                 goto out_close;
1476         }
1477
1478         err = perf_target__parse_uid(&trace.opts.target);
1479         if (err) {
1480                 perf_target__strerror(&trace.opts.target, err, bf, sizeof(bf));
1481                 fprintf(trace.output, "%s", bf);
1482                 goto out_close;
1483         }
1484
1485         if (!argc && perf_target__none(&trace.opts.target))
1486                 trace.opts.target.system_wide = true;
1487
1488         if (input_name)
1489                 err = trace__replay(&trace);
1490         else
1491                 err = trace__run(&trace, argc, argv);
1492
1493         if (trace.sched && !err)
1494                 trace__fprintf_thread_summary(&trace, trace.output);
1495
1496 out_close:
1497         if (output_name != NULL)
1498                 fclose(trace.output);
1499 out:
1500         return err;
1501 }