perf trace: Beautify socket 'family' arg
[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 *sighow[] = { "BLOCK", "UNBLOCK", "SETMASK", };
256 static DEFINE_STRARRAY(sighow);
257
258 static const char *socket_families[] = {
259         "UNSPEC", "LOCAL", "INET", "AX25", "IPX", "APPLETALK", "NETROM",
260         "BRIDGE", "ATMPVC", "X25", "INET6", "ROSE", "DECnet", "NETBEUI",
261         "SECURITY", "KEY", "NETLINK", "PACKET", "ASH", "ECONET", "ATMSVC",
262         "RDS", "SNA", "IRDA", "PPPOX", "WANPIPE", "LLC", "IB", "CAN", "TIPC",
263         "BLUETOOTH", "IUCV", "RXRPC", "ISDN", "PHONET", "IEEE802154", "CAIF",
264         "ALG", "NFC", "VSOCK",
265 };
266 static DEFINE_STRARRAY(socket_families);
267
268 static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
269                                                struct syscall_arg *arg)
270 {
271         int printed = 0, flags = arg->val;
272
273         if (!(flags & O_CREAT))
274                 arg->mask |= 1 << (arg->idx + 1); /* Mask the mode parm */
275
276         if (flags == 0)
277                 return scnprintf(bf, size, "RDONLY");
278 #define P_FLAG(n) \
279         if (flags & O_##n) { \
280                 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
281                 flags &= ~O_##n; \
282         }
283
284         P_FLAG(APPEND);
285         P_FLAG(ASYNC);
286         P_FLAG(CLOEXEC);
287         P_FLAG(CREAT);
288         P_FLAG(DIRECT);
289         P_FLAG(DIRECTORY);
290         P_FLAG(EXCL);
291         P_FLAG(LARGEFILE);
292         P_FLAG(NOATIME);
293         P_FLAG(NOCTTY);
294 #ifdef O_NONBLOCK
295         P_FLAG(NONBLOCK);
296 #elif O_NDELAY
297         P_FLAG(NDELAY);
298 #endif
299 #ifdef O_PATH
300         P_FLAG(PATH);
301 #endif
302         P_FLAG(RDWR);
303 #ifdef O_DSYNC
304         if ((flags & O_SYNC) == O_SYNC)
305                 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", "SYNC");
306         else {
307                 P_FLAG(DSYNC);
308         }
309 #else
310         P_FLAG(SYNC);
311 #endif
312         P_FLAG(TRUNC);
313         P_FLAG(WRONLY);
314 #undef P_FLAG
315
316         if (flags)
317                 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
318
319         return printed;
320 }
321
322 #define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags
323
324 static size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscall_arg *arg)
325 {
326         int sig = arg->val;
327
328         switch (sig) {
329 #define P_SIGNUM(n) case SIG##n: return scnprintf(bf, size, #n)
330         P_SIGNUM(HUP);
331         P_SIGNUM(INT);
332         P_SIGNUM(QUIT);
333         P_SIGNUM(ILL);
334         P_SIGNUM(TRAP);
335         P_SIGNUM(ABRT);
336         P_SIGNUM(BUS);
337         P_SIGNUM(FPE);
338         P_SIGNUM(KILL);
339         P_SIGNUM(USR1);
340         P_SIGNUM(SEGV);
341         P_SIGNUM(USR2);
342         P_SIGNUM(PIPE);
343         P_SIGNUM(ALRM);
344         P_SIGNUM(TERM);
345         P_SIGNUM(STKFLT);
346         P_SIGNUM(CHLD);
347         P_SIGNUM(CONT);
348         P_SIGNUM(STOP);
349         P_SIGNUM(TSTP);
350         P_SIGNUM(TTIN);
351         P_SIGNUM(TTOU);
352         P_SIGNUM(URG);
353         P_SIGNUM(XCPU);
354         P_SIGNUM(XFSZ);
355         P_SIGNUM(VTALRM);
356         P_SIGNUM(PROF);
357         P_SIGNUM(WINCH);
358         P_SIGNUM(IO);
359         P_SIGNUM(PWR);
360         P_SIGNUM(SYS);
361         default: break;
362         }
363
364         return scnprintf(bf, size, "%#x", sig);
365 }
366
367 #define SCA_SIGNUM syscall_arg__scnprintf_signum
368
369 static struct syscall_fmt {
370         const char *name;
371         const char *alias;
372         size_t     (*arg_scnprintf[6])(char *bf, size_t size, struct syscall_arg *arg);
373         void       *arg_parm[6];
374         bool       errmsg;
375         bool       timeout;
376         bool       hexret;
377 } syscall_fmts[] = {
378         { .name     = "access",     .errmsg = true, },
379         { .name     = "arch_prctl", .errmsg = true, .alias = "prctl", },
380         { .name     = "brk",        .hexret = true,
381           .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, },
382         { .name     = "mmap",       .hexret = true, },
383         { .name     = "connect",    .errmsg = true, },
384         { .name     = "fcntl",      .errmsg = true,
385           .arg_scnprintf = { [1] = SCA_STRARRAY, /* cmd */ },
386           .arg_parm      = { [1] = &strarray__fcntl_cmds, /* cmd */ }, },
387         { .name     = "fstat",      .errmsg = true, .alias = "newfstat", },
388         { .name     = "fstatat",    .errmsg = true, .alias = "newfstatat", },
389         { .name     = "futex",      .errmsg = true,
390           .arg_scnprintf = { [1] = SCA_FUTEX_OP, /* op */ }, },
391         { .name     = "getitimer",  .errmsg = true,
392           .arg_scnprintf = { [0] = SCA_STRARRAY, /* which */ },
393           .arg_parm      = { [0] = &strarray__itimers, /* which */ }, },
394         { .name     = "ioctl",      .errmsg = true,
395           .arg_scnprintf = { [2] = SCA_HEX, /* arg */ }, },
396         { .name     = "kill",       .errmsg = true,
397           .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
398         { .name     = "lseek",      .errmsg = true,
399           .arg_scnprintf = { [2] = SCA_STRARRAY, /* whence */ },
400           .arg_parm      = { [2] = &strarray__whences, /* whence */ }, },
401         { .name     = "lstat",      .errmsg = true, .alias = "newlstat", },
402         { .name     = "madvise",    .errmsg = true,
403           .arg_scnprintf = { [0] = SCA_HEX,      /* start */
404                              [2] = SCA_MADV_BHV, /* behavior */ }, },
405         { .name     = "mmap",       .hexret = true,
406           .arg_scnprintf = { [0] = SCA_HEX,       /* addr */
407                              [2] = SCA_MMAP_PROT, /* prot */
408                              [3] = SCA_MMAP_FLAGS, /* flags */ }, },
409         { .name     = "mprotect",   .errmsg = true,
410           .arg_scnprintf = { [0] = SCA_HEX, /* start */
411                              [2] = SCA_MMAP_PROT, /* prot */ }, },
412         { .name     = "mremap",     .hexret = true,
413           .arg_scnprintf = { [0] = SCA_HEX, /* addr */
414                              [4] = SCA_HEX, /* new_addr */ }, },
415         { .name     = "munmap",     .errmsg = true,
416           .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
417         { .name     = "open",       .errmsg = true,
418           .arg_scnprintf = { [1] = SCA_OPEN_FLAGS, /* flags */ }, },
419         { .name     = "open_by_handle_at", .errmsg = true,
420           .arg_scnprintf = { [2] = SCA_OPEN_FLAGS, /* flags */ }, },
421         { .name     = "openat",     .errmsg = true,
422           .arg_scnprintf = { [2] = SCA_OPEN_FLAGS, /* flags */ }, },
423         { .name     = "poll",       .errmsg = true, .timeout = true, },
424         { .name     = "ppoll",      .errmsg = true, .timeout = true, },
425         { .name     = "pread",      .errmsg = true, .alias = "pread64", },
426         { .name     = "pwrite",     .errmsg = true, .alias = "pwrite64", },
427         { .name     = "read",       .errmsg = true, },
428         { .name     = "recvfrom",   .errmsg = true, },
429         { .name     = "rt_sigaction", .errmsg = true,
430           .arg_scnprintf = { [0] = SCA_SIGNUM, /* sig */ }, },
431         { .name     = "rt_sigprocmask", .errmsg = true,
432           .arg_scnprintf = { [0] = SCA_STRARRAY, /* how */ },
433           .arg_parm      = { [0] = &strarray__sighow, /* how */ }, },
434         { .name     = "rt_sigqueueinfo", .errmsg = true,
435           .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
436         { .name     = "rt_tgsigqueueinfo", .errmsg = true,
437           .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
438         { .name     = "select",     .errmsg = true, .timeout = true, },
439         { .name     = "setitimer",  .errmsg = true,
440           .arg_scnprintf = { [0] = SCA_STRARRAY, /* which */ },
441           .arg_parm      = { [0] = &strarray__itimers, /* which */ }, },
442         { .name     = "socket",     .errmsg = true,
443           .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */ },
444           .arg_parm      = { [0] = &strarray__socket_families, /* family */ }, },
445         { .name     = "stat",       .errmsg = true, .alias = "newstat", },
446         { .name     = "tgkill",     .errmsg = true,
447           .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
448         { .name     = "tkill",      .errmsg = true,
449           .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
450         { .name     = "uname",      .errmsg = true, .alias = "newuname", },
451 };
452
453 static int syscall_fmt__cmp(const void *name, const void *fmtp)
454 {
455         const struct syscall_fmt *fmt = fmtp;
456         return strcmp(name, fmt->name);
457 }
458
459 static struct syscall_fmt *syscall_fmt__find(const char *name)
460 {
461         const int nmemb = ARRAY_SIZE(syscall_fmts);
462         return bsearch(name, syscall_fmts, nmemb, sizeof(struct syscall_fmt), syscall_fmt__cmp);
463 }
464
465 struct syscall {
466         struct event_format *tp_format;
467         const char          *name;
468         bool                filtered;
469         struct syscall_fmt  *fmt;
470         size_t              (**arg_scnprintf)(char *bf, size_t size, struct syscall_arg *arg);
471         void                **arg_parm;
472 };
473
474 static size_t fprintf_duration(unsigned long t, FILE *fp)
475 {
476         double duration = (double)t / NSEC_PER_MSEC;
477         size_t printed = fprintf(fp, "(");
478
479         if (duration >= 1.0)
480                 printed += color_fprintf(fp, PERF_COLOR_RED, "%6.3f ms", duration);
481         else if (duration >= 0.01)
482                 printed += color_fprintf(fp, PERF_COLOR_YELLOW, "%6.3f ms", duration);
483         else
484                 printed += color_fprintf(fp, PERF_COLOR_NORMAL, "%6.3f ms", duration);
485         return printed + fprintf(fp, "): ");
486 }
487
488 struct thread_trace {
489         u64               entry_time;
490         u64               exit_time;
491         bool              entry_pending;
492         unsigned long     nr_events;
493         char              *entry_str;
494         double            runtime_ms;
495 };
496
497 static struct thread_trace *thread_trace__new(void)
498 {
499         return zalloc(sizeof(struct thread_trace));
500 }
501
502 static struct thread_trace *thread__trace(struct thread *thread, FILE *fp)
503 {
504         struct thread_trace *ttrace;
505
506         if (thread == NULL)
507                 goto fail;
508
509         if (thread->priv == NULL)
510                 thread->priv = thread_trace__new();
511                 
512         if (thread->priv == NULL)
513                 goto fail;
514
515         ttrace = thread->priv;
516         ++ttrace->nr_events;
517
518         return ttrace;
519 fail:
520         color_fprintf(fp, PERF_COLOR_RED,
521                       "WARNING: not enough memory, dropping samples!\n");
522         return NULL;
523 }
524
525 struct trace {
526         struct perf_tool        tool;
527         int                     audit_machine;
528         struct {
529                 int             max;
530                 struct syscall  *table;
531         } syscalls;
532         struct perf_record_opts opts;
533         struct machine          host;
534         u64                     base_time;
535         FILE                    *output;
536         unsigned long           nr_events;
537         struct strlist          *ev_qualifier;
538         bool                    not_ev_qualifier;
539         struct intlist          *tid_list;
540         struct intlist          *pid_list;
541         bool                    sched;
542         bool                    multiple_threads;
543         double                  duration_filter;
544         double                  runtime_ms;
545 };
546
547 static bool trace__filter_duration(struct trace *trace, double t)
548 {
549         return t < (trace->duration_filter * NSEC_PER_MSEC);
550 }
551
552 static size_t trace__fprintf_tstamp(struct trace *trace, u64 tstamp, FILE *fp)
553 {
554         double ts = (double)(tstamp - trace->base_time) / NSEC_PER_MSEC;
555
556         return fprintf(fp, "%10.3f ", ts);
557 }
558
559 static bool done = false;
560
561 static void sig_handler(int sig __maybe_unused)
562 {
563         done = true;
564 }
565
566 static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thread,
567                                         u64 duration, u64 tstamp, FILE *fp)
568 {
569         size_t printed = trace__fprintf_tstamp(trace, tstamp, fp);
570         printed += fprintf_duration(duration, fp);
571
572         if (trace->multiple_threads)
573                 printed += fprintf(fp, "%d ", thread->tid);
574
575         return printed;
576 }
577
578 static int trace__process_event(struct trace *trace, struct machine *machine,
579                                 union perf_event *event)
580 {
581         int ret = 0;
582
583         switch (event->header.type) {
584         case PERF_RECORD_LOST:
585                 color_fprintf(trace->output, PERF_COLOR_RED,
586                               "LOST %" PRIu64 " events!\n", event->lost.lost);
587                 ret = machine__process_lost_event(machine, event);
588         default:
589                 ret = machine__process_event(machine, event);
590                 break;
591         }
592
593         return ret;
594 }
595
596 static int trace__tool_process(struct perf_tool *tool,
597                                union perf_event *event,
598                                struct perf_sample *sample __maybe_unused,
599                                struct machine *machine)
600 {
601         struct trace *trace = container_of(tool, struct trace, tool);
602         return trace__process_event(trace, machine, event);
603 }
604
605 static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
606 {
607         int err = symbol__init();
608
609         if (err)
610                 return err;
611
612         machine__init(&trace->host, "", HOST_KERNEL_ID);
613         machine__create_kernel_maps(&trace->host);
614
615         if (perf_target__has_task(&trace->opts.target)) {
616                 err = perf_event__synthesize_thread_map(&trace->tool, evlist->threads,
617                                                         trace__tool_process,
618                                                         &trace->host);
619         } else {
620                 err = perf_event__synthesize_threads(&trace->tool, trace__tool_process,
621                                                      &trace->host);
622         }
623
624         if (err)
625                 symbol__exit();
626
627         return err;
628 }
629
630 static int syscall__set_arg_fmts(struct syscall *sc)
631 {
632         struct format_field *field;
633         int idx = 0;
634
635         sc->arg_scnprintf = calloc(sc->tp_format->format.nr_fields - 1, sizeof(void *));
636         if (sc->arg_scnprintf == NULL)
637                 return -1;
638
639         if (sc->fmt)
640                 sc->arg_parm = sc->fmt->arg_parm;
641
642         for (field = sc->tp_format->format.fields->next; field; field = field->next) {
643                 if (sc->fmt && sc->fmt->arg_scnprintf[idx])
644                         sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx];
645                 else if (field->flags & FIELD_IS_POINTER)
646                         sc->arg_scnprintf[idx] = syscall_arg__scnprintf_hex;
647                 ++idx;
648         }
649
650         return 0;
651 }
652
653 static int trace__read_syscall_info(struct trace *trace, int id)
654 {
655         char tp_name[128];
656         struct syscall *sc;
657         const char *name = audit_syscall_to_name(id, trace->audit_machine);
658
659         if (name == NULL)
660                 return -1;
661
662         if (id > trace->syscalls.max) {
663                 struct syscall *nsyscalls = realloc(trace->syscalls.table, (id + 1) * sizeof(*sc));
664
665                 if (nsyscalls == NULL)
666                         return -1;
667
668                 if (trace->syscalls.max != -1) {
669                         memset(nsyscalls + trace->syscalls.max + 1, 0,
670                                (id - trace->syscalls.max) * sizeof(*sc));
671                 } else {
672                         memset(nsyscalls, 0, (id + 1) * sizeof(*sc));
673                 }
674
675                 trace->syscalls.table = nsyscalls;
676                 trace->syscalls.max   = id;
677         }
678
679         sc = trace->syscalls.table + id;
680         sc->name = name;
681
682         if (trace->ev_qualifier) {
683                 bool in = strlist__find(trace->ev_qualifier, name) != NULL;
684
685                 if (!(in ^ trace->not_ev_qualifier)) {
686                         sc->filtered = true;
687                         /*
688                          * No need to do read tracepoint information since this will be
689                          * filtered out.
690                          */
691                         return 0;
692                 }
693         }
694
695         sc->fmt  = syscall_fmt__find(sc->name);
696
697         snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name);
698         sc->tp_format = event_format__new("syscalls", tp_name);
699
700         if (sc->tp_format == NULL && sc->fmt && sc->fmt->alias) {
701                 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->fmt->alias);
702                 sc->tp_format = event_format__new("syscalls", tp_name);
703         }
704
705         if (sc->tp_format == NULL)
706                 return -1;
707
708         return syscall__set_arg_fmts(sc);
709 }
710
711 static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
712                                       unsigned long *args)
713 {
714         size_t printed = 0;
715
716         if (sc->tp_format != NULL) {
717                 struct format_field *field;
718                 u8 bit = 1;
719                 struct syscall_arg arg = {
720                         .idx  = 0,
721                         .mask = 0,
722                 };
723
724                 for (field = sc->tp_format->format.fields->next; field;
725                      field = field->next, ++arg.idx, bit <<= 1) {
726                         if (arg.mask & bit)
727                                 continue;
728
729                         printed += scnprintf(bf + printed, size - printed,
730                                              "%s%s: ", printed ? ", " : "", field->name);
731                         if (sc->arg_scnprintf && sc->arg_scnprintf[arg.idx]) {
732                                 arg.val = args[arg.idx];
733                                 if (sc->arg_parm)
734                                         arg.parm = sc->arg_parm[arg.idx];
735                                 printed += sc->arg_scnprintf[arg.idx](bf + printed,
736                                                                       size - printed, &arg);
737                         } else {
738                                 printed += scnprintf(bf + printed, size - printed,
739                                                      "%ld", args[arg.idx]);
740                         }
741                 }
742         } else {
743                 int i = 0;
744
745                 while (i < 6) {
746                         printed += scnprintf(bf + printed, size - printed,
747                                              "%sarg%d: %ld",
748                                              printed ? ", " : "", i, args[i]);
749                         ++i;
750                 }
751         }
752
753         return printed;
754 }
755
756 typedef int (*tracepoint_handler)(struct trace *trace, struct perf_evsel *evsel,
757                                   struct perf_sample *sample);
758
759 static struct syscall *trace__syscall_info(struct trace *trace,
760                                            struct perf_evsel *evsel,
761                                            struct perf_sample *sample)
762 {
763         int id = perf_evsel__intval(evsel, sample, "id");
764
765         if (id < 0) {
766
767                 /*
768                  * XXX: Noticed on x86_64, reproduced as far back as 3.0.36, haven't tried
769                  * before that, leaving at a higher verbosity level till that is
770                  * explained. Reproduced with plain ftrace with:
771                  *
772                  * echo 1 > /t/events/raw_syscalls/sys_exit/enable
773                  * grep "NR -1 " /t/trace_pipe
774                  *
775                  * After generating some load on the machine.
776                  */
777                 if (verbose > 1) {
778                         static u64 n;
779                         fprintf(trace->output, "Invalid syscall %d id, skipping (%s, %" PRIu64 ") ...\n",
780                                 id, perf_evsel__name(evsel), ++n);
781                 }
782                 return NULL;
783         }
784
785         if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL) &&
786             trace__read_syscall_info(trace, id))
787                 goto out_cant_read;
788
789         if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL))
790                 goto out_cant_read;
791
792         return &trace->syscalls.table[id];
793
794 out_cant_read:
795         if (verbose) {
796                 fprintf(trace->output, "Problems reading syscall %d", id);
797                 if (id <= trace->syscalls.max && trace->syscalls.table[id].name != NULL)
798                         fprintf(trace->output, "(%s)", trace->syscalls.table[id].name);
799                 fputs(" information\n", trace->output);
800         }
801         return NULL;
802 }
803
804 static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
805                             struct perf_sample *sample)
806 {
807         char *msg;
808         void *args;
809         size_t printed = 0;
810         struct thread *thread;
811         struct syscall *sc = trace__syscall_info(trace, evsel, sample);
812         struct thread_trace *ttrace;
813
814         if (sc == NULL)
815                 return -1;
816
817         if (sc->filtered)
818                 return 0;
819
820         thread = machine__findnew_thread(&trace->host, sample->pid,
821                                          sample->tid);
822         ttrace = thread__trace(thread, trace->output);
823         if (ttrace == NULL)
824                 return -1;
825
826         args = perf_evsel__rawptr(evsel, sample, "args");
827         if (args == NULL) {
828                 fprintf(trace->output, "Problems reading syscall arguments\n");
829                 return -1;
830         }
831
832         ttrace = thread->priv;
833
834         if (ttrace->entry_str == NULL) {
835                 ttrace->entry_str = malloc(1024);
836                 if (!ttrace->entry_str)
837                         return -1;
838         }
839
840         ttrace->entry_time = sample->time;
841         msg = ttrace->entry_str;
842         printed += scnprintf(msg + printed, 1024 - printed, "%s(", sc->name);
843
844         printed += syscall__scnprintf_args(sc, msg + printed, 1024 - printed,  args);
845
846         if (!strcmp(sc->name, "exit_group") || !strcmp(sc->name, "exit")) {
847                 if (!trace->duration_filter) {
848                         trace__fprintf_entry_head(trace, thread, 1, sample->time, trace->output);
849                         fprintf(trace->output, "%-70s\n", ttrace->entry_str);
850                 }
851         } else
852                 ttrace->entry_pending = true;
853
854         return 0;
855 }
856
857 static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
858                            struct perf_sample *sample)
859 {
860         int ret;
861         u64 duration = 0;
862         struct thread *thread;
863         struct syscall *sc = trace__syscall_info(trace, evsel, sample);
864         struct thread_trace *ttrace;
865
866         if (sc == NULL)
867                 return -1;
868
869         if (sc->filtered)
870                 return 0;
871
872         thread = machine__findnew_thread(&trace->host, sample->pid,
873                                          sample->tid);
874         ttrace = thread__trace(thread, trace->output);
875         if (ttrace == NULL)
876                 return -1;
877
878         ret = perf_evsel__intval(evsel, sample, "ret");
879
880         ttrace = thread->priv;
881
882         ttrace->exit_time = sample->time;
883
884         if (ttrace->entry_time) {
885                 duration = sample->time - ttrace->entry_time;
886                 if (trace__filter_duration(trace, duration))
887                         goto out;
888         } else if (trace->duration_filter)
889                 goto out;
890
891         trace__fprintf_entry_head(trace, thread, duration, sample->time, trace->output);
892
893         if (ttrace->entry_pending) {
894                 fprintf(trace->output, "%-70s", ttrace->entry_str);
895         } else {
896                 fprintf(trace->output, " ... [");
897                 color_fprintf(trace->output, PERF_COLOR_YELLOW, "continued");
898                 fprintf(trace->output, "]: %s()", sc->name);
899         }
900
901         if (sc->fmt == NULL) {
902 signed_print:
903                 fprintf(trace->output, ") = %d", ret);
904         } else if (ret < 0 && sc->fmt->errmsg) {
905                 char bf[256];
906                 const char *emsg = strerror_r(-ret, bf, sizeof(bf)),
907                            *e = audit_errno_to_name(-ret);
908
909                 fprintf(trace->output, ") = -1 %s %s", e, emsg);
910         } else if (ret == 0 && sc->fmt->timeout)
911                 fprintf(trace->output, ") = 0 Timeout");
912         else if (sc->fmt->hexret)
913                 fprintf(trace->output, ") = %#x", ret);
914         else
915                 goto signed_print;
916
917         fputc('\n', trace->output);
918 out:
919         ttrace->entry_pending = false;
920
921         return 0;
922 }
923
924 static int trace__sched_stat_runtime(struct trace *trace, struct perf_evsel *evsel,
925                                      struct perf_sample *sample)
926 {
927         u64 runtime = perf_evsel__intval(evsel, sample, "runtime");
928         double runtime_ms = (double)runtime / NSEC_PER_MSEC;
929         struct thread *thread = machine__findnew_thread(&trace->host,
930                                                         sample->pid,
931                                                         sample->tid);
932         struct thread_trace *ttrace = thread__trace(thread, trace->output);
933
934         if (ttrace == NULL)
935                 goto out_dump;
936
937         ttrace->runtime_ms += runtime_ms;
938         trace->runtime_ms += runtime_ms;
939         return 0;
940
941 out_dump:
942         fprintf(trace->output, "%s: comm=%s,pid=%u,runtime=%" PRIu64 ",vruntime=%" PRIu64 ")\n",
943                evsel->name,
944                perf_evsel__strval(evsel, sample, "comm"),
945                (pid_t)perf_evsel__intval(evsel, sample, "pid"),
946                runtime,
947                perf_evsel__intval(evsel, sample, "vruntime"));
948         return 0;
949 }
950
951 static bool skip_sample(struct trace *trace, struct perf_sample *sample)
952 {
953         if ((trace->pid_list && intlist__find(trace->pid_list, sample->pid)) ||
954             (trace->tid_list && intlist__find(trace->tid_list, sample->tid)))
955                 return false;
956
957         if (trace->pid_list || trace->tid_list)
958                 return true;
959
960         return false;
961 }
962
963 static int trace__process_sample(struct perf_tool *tool,
964                                  union perf_event *event __maybe_unused,
965                                  struct perf_sample *sample,
966                                  struct perf_evsel *evsel,
967                                  struct machine *machine __maybe_unused)
968 {
969         struct trace *trace = container_of(tool, struct trace, tool);
970         int err = 0;
971
972         tracepoint_handler handler = evsel->handler.func;
973
974         if (skip_sample(trace, sample))
975                 return 0;
976
977         if (trace->base_time == 0)
978                 trace->base_time = sample->time;
979
980         if (handler)
981                 handler(trace, evsel, sample);
982
983         return err;
984 }
985
986 static bool
987 perf_session__has_tp(struct perf_session *session, const char *name)
988 {
989         struct perf_evsel *evsel;
990
991         evsel = perf_evlist__find_tracepoint_by_name(session->evlist, name);
992
993         return evsel != NULL;
994 }
995
996 static int parse_target_str(struct trace *trace)
997 {
998         if (trace->opts.target.pid) {
999                 trace->pid_list = intlist__new(trace->opts.target.pid);
1000                 if (trace->pid_list == NULL) {
1001                         pr_err("Error parsing process id string\n");
1002                         return -EINVAL;
1003                 }
1004         }
1005
1006         if (trace->opts.target.tid) {
1007                 trace->tid_list = intlist__new(trace->opts.target.tid);
1008                 if (trace->tid_list == NULL) {
1009                         pr_err("Error parsing thread id string\n");
1010                         return -EINVAL;
1011                 }
1012         }
1013
1014         return 0;
1015 }
1016
1017 static int trace__run(struct trace *trace, int argc, const char **argv)
1018 {
1019         struct perf_evlist *evlist = perf_evlist__new();
1020         struct perf_evsel *evsel;
1021         int err = -1, i;
1022         unsigned long before;
1023         const bool forks = argc > 0;
1024
1025         if (evlist == NULL) {
1026                 fprintf(trace->output, "Not enough memory to run!\n");
1027                 goto out;
1028         }
1029
1030         if (perf_evlist__add_newtp(evlist, "raw_syscalls", "sys_enter", trace__sys_enter) ||
1031             perf_evlist__add_newtp(evlist, "raw_syscalls", "sys_exit", trace__sys_exit)) {
1032                 fprintf(trace->output, "Couldn't read the raw_syscalls tracepoints information!\n");
1033                 goto out_delete_evlist;
1034         }
1035
1036         if (trace->sched &&
1037             perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime",
1038                                    trace__sched_stat_runtime)) {
1039                 fprintf(trace->output, "Couldn't read the sched_stat_runtime tracepoint information!\n");
1040                 goto out_delete_evlist;
1041         }
1042
1043         err = perf_evlist__create_maps(evlist, &trace->opts.target);
1044         if (err < 0) {
1045                 fprintf(trace->output, "Problems parsing the target to trace, check your options!\n");
1046                 goto out_delete_evlist;
1047         }
1048
1049         err = trace__symbols_init(trace, evlist);
1050         if (err < 0) {
1051                 fprintf(trace->output, "Problems initializing symbol libraries!\n");
1052                 goto out_delete_maps;
1053         }
1054
1055         perf_evlist__config(evlist, &trace->opts);
1056
1057         signal(SIGCHLD, sig_handler);
1058         signal(SIGINT, sig_handler);
1059
1060         if (forks) {
1061                 err = perf_evlist__prepare_workload(evlist, &trace->opts.target,
1062                                                     argv, false, false);
1063                 if (err < 0) {
1064                         fprintf(trace->output, "Couldn't run the workload!\n");
1065                         goto out_delete_maps;
1066                 }
1067         }
1068
1069         err = perf_evlist__open(evlist);
1070         if (err < 0) {
1071                 fprintf(trace->output, "Couldn't create the events: %s\n", strerror(errno));
1072                 goto out_delete_maps;
1073         }
1074
1075         err = perf_evlist__mmap(evlist, UINT_MAX, false);
1076         if (err < 0) {
1077                 fprintf(trace->output, "Couldn't mmap the events: %s\n", strerror(errno));
1078                 goto out_close_evlist;
1079         }
1080
1081         perf_evlist__enable(evlist);
1082
1083         if (forks)
1084                 perf_evlist__start_workload(evlist);
1085
1086         trace->multiple_threads = evlist->threads->map[0] == -1 || evlist->threads->nr > 1;
1087 again:
1088         before = trace->nr_events;
1089
1090         for (i = 0; i < evlist->nr_mmaps; i++) {
1091                 union perf_event *event;
1092
1093                 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
1094                         const u32 type = event->header.type;
1095                         tracepoint_handler handler;
1096                         struct perf_sample sample;
1097
1098                         ++trace->nr_events;
1099
1100                         err = perf_evlist__parse_sample(evlist, event, &sample);
1101                         if (err) {
1102                                 fprintf(trace->output, "Can't parse sample, err = %d, skipping...\n", err);
1103                                 continue;
1104                         }
1105
1106                         if (trace->base_time == 0)
1107                                 trace->base_time = sample.time;
1108
1109                         if (type != PERF_RECORD_SAMPLE) {
1110                                 trace__process_event(trace, &trace->host, event);
1111                                 continue;
1112                         }
1113
1114                         evsel = perf_evlist__id2evsel(evlist, sample.id);
1115                         if (evsel == NULL) {
1116                                 fprintf(trace->output, "Unknown tp ID %" PRIu64 ", skipping...\n", sample.id);
1117                                 continue;
1118                         }
1119
1120                         if (sample.raw_data == NULL) {
1121                                 fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n",
1122                                        perf_evsel__name(evsel), sample.tid,
1123                                        sample.cpu, sample.raw_size);
1124                                 continue;
1125                         }
1126
1127                         handler = evsel->handler.func;
1128                         handler(trace, evsel, &sample);
1129
1130                         if (done)
1131                                 goto out_unmap_evlist;
1132                 }
1133         }
1134
1135         if (trace->nr_events == before) {
1136                 if (done)
1137                         goto out_unmap_evlist;
1138
1139                 poll(evlist->pollfd, evlist->nr_fds, -1);
1140         }
1141
1142         if (done)
1143                 perf_evlist__disable(evlist);
1144
1145         goto again;
1146
1147 out_unmap_evlist:
1148         perf_evlist__munmap(evlist);
1149 out_close_evlist:
1150         perf_evlist__close(evlist);
1151 out_delete_maps:
1152         perf_evlist__delete_maps(evlist);
1153 out_delete_evlist:
1154         perf_evlist__delete(evlist);
1155 out:
1156         return err;
1157 }
1158
1159 static int trace__replay(struct trace *trace)
1160 {
1161         const struct perf_evsel_str_handler handlers[] = {
1162                 { "raw_syscalls:sys_enter",  trace__sys_enter, },
1163                 { "raw_syscalls:sys_exit",   trace__sys_exit, },
1164         };
1165
1166         struct perf_session *session;
1167         int err = -1;
1168
1169         trace->tool.sample        = trace__process_sample;
1170         trace->tool.mmap          = perf_event__process_mmap;
1171         trace->tool.mmap2         = perf_event__process_mmap2;
1172         trace->tool.comm          = perf_event__process_comm;
1173         trace->tool.exit          = perf_event__process_exit;
1174         trace->tool.fork          = perf_event__process_fork;
1175         trace->tool.attr          = perf_event__process_attr;
1176         trace->tool.tracing_data = perf_event__process_tracing_data;
1177         trace->tool.build_id      = perf_event__process_build_id;
1178
1179         trace->tool.ordered_samples = true;
1180         trace->tool.ordering_requires_timestamps = true;
1181
1182         /* add tid to output */
1183         trace->multiple_threads = true;
1184
1185         if (symbol__init() < 0)
1186                 return -1;
1187
1188         session = perf_session__new(input_name, O_RDONLY, 0, false,
1189                                     &trace->tool);
1190         if (session == NULL)
1191                 return -ENOMEM;
1192
1193         err = perf_session__set_tracepoints_handlers(session, handlers);
1194         if (err)
1195                 goto out;
1196
1197         if (!perf_session__has_tp(session, "raw_syscalls:sys_enter")) {
1198                 pr_err("Data file does not have raw_syscalls:sys_enter events\n");
1199                 goto out;
1200         }
1201
1202         if (!perf_session__has_tp(session, "raw_syscalls:sys_exit")) {
1203                 pr_err("Data file does not have raw_syscalls:sys_exit events\n");
1204                 goto out;
1205         }
1206
1207         err = parse_target_str(trace);
1208         if (err != 0)
1209                 goto out;
1210
1211         setup_pager();
1212
1213         err = perf_session__process_events(session, &trace->tool);
1214         if (err)
1215                 pr_err("Failed to process events, error %d", err);
1216
1217 out:
1218         perf_session__delete(session);
1219
1220         return err;
1221 }
1222
1223 static size_t trace__fprintf_threads_header(FILE *fp)
1224 {
1225         size_t printed;
1226
1227         printed  = fprintf(fp, "\n _____________________________________________________________________\n");
1228         printed += fprintf(fp," __)    Summary of events    (__\n\n");
1229         printed += fprintf(fp,"              [ task - pid ]     [ events ] [ ratio ]  [ runtime ]\n");
1230         printed += fprintf(fp," _____________________________________________________________________\n\n");
1231
1232         return printed;
1233 }
1234
1235 static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp)
1236 {
1237         size_t printed = trace__fprintf_threads_header(fp);
1238         struct rb_node *nd;
1239
1240         for (nd = rb_first(&trace->host.threads); nd; nd = rb_next(nd)) {
1241                 struct thread *thread = rb_entry(nd, struct thread, rb_node);
1242                 struct thread_trace *ttrace = thread->priv;
1243                 const char *color;
1244                 double ratio;
1245
1246                 if (ttrace == NULL)
1247                         continue;
1248
1249                 ratio = (double)ttrace->nr_events / trace->nr_events * 100.0;
1250
1251                 color = PERF_COLOR_NORMAL;
1252                 if (ratio > 50.0)
1253                         color = PERF_COLOR_RED;
1254                 else if (ratio > 25.0)
1255                         color = PERF_COLOR_GREEN;
1256                 else if (ratio > 5.0)
1257                         color = PERF_COLOR_YELLOW;
1258
1259                 printed += color_fprintf(fp, color, "%20s", thread->comm);
1260                 printed += fprintf(fp, " - %-5d :%11lu   [", thread->tid, ttrace->nr_events);
1261                 printed += color_fprintf(fp, color, "%5.1f%%", ratio);
1262                 printed += fprintf(fp, " ] %10.3f ms\n", ttrace->runtime_ms);
1263         }
1264
1265         return printed;
1266 }
1267
1268 static int trace__set_duration(const struct option *opt, const char *str,
1269                                int unset __maybe_unused)
1270 {
1271         struct trace *trace = opt->value;
1272
1273         trace->duration_filter = atof(str);
1274         return 0;
1275 }
1276
1277 static int trace__open_output(struct trace *trace, const char *filename)
1278 {
1279         struct stat st;
1280
1281         if (!stat(filename, &st) && st.st_size) {
1282                 char oldname[PATH_MAX];
1283
1284                 scnprintf(oldname, sizeof(oldname), "%s.old", filename);
1285                 unlink(oldname);
1286                 rename(filename, oldname);
1287         }
1288
1289         trace->output = fopen(filename, "w");
1290
1291         return trace->output == NULL ? -errno : 0;
1292 }
1293
1294 int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
1295 {
1296         const char * const trace_usage[] = {
1297                 "perf trace [<options>] [<command>]",
1298                 "perf trace [<options>] -- <command> [<options>]",
1299                 NULL
1300         };
1301         struct trace trace = {
1302                 .audit_machine = audit_detect_machine(),
1303                 .syscalls = {
1304                         . max = -1,
1305                 },
1306                 .opts = {
1307                         .target = {
1308                                 .uid       = UINT_MAX,
1309                                 .uses_mmap = true,
1310                         },
1311                         .user_freq     = UINT_MAX,
1312                         .user_interval = ULLONG_MAX,
1313                         .no_delay      = true,
1314                         .mmap_pages    = 1024,
1315                 },
1316                 .output = stdout,
1317         };
1318         const char *output_name = NULL;
1319         const char *ev_qualifier_str = NULL;
1320         const struct option trace_options[] = {
1321         OPT_STRING('e', "expr", &ev_qualifier_str, "expr",
1322                     "list of events to trace"),
1323         OPT_STRING('o', "output", &output_name, "file", "output file name"),
1324         OPT_STRING('i', "input", &input_name, "file", "Analyze events in file"),
1325         OPT_STRING('p', "pid", &trace.opts.target.pid, "pid",
1326                     "trace events on existing process id"),
1327         OPT_STRING('t', "tid", &trace.opts.target.tid, "tid",
1328                     "trace events on existing thread id"),
1329         OPT_BOOLEAN('a', "all-cpus", &trace.opts.target.system_wide,
1330                     "system-wide collection from all CPUs"),
1331         OPT_STRING('C', "cpu", &trace.opts.target.cpu_list, "cpu",
1332                     "list of cpus to monitor"),
1333         OPT_BOOLEAN(0, "no-inherit", &trace.opts.no_inherit,
1334                     "child tasks do not inherit counters"),
1335         OPT_UINTEGER('m', "mmap-pages", &trace.opts.mmap_pages,
1336                      "number of mmap data pages"),
1337         OPT_STRING('u', "uid", &trace.opts.target.uid_str, "user",
1338                    "user to profile"),
1339         OPT_CALLBACK(0, "duration", &trace, "float",
1340                      "show only events with duration > N.M ms",
1341                      trace__set_duration),
1342         OPT_BOOLEAN(0, "sched", &trace.sched, "show blocking scheduler events"),
1343         OPT_INCR('v', "verbose", &verbose, "be more verbose"),
1344         OPT_END()
1345         };
1346         int err;
1347         char bf[BUFSIZ];
1348
1349         argc = parse_options(argc, argv, trace_options, trace_usage, 0);
1350
1351         if (output_name != NULL) {
1352                 err = trace__open_output(&trace, output_name);
1353                 if (err < 0) {
1354                         perror("failed to create output file");
1355                         goto out;
1356                 }
1357         }
1358
1359         if (ev_qualifier_str != NULL) {
1360                 const char *s = ev_qualifier_str;
1361
1362                 trace.not_ev_qualifier = *s == '!';
1363                 if (trace.not_ev_qualifier)
1364                         ++s;
1365                 trace.ev_qualifier = strlist__new(true, s);
1366                 if (trace.ev_qualifier == NULL) {
1367                         fputs("Not enough memory to parse event qualifier",
1368                               trace.output);
1369                         err = -ENOMEM;
1370                         goto out_close;
1371                 }
1372         }
1373
1374         err = perf_target__validate(&trace.opts.target);
1375         if (err) {
1376                 perf_target__strerror(&trace.opts.target, err, bf, sizeof(bf));
1377                 fprintf(trace.output, "%s", bf);
1378                 goto out_close;
1379         }
1380
1381         err = perf_target__parse_uid(&trace.opts.target);
1382         if (err) {
1383                 perf_target__strerror(&trace.opts.target, err, bf, sizeof(bf));
1384                 fprintf(trace.output, "%s", bf);
1385                 goto out_close;
1386         }
1387
1388         if (!argc && perf_target__none(&trace.opts.target))
1389                 trace.opts.target.system_wide = true;
1390
1391         if (input_name)
1392                 err = trace__replay(&trace);
1393         else
1394                 err = trace__run(&trace, argc, argv);
1395
1396         if (trace.sched && !err)
1397                 trace__fprintf_thread_summary(&trace, trace.output);
1398
1399 out_close:
1400         if (output_name != NULL)
1401                 fclose(trace.output);
1402 out:
1403         return err;
1404 }