blob: 39a947a0d1229edc7d4b23c7252afedd8a5cc4f9 [file] [log] [blame]
Robert Richter4e319022013-06-11 17:29:18 +02001#include <traceevent/event-parse.h>
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002#include "builtin.h"
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03003#include "util/color.h"
Arnaldo Carvalho de Melo7c304ee02013-08-22 16:49:54 -03004#include "util/debug.h"
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03005#include "util/evlist.h"
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03006#include "util/machine.h"
David Ahern6810fc92013-08-28 22:29:52 -06007#include "util/session.h"
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03008#include "util/thread.h"
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03009#include "util/parse-options.h"
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -030010#include "util/strlist.h"
David Ahernbdc89662013-08-28 22:29:53 -060011#include "util/intlist.h"
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -030012#include "util/thread_map.h"
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -030013
14#include <libaudit.h>
15#include <stdlib.h>
Arnaldo Carvalho de Melo49af9e92013-09-12 12:18:56 -030016#include <sys/eventfd.h>
Arnaldo Carvalho de Meloae685382013-08-20 17:44:42 -030017#include <sys/mman.h>
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -030018#include <linux/futex.h>
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -030019
Ingo Molnar456857b2013-09-12 15:29:00 +020020/* For older distros: */
21#ifndef MAP_STACK
22# define MAP_STACK 0x20000
23#endif
24
25#ifndef MADV_HWPOISON
26# define MADV_HWPOISON 100
27#endif
28
29#ifndef MADV_MERGEABLE
30# define MADV_MERGEABLE 12
31#endif
32
33#ifndef MADV_UNMERGEABLE
34# define MADV_UNMERGEABLE 13
35#endif
36
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -030037struct syscall_arg {
38 unsigned long val;
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -030039 void *parm;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -030040 u8 idx;
41 u8 mask;
42};
43
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -030044struct strarray {
45 int nr_entries;
46 const char **entries;
47};
48
49#define DEFINE_STRARRAY(array) struct strarray strarray__##array = { \
50 .nr_entries = ARRAY_SIZE(array), \
51 .entries = array, \
52}
53
54static size_t syscall_arg__scnprintf_strarray(char *bf, size_t size,
55 struct syscall_arg *arg)
56{
57 int idx = arg->val;
58 struct strarray *sa = arg->parm;
59
60 if (idx < 0 || idx >= sa->nr_entries)
61 return scnprintf(bf, size, "%d", idx);
62
63 return scnprintf(bf, size, "%s", sa->entries[idx]);
64}
65
66#define SCA_STRARRAY syscall_arg__scnprintf_strarray
67
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -030068static size_t syscall_arg__scnprintf_hex(char *bf, size_t size,
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -030069 struct syscall_arg *arg)
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -030070{
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -030071 return scnprintf(bf, size, "%#lx", arg->val);
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -030072}
73
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -030074#define SCA_HEX syscall_arg__scnprintf_hex
75
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -030076static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size,
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -030077 struct syscall_arg *arg)
Arnaldo Carvalho de Meloae685382013-08-20 17:44:42 -030078{
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -030079 int printed = 0, prot = arg->val;
Arnaldo Carvalho de Meloae685382013-08-20 17:44:42 -030080
81 if (prot == PROT_NONE)
82 return scnprintf(bf, size, "NONE");
83#define P_MMAP_PROT(n) \
84 if (prot & PROT_##n) { \
85 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
86 prot &= ~PROT_##n; \
87 }
88
89 P_MMAP_PROT(EXEC);
90 P_MMAP_PROT(READ);
91 P_MMAP_PROT(WRITE);
92#ifdef PROT_SEM
93 P_MMAP_PROT(SEM);
94#endif
95 P_MMAP_PROT(GROWSDOWN);
96 P_MMAP_PROT(GROWSUP);
97#undef P_MMAP_PROT
98
99 if (prot)
100 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", prot);
101
102 return printed;
103}
104
105#define SCA_MMAP_PROT syscall_arg__scnprintf_mmap_prot
106
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -0300107static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size,
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300108 struct syscall_arg *arg)
Arnaldo Carvalho de Melo941557e2013-08-23 10:48:33 -0300109{
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300110 int printed = 0, flags = arg->val;
Arnaldo Carvalho de Melo941557e2013-08-23 10:48:33 -0300111
112#define P_MMAP_FLAG(n) \
113 if (flags & MAP_##n) { \
114 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
115 flags &= ~MAP_##n; \
116 }
117
118 P_MMAP_FLAG(SHARED);
119 P_MMAP_FLAG(PRIVATE);
Kyle McMartin41817812013-09-05 10:29:47 -0400120#ifdef MAP_32BIT
Arnaldo Carvalho de Melo941557e2013-08-23 10:48:33 -0300121 P_MMAP_FLAG(32BIT);
Kyle McMartin41817812013-09-05 10:29:47 -0400122#endif
Arnaldo Carvalho de Melo941557e2013-08-23 10:48:33 -0300123 P_MMAP_FLAG(ANONYMOUS);
124 P_MMAP_FLAG(DENYWRITE);
125 P_MMAP_FLAG(EXECUTABLE);
126 P_MMAP_FLAG(FILE);
127 P_MMAP_FLAG(FIXED);
128 P_MMAP_FLAG(GROWSDOWN);
David Ahernf2935f32013-08-27 10:50:40 -0600129#ifdef MAP_HUGETLB
Arnaldo Carvalho de Melo941557e2013-08-23 10:48:33 -0300130 P_MMAP_FLAG(HUGETLB);
David Ahernf2935f32013-08-27 10:50:40 -0600131#endif
Arnaldo Carvalho de Melo941557e2013-08-23 10:48:33 -0300132 P_MMAP_FLAG(LOCKED);
133 P_MMAP_FLAG(NONBLOCK);
134 P_MMAP_FLAG(NORESERVE);
135 P_MMAP_FLAG(POPULATE);
136 P_MMAP_FLAG(STACK);
137#ifdef MAP_UNINITIALIZED
138 P_MMAP_FLAG(UNINITIALIZED);
139#endif
140#undef P_MMAP_FLAG
141
142 if (flags)
143 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
144
145 return printed;
146}
147
148#define SCA_MMAP_FLAGS syscall_arg__scnprintf_mmap_flags
149
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -0300150static size_t syscall_arg__scnprintf_madvise_behavior(char *bf, size_t size,
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300151 struct syscall_arg *arg)
Arnaldo Carvalho de Melo9e9716d2013-08-23 10:06:41 -0300152{
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300153 int behavior = arg->val;
Arnaldo Carvalho de Melo9e9716d2013-08-23 10:06:41 -0300154
155 switch (behavior) {
156#define P_MADV_BHV(n) case MADV_##n: return scnprintf(bf, size, #n)
157 P_MADV_BHV(NORMAL);
158 P_MADV_BHV(RANDOM);
159 P_MADV_BHV(SEQUENTIAL);
160 P_MADV_BHV(WILLNEED);
161 P_MADV_BHV(DONTNEED);
162 P_MADV_BHV(REMOVE);
163 P_MADV_BHV(DONTFORK);
164 P_MADV_BHV(DOFORK);
165 P_MADV_BHV(HWPOISON);
166#ifdef MADV_SOFT_OFFLINE
167 P_MADV_BHV(SOFT_OFFLINE);
168#endif
169 P_MADV_BHV(MERGEABLE);
170 P_MADV_BHV(UNMERGEABLE);
David Ahernf2935f32013-08-27 10:50:40 -0600171#ifdef MADV_HUGEPAGE
Arnaldo Carvalho de Melo9e9716d2013-08-23 10:06:41 -0300172 P_MADV_BHV(HUGEPAGE);
David Ahernf2935f32013-08-27 10:50:40 -0600173#endif
174#ifdef MADV_NOHUGEPAGE
Arnaldo Carvalho de Melo9e9716d2013-08-23 10:06:41 -0300175 P_MADV_BHV(NOHUGEPAGE);
David Ahernf2935f32013-08-27 10:50:40 -0600176#endif
Arnaldo Carvalho de Melo9e9716d2013-08-23 10:06:41 -0300177#ifdef MADV_DONTDUMP
178 P_MADV_BHV(DONTDUMP);
179#endif
180#ifdef MADV_DODUMP
181 P_MADV_BHV(DODUMP);
182#endif
183#undef P_MADV_PHV
184 default: break;
185 }
186
187 return scnprintf(bf, size, "%#x", behavior);
188}
189
190#define SCA_MADV_BHV syscall_arg__scnprintf_madvise_behavior
191
Arnaldo Carvalho de Melo5cea6ff2013-09-20 11:49:50 -0300192static size_t syscall_arg__scnprintf_flock(char *bf, size_t size,
193 struct syscall_arg *arg)
194{
195 int printed = 0, op = arg->val;
196
197 if (op == 0)
198 return scnprintf(bf, size, "NONE");
199#define P_CMD(cmd) \
200 if ((op & LOCK_##cmd) == LOCK_##cmd) { \
201 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #cmd); \
202 op &= ~LOCK_##cmd; \
203 }
204
205 P_CMD(SH);
206 P_CMD(EX);
207 P_CMD(NB);
208 P_CMD(UN);
209 P_CMD(MAND);
210 P_CMD(RW);
211 P_CMD(READ);
212 P_CMD(WRITE);
213#undef P_OP
214
215 if (op)
216 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", op);
217
218 return printed;
219}
220
221#define SCA_FLOCK syscall_arg__scnprintf_flock
222
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300223static size_t syscall_arg__scnprintf_futex_op(char *bf, size_t size, struct syscall_arg *arg)
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -0300224{
225 enum syscall_futex_args {
226 SCF_UADDR = (1 << 0),
227 SCF_OP = (1 << 1),
228 SCF_VAL = (1 << 2),
229 SCF_TIMEOUT = (1 << 3),
230 SCF_UADDR2 = (1 << 4),
231 SCF_VAL3 = (1 << 5),
232 };
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300233 int op = arg->val;
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -0300234 int cmd = op & FUTEX_CMD_MASK;
235 size_t printed = 0;
236
237 switch (cmd) {
238#define P_FUTEX_OP(n) case FUTEX_##n: printed = scnprintf(bf, size, #n);
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300239 P_FUTEX_OP(WAIT); arg->mask |= SCF_VAL3|SCF_UADDR2; break;
240 P_FUTEX_OP(WAKE); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
241 P_FUTEX_OP(FD); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
242 P_FUTEX_OP(REQUEUE); arg->mask |= SCF_VAL3|SCF_TIMEOUT; break;
243 P_FUTEX_OP(CMP_REQUEUE); arg->mask |= SCF_TIMEOUT; break;
244 P_FUTEX_OP(CMP_REQUEUE_PI); arg->mask |= SCF_TIMEOUT; break;
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -0300245 P_FUTEX_OP(WAKE_OP); break;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300246 P_FUTEX_OP(LOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
247 P_FUTEX_OP(UNLOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
248 P_FUTEX_OP(TRYLOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2; break;
249 P_FUTEX_OP(WAIT_BITSET); arg->mask |= SCF_UADDR2; break;
250 P_FUTEX_OP(WAKE_BITSET); arg->mask |= SCF_UADDR2; break;
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -0300251 P_FUTEX_OP(WAIT_REQUEUE_PI); break;
252 default: printed = scnprintf(bf, size, "%#x", cmd); break;
253 }
254
255 if (op & FUTEX_PRIVATE_FLAG)
256 printed += scnprintf(bf + printed, size - printed, "|PRIV");
257
258 if (op & FUTEX_CLOCK_REALTIME)
259 printed += scnprintf(bf + printed, size - printed, "|CLKRT");
260
261 return printed;
262}
263
Arnaldo Carvalho de Meloefe6b882013-09-03 16:15:12 -0300264#define SCA_FUTEX_OP syscall_arg__scnprintf_futex_op
265
Arnaldo Carvalho de Meloeac032c2013-09-20 11:27:32 -0300266static const char *epoll_ctl_ops[] = { [1] = "ADD", "DEL", "MOD", };
267static DEFINE_STRARRAY(epoll_ctl_ops);
268
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300269static const char *itimers[] = { "REAL", "VIRTUAL", "PROF", };
270static DEFINE_STRARRAY(itimers);
271
Arnaldo Carvalho de Meloefe6b882013-09-03 16:15:12 -0300272static const char *whences[] = { "SET", "CUR", "END",
273#ifdef SEEK_DATA
274"DATA",
275#endif
276#ifdef SEEK_HOLE
277"HOLE",
278#endif
279};
280static DEFINE_STRARRAY(whences);
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -0300281
Arnaldo Carvalho de Melo80f587d2013-09-03 16:28:58 -0300282static const char *fcntl_cmds[] = {
283 "DUPFD", "GETFD", "SETFD", "GETFL", "SETFL", "GETLK", "SETLK",
284 "SETLKW", "SETOWN", "GETOWN", "SETSIG", "GETSIG", "F_GETLK64",
285 "F_SETLK64", "F_SETLKW64", "F_SETOWN_EX", "F_GETOWN_EX",
286 "F_GETOWNER_UIDS",
287};
288static DEFINE_STRARRAY(fcntl_cmds);
289
Arnaldo Carvalho de Meloc045bf02013-09-04 11:52:33 -0300290static const char *rlimit_resources[] = {
291 "CPU", "FSIZE", "DATA", "STACK", "CORE", "RSS", "NPROC", "NOFILE",
292 "MEMLOCK", "AS", "LOCKS", "SIGPENDING", "MSGQUEUE", "NICE", "RTPRIO",
293 "RTTIME",
294};
295static DEFINE_STRARRAY(rlimit_resources);
296
Arnaldo Carvalho de Meloeb5b1b12013-09-03 16:37:46 -0300297static const char *sighow[] = { "BLOCK", "UNBLOCK", "SETMASK", };
298static DEFINE_STRARRAY(sighow);
299
David Ahern4f8c1b72013-09-22 19:45:00 -0600300static const char *clockid[] = {
301 "REALTIME", "MONOTONIC", "PROCESS_CPUTIME_ID", "THREAD_CPUTIME_ID",
302 "MONOTONIC_RAW", "REALTIME_COARSE", "MONOTONIC_COARSE",
303};
304static DEFINE_STRARRAY(clockid);
305
Arnaldo Carvalho de Meloe10bce82013-09-04 10:27:41 -0300306static const char *socket_families[] = {
307 "UNSPEC", "LOCAL", "INET", "AX25", "IPX", "APPLETALK", "NETROM",
308 "BRIDGE", "ATMPVC", "X25", "INET6", "ROSE", "DECnet", "NETBEUI",
309 "SECURITY", "KEY", "NETLINK", "PACKET", "ASH", "ECONET", "ATMSVC",
310 "RDS", "SNA", "IRDA", "PPPOX", "WANPIPE", "LLC", "IB", "CAN", "TIPC",
311 "BLUETOOTH", "IUCV", "RXRPC", "ISDN", "PHONET", "IEEE802154", "CAIF",
312 "ALG", "NFC", "VSOCK",
313};
314static DEFINE_STRARRAY(socket_families);
315
Arnaldo Carvalho de Meloa28b24b2013-09-04 11:00:44 -0300316#ifndef SOCK_TYPE_MASK
317#define SOCK_TYPE_MASK 0xf
318#endif
319
320static size_t syscall_arg__scnprintf_socket_type(char *bf, size_t size,
321 struct syscall_arg *arg)
322{
323 size_t printed;
324 int type = arg->val,
325 flags = type & ~SOCK_TYPE_MASK;
326
327 type &= SOCK_TYPE_MASK;
328 /*
329 * Can't use a strarray, MIPS may override for ABI reasons.
330 */
331 switch (type) {
332#define P_SK_TYPE(n) case SOCK_##n: printed = scnprintf(bf, size, #n); break;
333 P_SK_TYPE(STREAM);
334 P_SK_TYPE(DGRAM);
335 P_SK_TYPE(RAW);
336 P_SK_TYPE(RDM);
337 P_SK_TYPE(SEQPACKET);
338 P_SK_TYPE(DCCP);
339 P_SK_TYPE(PACKET);
340#undef P_SK_TYPE
341 default:
342 printed = scnprintf(bf, size, "%#x", type);
343 }
344
345#define P_SK_FLAG(n) \
346 if (flags & SOCK_##n) { \
347 printed += scnprintf(bf + printed, size - printed, "|%s", #n); \
348 flags &= ~SOCK_##n; \
349 }
350
351 P_SK_FLAG(CLOEXEC);
352 P_SK_FLAG(NONBLOCK);
353#undef P_SK_FLAG
354
355 if (flags)
356 printed += scnprintf(bf + printed, size - printed, "|%#x", flags);
357
358 return printed;
359}
360
361#define SCA_SK_TYPE syscall_arg__scnprintf_socket_type
362
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -0300363#ifndef MSG_PROBE
364#define MSG_PROBE 0x10
365#endif
366#ifndef MSG_SENDPAGE_NOTLAST
367#define MSG_SENDPAGE_NOTLAST 0x20000
368#endif
369#ifndef MSG_FASTOPEN
370#define MSG_FASTOPEN 0x20000000
371#endif
372
373static size_t syscall_arg__scnprintf_msg_flags(char *bf, size_t size,
374 struct syscall_arg *arg)
375{
376 int printed = 0, flags = arg->val;
377
378 if (flags == 0)
379 return scnprintf(bf, size, "NONE");
380#define P_MSG_FLAG(n) \
381 if (flags & MSG_##n) { \
382 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
383 flags &= ~MSG_##n; \
384 }
385
386 P_MSG_FLAG(OOB);
387 P_MSG_FLAG(PEEK);
388 P_MSG_FLAG(DONTROUTE);
389 P_MSG_FLAG(TRYHARD);
390 P_MSG_FLAG(CTRUNC);
391 P_MSG_FLAG(PROBE);
392 P_MSG_FLAG(TRUNC);
393 P_MSG_FLAG(DONTWAIT);
394 P_MSG_FLAG(EOR);
395 P_MSG_FLAG(WAITALL);
396 P_MSG_FLAG(FIN);
397 P_MSG_FLAG(SYN);
398 P_MSG_FLAG(CONFIRM);
399 P_MSG_FLAG(RST);
400 P_MSG_FLAG(ERRQUEUE);
401 P_MSG_FLAG(NOSIGNAL);
402 P_MSG_FLAG(MORE);
403 P_MSG_FLAG(WAITFORONE);
404 P_MSG_FLAG(SENDPAGE_NOTLAST);
405 P_MSG_FLAG(FASTOPEN);
406 P_MSG_FLAG(CMSG_CLOEXEC);
407#undef P_MSG_FLAG
408
409 if (flags)
410 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
411
412 return printed;
413}
414
415#define SCA_MSG_FLAGS syscall_arg__scnprintf_msg_flags
416
Arnaldo Carvalho de Melo51108992013-09-04 11:42:27 -0300417static size_t syscall_arg__scnprintf_access_mode(char *bf, size_t size,
418 struct syscall_arg *arg)
419{
420 size_t printed = 0;
421 int mode = arg->val;
422
423 if (mode == F_OK) /* 0 */
424 return scnprintf(bf, size, "F");
425#define P_MODE(n) \
426 if (mode & n##_OK) { \
427 printed += scnprintf(bf + printed, size - printed, "%s", #n); \
428 mode &= ~n##_OK; \
429 }
430
431 P_MODE(R);
432 P_MODE(W);
433 P_MODE(X);
434#undef P_MODE
435
436 if (mode)
437 printed += scnprintf(bf + printed, size - printed, "|%#x", mode);
438
439 return printed;
440}
441
442#define SCA_ACCMODE syscall_arg__scnprintf_access_mode
443
Arnaldo Carvalho de Melobe65a892013-09-02 16:22:31 -0300444static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300445 struct syscall_arg *arg)
Arnaldo Carvalho de Melobe65a892013-09-02 16:22:31 -0300446{
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300447 int printed = 0, flags = arg->val;
Arnaldo Carvalho de Melobe65a892013-09-02 16:22:31 -0300448
449 if (!(flags & O_CREAT))
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300450 arg->mask |= 1 << (arg->idx + 1); /* Mask the mode parm */
Arnaldo Carvalho de Melobe65a892013-09-02 16:22:31 -0300451
452 if (flags == 0)
453 return scnprintf(bf, size, "RDONLY");
454#define P_FLAG(n) \
455 if (flags & O_##n) { \
456 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
457 flags &= ~O_##n; \
458 }
459
460 P_FLAG(APPEND);
461 P_FLAG(ASYNC);
462 P_FLAG(CLOEXEC);
463 P_FLAG(CREAT);
464 P_FLAG(DIRECT);
465 P_FLAG(DIRECTORY);
466 P_FLAG(EXCL);
467 P_FLAG(LARGEFILE);
468 P_FLAG(NOATIME);
469 P_FLAG(NOCTTY);
470#ifdef O_NONBLOCK
471 P_FLAG(NONBLOCK);
472#elif O_NDELAY
473 P_FLAG(NDELAY);
474#endif
475#ifdef O_PATH
476 P_FLAG(PATH);
477#endif
478 P_FLAG(RDWR);
479#ifdef O_DSYNC
480 if ((flags & O_SYNC) == O_SYNC)
481 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", "SYNC");
482 else {
483 P_FLAG(DSYNC);
484 }
485#else
486 P_FLAG(SYNC);
487#endif
488 P_FLAG(TRUNC);
489 P_FLAG(WRONLY);
490#undef P_FLAG
491
492 if (flags)
493 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
494
495 return printed;
496}
497
498#define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags
499
Arnaldo Carvalho de Melo49af9e92013-09-12 12:18:56 -0300500static size_t syscall_arg__scnprintf_eventfd_flags(char *bf, size_t size,
501 struct syscall_arg *arg)
502{
503 int printed = 0, flags = arg->val;
504
505 if (flags == 0)
506 return scnprintf(bf, size, "NONE");
507#define P_FLAG(n) \
508 if (flags & EFD_##n) { \
509 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
510 flags &= ~EFD_##n; \
511 }
512
513 P_FLAG(SEMAPHORE);
514 P_FLAG(CLOEXEC);
515 P_FLAG(NONBLOCK);
516#undef P_FLAG
517
518 if (flags)
519 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
520
521 return printed;
522}
523
524#define SCA_EFD_FLAGS syscall_arg__scnprintf_eventfd_flags
525
Arnaldo Carvalho de Melo46cce192013-09-23 12:52:04 -0300526static size_t syscall_arg__scnprintf_pipe_flags(char *bf, size_t size,
527 struct syscall_arg *arg)
528{
529 int printed = 0, flags = arg->val;
530
531#define P_FLAG(n) \
532 if (flags & O_##n) { \
533 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
534 flags &= ~O_##n; \
535 }
536
537 P_FLAG(CLOEXEC);
538 P_FLAG(NONBLOCK);
539#undef P_FLAG
540
541 if (flags)
542 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
543
544 return printed;
545}
546
547#define SCA_PIPE_FLAGS syscall_arg__scnprintf_pipe_flags
548
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -0300549static size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscall_arg *arg)
550{
551 int sig = arg->val;
552
553 switch (sig) {
554#define P_SIGNUM(n) case SIG##n: return scnprintf(bf, size, #n)
555 P_SIGNUM(HUP);
556 P_SIGNUM(INT);
557 P_SIGNUM(QUIT);
558 P_SIGNUM(ILL);
559 P_SIGNUM(TRAP);
560 P_SIGNUM(ABRT);
561 P_SIGNUM(BUS);
562 P_SIGNUM(FPE);
563 P_SIGNUM(KILL);
564 P_SIGNUM(USR1);
565 P_SIGNUM(SEGV);
566 P_SIGNUM(USR2);
567 P_SIGNUM(PIPE);
568 P_SIGNUM(ALRM);
569 P_SIGNUM(TERM);
570 P_SIGNUM(STKFLT);
571 P_SIGNUM(CHLD);
572 P_SIGNUM(CONT);
573 P_SIGNUM(STOP);
574 P_SIGNUM(TSTP);
575 P_SIGNUM(TTIN);
576 P_SIGNUM(TTOU);
577 P_SIGNUM(URG);
578 P_SIGNUM(XCPU);
579 P_SIGNUM(XFSZ);
580 P_SIGNUM(VTALRM);
581 P_SIGNUM(PROF);
582 P_SIGNUM(WINCH);
583 P_SIGNUM(IO);
584 P_SIGNUM(PWR);
585 P_SIGNUM(SYS);
586 default: break;
587 }
588
589 return scnprintf(bf, size, "%#x", sig);
590}
591
592#define SCA_SIGNUM syscall_arg__scnprintf_signum
593
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300594#define STRARRAY(arg, name, array) \
595 .arg_scnprintf = { [arg] = SCA_STRARRAY, }, \
596 .arg_parm = { [arg] = &strarray__##array, }
597
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300598static struct syscall_fmt {
599 const char *name;
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -0300600 const char *alias;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300601 size_t (*arg_scnprintf[6])(char *bf, size_t size, struct syscall_arg *arg);
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300602 void *arg_parm[6];
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300603 bool errmsg;
604 bool timeout;
Arnaldo Carvalho de Melo04b34722013-08-26 11:36:30 -0300605 bool hexret;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300606} syscall_fmts[] = {
Arnaldo Carvalho de Melo51108992013-09-04 11:42:27 -0300607 { .name = "access", .errmsg = true,
608 .arg_scnprintf = { [1] = SCA_ACCMODE, /* mode */ }, },
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -0300609 { .name = "arch_prctl", .errmsg = true, .alias = "prctl", },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -0300610 { .name = "brk", .hexret = true,
611 .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, },
David Ahern4f8c1b72013-09-22 19:45:00 -0600612 { .name = "clock_gettime", .errmsg = true, STRARRAY(0, clk_id, clockid), },
Arnaldo Carvalho de Meloa14bb862013-07-30 16:38:23 -0300613 { .name = "connect", .errmsg = true, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300614 { .name = "epoll_ctl", .errmsg = true, STRARRAY(1, op, epoll_ctl_ops), },
Arnaldo Carvalho de Melo49af9e92013-09-12 12:18:56 -0300615 { .name = "eventfd2", .errmsg = true,
616 .arg_scnprintf = { [1] = SCA_EFD_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300617 { .name = "fcntl", .errmsg = true, STRARRAY(1, cmd, fcntl_cmds), },
Arnaldo Carvalho de Melo5cea6ff2013-09-20 11:49:50 -0300618 { .name = "flock", .errmsg = true,
619 .arg_scnprintf = { [1] = SCA_FLOCK, /* cmd */ }, },
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -0300620 { .name = "fstat", .errmsg = true, .alias = "newfstat", },
621 { .name = "fstatat", .errmsg = true, .alias = "newfstatat", },
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -0300622 { .name = "futex", .errmsg = true,
623 .arg_scnprintf = { [1] = SCA_FUTEX_OP, /* op */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300624 { .name = "getitimer", .errmsg = true, STRARRAY(0, which, itimers), },
625 { .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -0300626 { .name = "ioctl", .errmsg = true,
627 .arg_scnprintf = { [2] = SCA_HEX, /* arg */ }, },
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -0300628 { .name = "kill", .errmsg = true,
629 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300630 { .name = "lseek", .errmsg = true, STRARRAY(2, whence, whences), },
Arnaldo Carvalho de Meloe5959682013-08-26 12:21:41 -0300631 { .name = "lstat", .errmsg = true, .alias = "newlstat", },
Arnaldo Carvalho de Melo9e9716d2013-08-23 10:06:41 -0300632 { .name = "madvise", .errmsg = true,
633 .arg_scnprintf = { [0] = SCA_HEX, /* start */
634 [2] = SCA_MADV_BHV, /* behavior */ }, },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -0300635 { .name = "mmap", .hexret = true,
Arnaldo Carvalho de Meloae685382013-08-20 17:44:42 -0300636 .arg_scnprintf = { [0] = SCA_HEX, /* addr */
Arnaldo Carvalho de Melo941557e2013-08-23 10:48:33 -0300637 [2] = SCA_MMAP_PROT, /* prot */
638 [3] = SCA_MMAP_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -0300639 { .name = "mprotect", .errmsg = true,
Arnaldo Carvalho de Meloae685382013-08-20 17:44:42 -0300640 .arg_scnprintf = { [0] = SCA_HEX, /* start */
641 [2] = SCA_MMAP_PROT, /* prot */ }, },
642 { .name = "mremap", .hexret = true,
643 .arg_scnprintf = { [0] = SCA_HEX, /* addr */
644 [4] = SCA_HEX, /* new_addr */ }, },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -0300645 { .name = "munmap", .errmsg = true,
646 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
Arnaldo Carvalho de Melobe65a892013-09-02 16:22:31 -0300647 { .name = "open", .errmsg = true,
648 .arg_scnprintf = { [1] = SCA_OPEN_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo31cd3852013-09-02 16:40:40 -0300649 { .name = "open_by_handle_at", .errmsg = true,
650 .arg_scnprintf = { [2] = SCA_OPEN_FLAGS, /* flags */ }, },
651 { .name = "openat", .errmsg = true,
652 .arg_scnprintf = { [2] = SCA_OPEN_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo46cce192013-09-23 12:52:04 -0300653 { .name = "pipe2", .errmsg = true,
654 .arg_scnprintf = { [1] = SCA_PIPE_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -0300655 { .name = "poll", .errmsg = true, .timeout = true, },
656 { .name = "ppoll", .errmsg = true, .timeout = true, },
Arnaldo Carvalho de Meloe5959682013-08-26 12:21:41 -0300657 { .name = "pread", .errmsg = true, .alias = "pread64", },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300658 { .name = "prlimit64", .errmsg = true, STRARRAY(1, resource, rlimit_resources), },
Arnaldo Carvalho de Meloe5959682013-08-26 12:21:41 -0300659 { .name = "pwrite", .errmsg = true, .alias = "pwrite64", },
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -0300660 { .name = "read", .errmsg = true, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -0300661 { .name = "recvfrom", .errmsg = true,
662 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
663 { .name = "recvmmsg", .errmsg = true,
664 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
665 { .name = "recvmsg", .errmsg = true,
666 .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -0300667 { .name = "rt_sigaction", .errmsg = true,
668 .arg_scnprintf = { [0] = SCA_SIGNUM, /* sig */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300669 { .name = "rt_sigprocmask", .errmsg = true, STRARRAY(0, how, sighow), },
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -0300670 { .name = "rt_sigqueueinfo", .errmsg = true,
671 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
672 { .name = "rt_tgsigqueueinfo", .errmsg = true,
673 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -0300674 { .name = "select", .errmsg = true, .timeout = true, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -0300675 { .name = "sendmmsg", .errmsg = true,
676 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
677 { .name = "sendmsg", .errmsg = true,
678 .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, },
679 { .name = "sendto", .errmsg = true,
680 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300681 { .name = "setitimer", .errmsg = true, STRARRAY(0, which, itimers), },
682 { .name = "setrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
Arnaldo Carvalho de Meloe10bce82013-09-04 10:27:41 -0300683 { .name = "socket", .errmsg = true,
Arnaldo Carvalho de Meloa28b24b2013-09-04 11:00:44 -0300684 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
685 [1] = SCA_SK_TYPE, /* type */ },
Arnaldo Carvalho de Meloe10bce82013-09-04 10:27:41 -0300686 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, },
Arnaldo Carvalho de Melo07120aa2013-09-20 12:24:20 -0300687 { .name = "socketpair", .errmsg = true,
688 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
689 [1] = SCA_SK_TYPE, /* type */ },
690 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, },
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -0300691 { .name = "stat", .errmsg = true, .alias = "newstat", },
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -0300692 { .name = "tgkill", .errmsg = true,
693 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
694 { .name = "tkill", .errmsg = true,
695 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
Arnaldo Carvalho de Meloe5959682013-08-26 12:21:41 -0300696 { .name = "uname", .errmsg = true, .alias = "newuname", },
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300697};
698
699static int syscall_fmt__cmp(const void *name, const void *fmtp)
700{
701 const struct syscall_fmt *fmt = fmtp;
702 return strcmp(name, fmt->name);
703}
704
705static struct syscall_fmt *syscall_fmt__find(const char *name)
706{
707 const int nmemb = ARRAY_SIZE(syscall_fmts);
708 return bsearch(name, syscall_fmts, nmemb, sizeof(struct syscall_fmt), syscall_fmt__cmp);
709}
710
711struct syscall {
712 struct event_format *tp_format;
713 const char *name;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -0300714 bool filtered;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300715 struct syscall_fmt *fmt;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300716 size_t (**arg_scnprintf)(char *bf, size_t size, struct syscall_arg *arg);
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300717 void **arg_parm;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300718};
719
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -0200720static size_t fprintf_duration(unsigned long t, FILE *fp)
721{
722 double duration = (double)t / NSEC_PER_MSEC;
723 size_t printed = fprintf(fp, "(");
724
725 if (duration >= 1.0)
726 printed += color_fprintf(fp, PERF_COLOR_RED, "%6.3f ms", duration);
727 else if (duration >= 0.01)
728 printed += color_fprintf(fp, PERF_COLOR_YELLOW, "%6.3f ms", duration);
729 else
730 printed += color_fprintf(fp, PERF_COLOR_NORMAL, "%6.3f ms", duration);
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -0300731 return printed + fprintf(fp, "): ");
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -0200732}
733
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300734struct thread_trace {
735 u64 entry_time;
736 u64 exit_time;
737 bool entry_pending;
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -0300738 unsigned long nr_events;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300739 char *entry_str;
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -0300740 double runtime_ms;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300741};
742
743static struct thread_trace *thread_trace__new(void)
744{
745 return zalloc(sizeof(struct thread_trace));
746}
747
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -0300748static struct thread_trace *thread__trace(struct thread *thread, FILE *fp)
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300749{
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -0300750 struct thread_trace *ttrace;
751
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300752 if (thread == NULL)
753 goto fail;
754
755 if (thread->priv == NULL)
756 thread->priv = thread_trace__new();
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -0300757
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300758 if (thread->priv == NULL)
759 goto fail;
760
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -0300761 ttrace = thread->priv;
762 ++ttrace->nr_events;
763
764 return ttrace;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300765fail:
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -0300766 color_fprintf(fp, PERF_COLOR_RED,
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300767 "WARNING: not enough memory, dropping samples!\n");
768 return NULL;
769}
770
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300771struct trace {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -0300772 struct perf_tool tool;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300773 int audit_machine;
774 struct {
775 int max;
776 struct syscall *table;
777 } syscalls;
778 struct perf_record_opts opts;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300779 struct machine host;
780 u64 base_time;
David Ahern4bb09192013-09-04 12:37:43 -0600781 bool full_time;
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -0300782 FILE *output;
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -0300783 unsigned long nr_events;
Arnaldo Carvalho de Melob059efd2013-08-21 12:56:21 -0300784 struct strlist *ev_qualifier;
785 bool not_ev_qualifier;
David Ahernbdc89662013-08-28 22:29:53 -0600786 struct intlist *tid_list;
787 struct intlist *pid_list;
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -0300788 bool sched;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300789 bool multiple_threads;
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -0300790 bool show_comm;
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -0300791 double duration_filter;
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -0300792 double runtime_ms;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300793};
794
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -0300795static bool trace__filter_duration(struct trace *trace, double t)
796{
797 return t < (trace->duration_filter * NSEC_PER_MSEC);
798}
799
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300800static size_t trace__fprintf_tstamp(struct trace *trace, u64 tstamp, FILE *fp)
801{
802 double ts = (double)(tstamp - trace->base_time) / NSEC_PER_MSEC;
803
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -0200804 return fprintf(fp, "%10.3f ", ts);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300805}
806
Namhyung Kimf15eb532012-10-05 14:02:16 +0900807static bool done = false;
808
809static void sig_handler(int sig __maybe_unused)
810{
811 done = true;
812}
813
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300814static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thread,
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -0200815 u64 duration, u64 tstamp, FILE *fp)
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300816{
817 size_t printed = trace__fprintf_tstamp(trace, tstamp, fp);
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -0200818 printed += fprintf_duration(duration, fp);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300819
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -0300820 if (trace->multiple_threads) {
821 if (trace->show_comm)
822 printed += fprintf(fp, "%.14s/", thread->comm);
Adrian Hunter38051232013-07-04 16:20:31 +0300823 printed += fprintf(fp, "%d ", thread->tid);
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -0300824 }
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300825
826 return printed;
827}
828
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -0300829static int trace__process_event(struct trace *trace, struct machine *machine,
830 union perf_event *event)
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300831{
832 int ret = 0;
833
834 switch (event->header.type) {
835 case PERF_RECORD_LOST:
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -0300836 color_fprintf(trace->output, PERF_COLOR_RED,
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300837 "LOST %" PRIu64 " events!\n", event->lost.lost);
838 ret = machine__process_lost_event(machine, event);
839 default:
840 ret = machine__process_event(machine, event);
841 break;
842 }
843
844 return ret;
845}
846
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -0300847static int trace__tool_process(struct perf_tool *tool,
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300848 union perf_event *event,
849 struct perf_sample *sample __maybe_unused,
850 struct machine *machine)
851{
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -0300852 struct trace *trace = container_of(tool, struct trace, tool);
853 return trace__process_event(trace, machine, event);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300854}
855
856static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
857{
858 int err = symbol__init();
859
860 if (err)
861 return err;
862
863 machine__init(&trace->host, "", HOST_KERNEL_ID);
864 machine__create_kernel_maps(&trace->host);
865
866 if (perf_target__has_task(&trace->opts.target)) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -0300867 err = perf_event__synthesize_thread_map(&trace->tool, evlist->threads,
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300868 trace__tool_process,
869 &trace->host);
870 } else {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -0300871 err = perf_event__synthesize_threads(&trace->tool, trace__tool_process,
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300872 &trace->host);
873 }
874
875 if (err)
876 symbol__exit();
877
878 return err;
879}
880
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -0300881static int syscall__set_arg_fmts(struct syscall *sc)
882{
883 struct format_field *field;
884 int idx = 0;
885
886 sc->arg_scnprintf = calloc(sc->tp_format->format.nr_fields - 1, sizeof(void *));
887 if (sc->arg_scnprintf == NULL)
888 return -1;
889
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300890 if (sc->fmt)
891 sc->arg_parm = sc->fmt->arg_parm;
892
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -0300893 for (field = sc->tp_format->format.fields->next; field; field = field->next) {
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -0300894 if (sc->fmt && sc->fmt->arg_scnprintf[idx])
895 sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx];
896 else if (field->flags & FIELD_IS_POINTER)
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -0300897 sc->arg_scnprintf[idx] = syscall_arg__scnprintf_hex;
898 ++idx;
899 }
900
901 return 0;
902}
903
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300904static int trace__read_syscall_info(struct trace *trace, int id)
905{
906 char tp_name[128];
907 struct syscall *sc;
Arnaldo Carvalho de Melo3a531262012-10-20 12:39:03 -0300908 const char *name = audit_syscall_to_name(id, trace->audit_machine);
909
910 if (name == NULL)
911 return -1;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300912
913 if (id > trace->syscalls.max) {
914 struct syscall *nsyscalls = realloc(trace->syscalls.table, (id + 1) * sizeof(*sc));
915
916 if (nsyscalls == NULL)
917 return -1;
918
919 if (trace->syscalls.max != -1) {
920 memset(nsyscalls + trace->syscalls.max + 1, 0,
921 (id - trace->syscalls.max) * sizeof(*sc));
922 } else {
923 memset(nsyscalls, 0, (id + 1) * sizeof(*sc));
924 }
925
926 trace->syscalls.table = nsyscalls;
927 trace->syscalls.max = id;
928 }
929
930 sc = trace->syscalls.table + id;
Arnaldo Carvalho de Melo3a531262012-10-20 12:39:03 -0300931 sc->name = name;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -0300932
Arnaldo Carvalho de Melob059efd2013-08-21 12:56:21 -0300933 if (trace->ev_qualifier) {
934 bool in = strlist__find(trace->ev_qualifier, name) != NULL;
935
936 if (!(in ^ trace->not_ev_qualifier)) {
937 sc->filtered = true;
938 /*
939 * No need to do read tracepoint information since this will be
940 * filtered out.
941 */
942 return 0;
943 }
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -0300944 }
945
Arnaldo Carvalho de Melo3a531262012-10-20 12:39:03 -0300946 sc->fmt = syscall_fmt__find(sc->name);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300947
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -0300948 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name);
949 sc->tp_format = event_format__new("syscalls", tp_name);
950
951 if (sc->tp_format == NULL && sc->fmt && sc->fmt->alias) {
952 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->fmt->alias);
953 sc->tp_format = event_format__new("syscalls", tp_name);
954 }
955
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -0300956 if (sc->tp_format == NULL)
957 return -1;
958
959 return syscall__set_arg_fmts(sc);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300960}
961
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300962static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
963 unsigned long *args)
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300964{
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300965 size_t printed = 0;
966
967 if (sc->tp_format != NULL) {
968 struct format_field *field;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300969 u8 bit = 1;
970 struct syscall_arg arg = {
971 .idx = 0,
972 .mask = 0,
973 };
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300974
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -0300975 for (field = sc->tp_format->format.fields->next; field;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300976 field = field->next, ++arg.idx, bit <<= 1) {
977 if (arg.mask & bit)
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -0300978 continue;
Arnaldo Carvalho de Melo4aa58232013-09-20 12:19:41 -0300979 /*
980 * Suppress this argument if its value is zero and
981 * and we don't have a string associated in an
982 * strarray for it.
983 */
984 if (args[arg.idx] == 0 &&
985 !(sc->arg_scnprintf &&
986 sc->arg_scnprintf[arg.idx] == SCA_STRARRAY &&
987 sc->arg_parm[arg.idx]))
Arnaldo Carvalho de Melo22ae5cf12013-09-12 11:27:34 -0300988 continue;
989
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300990 printed += scnprintf(bf + printed, size - printed,
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -0300991 "%s%s: ", printed ? ", " : "", field->name);
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300992 if (sc->arg_scnprintf && sc->arg_scnprintf[arg.idx]) {
993 arg.val = args[arg.idx];
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300994 if (sc->arg_parm)
995 arg.parm = sc->arg_parm[arg.idx];
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300996 printed += sc->arg_scnprintf[arg.idx](bf + printed,
997 size - printed, &arg);
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -0300998 } else {
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -0300999 printed += scnprintf(bf + printed, size - printed,
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001000 "%ld", args[arg.idx]);
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -03001001 }
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001002 }
1003 } else {
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001004 int i = 0;
1005
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001006 while (i < 6) {
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001007 printed += scnprintf(bf + printed, size - printed,
1008 "%sarg%d: %ld",
1009 printed ? ", " : "", i, args[i]);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001010 ++i;
1011 }
1012 }
1013
1014 return printed;
1015}
1016
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001017typedef int (*tracepoint_handler)(struct trace *trace, struct perf_evsel *evsel,
1018 struct perf_sample *sample);
1019
1020static struct syscall *trace__syscall_info(struct trace *trace,
1021 struct perf_evsel *evsel,
1022 struct perf_sample *sample)
1023{
1024 int id = perf_evsel__intval(evsel, sample, "id");
1025
1026 if (id < 0) {
Arnaldo Carvalho de Meloadaa18b2013-08-22 17:55:25 -03001027
1028 /*
1029 * XXX: Noticed on x86_64, reproduced as far back as 3.0.36, haven't tried
1030 * before that, leaving at a higher verbosity level till that is
1031 * explained. Reproduced with plain ftrace with:
1032 *
1033 * echo 1 > /t/events/raw_syscalls/sys_exit/enable
1034 * grep "NR -1 " /t/trace_pipe
1035 *
1036 * After generating some load on the machine.
1037 */
1038 if (verbose > 1) {
1039 static u64 n;
1040 fprintf(trace->output, "Invalid syscall %d id, skipping (%s, %" PRIu64 ") ...\n",
1041 id, perf_evsel__name(evsel), ++n);
1042 }
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001043 return NULL;
1044 }
1045
1046 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL) &&
1047 trace__read_syscall_info(trace, id))
1048 goto out_cant_read;
1049
1050 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL))
1051 goto out_cant_read;
1052
1053 return &trace->syscalls.table[id];
1054
1055out_cant_read:
Arnaldo Carvalho de Melo7c304ee02013-08-22 16:49:54 -03001056 if (verbose) {
1057 fprintf(trace->output, "Problems reading syscall %d", id);
1058 if (id <= trace->syscalls.max && trace->syscalls.table[id].name != NULL)
1059 fprintf(trace->output, "(%s)", trace->syscalls.table[id].name);
1060 fputs(" information\n", trace->output);
1061 }
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001062 return NULL;
1063}
1064
1065static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
1066 struct perf_sample *sample)
1067{
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001068 char *msg;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001069 void *args;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001070 size_t printed = 0;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001071 struct thread *thread;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001072 struct syscall *sc = trace__syscall_info(trace, evsel, sample);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001073 struct thread_trace *ttrace;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001074
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001075 if (sc == NULL)
1076 return -1;
1077
1078 if (sc->filtered)
1079 return 0;
1080
Adrian Hunter314add62013-08-27 11:23:03 +03001081 thread = machine__findnew_thread(&trace->host, sample->pid,
1082 sample->tid);
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001083 ttrace = thread__trace(thread, trace->output);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001084 if (ttrace == NULL)
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001085 return -1;
1086
1087 args = perf_evsel__rawptr(evsel, sample, "args");
1088 if (args == NULL) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001089 fprintf(trace->output, "Problems reading syscall arguments\n");
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001090 return -1;
1091 }
1092
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001093 ttrace = thread->priv;
1094
1095 if (ttrace->entry_str == NULL) {
1096 ttrace->entry_str = malloc(1024);
1097 if (!ttrace->entry_str)
1098 return -1;
1099 }
1100
1101 ttrace->entry_time = sample->time;
1102 msg = ttrace->entry_str;
1103 printed += scnprintf(msg + printed, 1024 - printed, "%s(", sc->name);
1104
1105 printed += syscall__scnprintf_args(sc, msg + printed, 1024 - printed, args);
1106
1107 if (!strcmp(sc->name, "exit_group") || !strcmp(sc->name, "exit")) {
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001108 if (!trace->duration_filter) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001109 trace__fprintf_entry_head(trace, thread, 1, sample->time, trace->output);
1110 fprintf(trace->output, "%-70s\n", ttrace->entry_str);
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001111 }
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001112 } else
1113 ttrace->entry_pending = true;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001114
1115 return 0;
1116}
1117
1118static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
1119 struct perf_sample *sample)
1120{
1121 int ret;
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001122 u64 duration = 0;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001123 struct thread *thread;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001124 struct syscall *sc = trace__syscall_info(trace, evsel, sample);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001125 struct thread_trace *ttrace;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001126
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001127 if (sc == NULL)
1128 return -1;
1129
1130 if (sc->filtered)
1131 return 0;
1132
Adrian Hunter314add62013-08-27 11:23:03 +03001133 thread = machine__findnew_thread(&trace->host, sample->pid,
1134 sample->tid);
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001135 ttrace = thread__trace(thread, trace->output);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001136 if (ttrace == NULL)
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001137 return -1;
1138
1139 ret = perf_evsel__intval(evsel, sample, "ret");
1140
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001141 ttrace = thread->priv;
1142
1143 ttrace->exit_time = sample->time;
1144
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001145 if (ttrace->entry_time) {
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001146 duration = sample->time - ttrace->entry_time;
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001147 if (trace__filter_duration(trace, duration))
1148 goto out;
1149 } else if (trace->duration_filter)
1150 goto out;
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001151
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001152 trace__fprintf_entry_head(trace, thread, duration, sample->time, trace->output);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001153
1154 if (ttrace->entry_pending) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001155 fprintf(trace->output, "%-70s", ttrace->entry_str);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001156 } else {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001157 fprintf(trace->output, " ... [");
1158 color_fprintf(trace->output, PERF_COLOR_YELLOW, "continued");
1159 fprintf(trace->output, "]: %s()", sc->name);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001160 }
1161
Arnaldo Carvalho de Meloda3c9a42013-08-26 11:28:34 -03001162 if (sc->fmt == NULL) {
1163signed_print:
1164 fprintf(trace->output, ") = %d", ret);
1165 } else if (ret < 0 && sc->fmt->errmsg) {
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001166 char bf[256];
1167 const char *emsg = strerror_r(-ret, bf, sizeof(bf)),
1168 *e = audit_errno_to_name(-ret);
1169
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001170 fprintf(trace->output, ") = -1 %s %s", e, emsg);
Arnaldo Carvalho de Meloda3c9a42013-08-26 11:28:34 -03001171 } else if (ret == 0 && sc->fmt->timeout)
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001172 fprintf(trace->output, ") = 0 Timeout");
Arnaldo Carvalho de Melo04b34722013-08-26 11:36:30 -03001173 else if (sc->fmt->hexret)
1174 fprintf(trace->output, ") = %#x", ret);
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001175 else
Arnaldo Carvalho de Meloda3c9a42013-08-26 11:28:34 -03001176 goto signed_print;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001177
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001178 fputc('\n', trace->output);
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001179out:
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001180 ttrace->entry_pending = false;
1181
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001182 return 0;
1183}
1184
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001185static int trace__sched_stat_runtime(struct trace *trace, struct perf_evsel *evsel,
1186 struct perf_sample *sample)
1187{
1188 u64 runtime = perf_evsel__intval(evsel, sample, "runtime");
1189 double runtime_ms = (double)runtime / NSEC_PER_MSEC;
Adrian Hunter314add62013-08-27 11:23:03 +03001190 struct thread *thread = machine__findnew_thread(&trace->host,
1191 sample->pid,
1192 sample->tid);
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001193 struct thread_trace *ttrace = thread__trace(thread, trace->output);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001194
1195 if (ttrace == NULL)
1196 goto out_dump;
1197
1198 ttrace->runtime_ms += runtime_ms;
1199 trace->runtime_ms += runtime_ms;
1200 return 0;
1201
1202out_dump:
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001203 fprintf(trace->output, "%s: comm=%s,pid=%u,runtime=%" PRIu64 ",vruntime=%" PRIu64 ")\n",
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001204 evsel->name,
1205 perf_evsel__strval(evsel, sample, "comm"),
1206 (pid_t)perf_evsel__intval(evsel, sample, "pid"),
1207 runtime,
1208 perf_evsel__intval(evsel, sample, "vruntime"));
1209 return 0;
1210}
1211
David Ahernbdc89662013-08-28 22:29:53 -06001212static bool skip_sample(struct trace *trace, struct perf_sample *sample)
1213{
1214 if ((trace->pid_list && intlist__find(trace->pid_list, sample->pid)) ||
1215 (trace->tid_list && intlist__find(trace->tid_list, sample->tid)))
1216 return false;
1217
1218 if (trace->pid_list || trace->tid_list)
1219 return true;
1220
1221 return false;
1222}
1223
David Ahern6810fc92013-08-28 22:29:52 -06001224static int trace__process_sample(struct perf_tool *tool,
1225 union perf_event *event __maybe_unused,
1226 struct perf_sample *sample,
1227 struct perf_evsel *evsel,
1228 struct machine *machine __maybe_unused)
1229{
1230 struct trace *trace = container_of(tool, struct trace, tool);
1231 int err = 0;
1232
1233 tracepoint_handler handler = evsel->handler.func;
1234
David Ahernbdc89662013-08-28 22:29:53 -06001235 if (skip_sample(trace, sample))
1236 return 0;
1237
David Ahern4bb09192013-09-04 12:37:43 -06001238 if (!trace->full_time && trace->base_time == 0)
David Ahern6810fc92013-08-28 22:29:52 -06001239 trace->base_time = sample->time;
1240
1241 if (handler)
1242 handler(trace, evsel, sample);
1243
1244 return err;
1245}
1246
1247static bool
1248perf_session__has_tp(struct perf_session *session, const char *name)
1249{
1250 struct perf_evsel *evsel;
1251
1252 evsel = perf_evlist__find_tracepoint_by_name(session->evlist, name);
1253
1254 return evsel != NULL;
1255}
1256
David Ahernbdc89662013-08-28 22:29:53 -06001257static int parse_target_str(struct trace *trace)
1258{
1259 if (trace->opts.target.pid) {
1260 trace->pid_list = intlist__new(trace->opts.target.pid);
1261 if (trace->pid_list == NULL) {
1262 pr_err("Error parsing process id string\n");
1263 return -EINVAL;
1264 }
1265 }
1266
1267 if (trace->opts.target.tid) {
1268 trace->tid_list = intlist__new(trace->opts.target.tid);
1269 if (trace->tid_list == NULL) {
1270 pr_err("Error parsing thread id string\n");
1271 return -EINVAL;
1272 }
1273 }
1274
1275 return 0;
1276}
1277
Namhyung Kimf15eb532012-10-05 14:02:16 +09001278static int trace__run(struct trace *trace, int argc, const char **argv)
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001279{
Namhyung Kim334fe7a2013-03-11 16:43:12 +09001280 struct perf_evlist *evlist = perf_evlist__new();
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001281 struct perf_evsel *evsel;
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03001282 int err = -1, i;
1283 unsigned long before;
Namhyung Kimf15eb532012-10-05 14:02:16 +09001284 const bool forks = argc > 0;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001285
1286 if (evlist == NULL) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001287 fprintf(trace->output, "Not enough memory to run!\n");
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001288 goto out;
1289 }
1290
Arnaldo Carvalho de Melo39876e72012-10-03 11:40:22 -03001291 if (perf_evlist__add_newtp(evlist, "raw_syscalls", "sys_enter", trace__sys_enter) ||
1292 perf_evlist__add_newtp(evlist, "raw_syscalls", "sys_exit", trace__sys_exit)) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001293 fprintf(trace->output, "Couldn't read the raw_syscalls tracepoints information!\n");
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001294 goto out_delete_evlist;
1295 }
1296
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001297 if (trace->sched &&
1298 perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime",
1299 trace__sched_stat_runtime)) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001300 fprintf(trace->output, "Couldn't read the sched_stat_runtime tracepoint information!\n");
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001301 goto out_delete_evlist;
1302 }
1303
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001304 err = perf_evlist__create_maps(evlist, &trace->opts.target);
1305 if (err < 0) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001306 fprintf(trace->output, "Problems parsing the target to trace, check your options!\n");
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001307 goto out_delete_evlist;
1308 }
1309
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001310 err = trace__symbols_init(trace, evlist);
1311 if (err < 0) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001312 fprintf(trace->output, "Problems initializing symbol libraries!\n");
Namhyung Kim3beb0862013-03-15 14:48:50 +09001313 goto out_delete_maps;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001314 }
1315
Arnaldo Carvalho de Melof77a9512012-12-10 16:41:31 -03001316 perf_evlist__config(evlist, &trace->opts);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001317
Namhyung Kimf15eb532012-10-05 14:02:16 +09001318 signal(SIGCHLD, sig_handler);
1319 signal(SIGINT, sig_handler);
1320
1321 if (forks) {
Namhyung Kim6ef73ec2013-03-11 16:43:15 +09001322 err = perf_evlist__prepare_workload(evlist, &trace->opts.target,
Namhyung Kim55e162e2013-03-11 16:43:17 +09001323 argv, false, false);
Namhyung Kimf15eb532012-10-05 14:02:16 +09001324 if (err < 0) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001325 fprintf(trace->output, "Couldn't run the workload!\n");
Namhyung Kim3beb0862013-03-15 14:48:50 +09001326 goto out_delete_maps;
Namhyung Kimf15eb532012-10-05 14:02:16 +09001327 }
1328 }
1329
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001330 err = perf_evlist__open(evlist);
1331 if (err < 0) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001332 fprintf(trace->output, "Couldn't create the events: %s\n", strerror(errno));
Namhyung Kim3beb0862013-03-15 14:48:50 +09001333 goto out_delete_maps;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001334 }
1335
1336 err = perf_evlist__mmap(evlist, UINT_MAX, false);
1337 if (err < 0) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001338 fprintf(trace->output, "Couldn't mmap the events: %s\n", strerror(errno));
Namhyung Kim3beb0862013-03-15 14:48:50 +09001339 goto out_close_evlist;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001340 }
1341
1342 perf_evlist__enable(evlist);
Namhyung Kimf15eb532012-10-05 14:02:16 +09001343
1344 if (forks)
1345 perf_evlist__start_workload(evlist);
1346
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001347 trace->multiple_threads = evlist->threads->map[0] == -1 || evlist->threads->nr > 1;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001348again:
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03001349 before = trace->nr_events;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001350
1351 for (i = 0; i < evlist->nr_mmaps; i++) {
1352 union perf_event *event;
1353
1354 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
1355 const u32 type = event->header.type;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001356 tracepoint_handler handler;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001357 struct perf_sample sample;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001358
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03001359 ++trace->nr_events;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001360
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001361 err = perf_evlist__parse_sample(evlist, event, &sample);
1362 if (err) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001363 fprintf(trace->output, "Can't parse sample, err = %d, skipping...\n", err);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001364 continue;
1365 }
1366
David Ahern4bb09192013-09-04 12:37:43 -06001367 if (!trace->full_time && trace->base_time == 0)
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001368 trace->base_time = sample.time;
1369
1370 if (type != PERF_RECORD_SAMPLE) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001371 trace__process_event(trace, &trace->host, event);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001372 continue;
1373 }
1374
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001375 evsel = perf_evlist__id2evsel(evlist, sample.id);
1376 if (evsel == NULL) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001377 fprintf(trace->output, "Unknown tp ID %" PRIu64 ", skipping...\n", sample.id);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001378 continue;
1379 }
1380
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001381 if (sample.raw_data == NULL) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001382 fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n",
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001383 perf_evsel__name(evsel), sample.tid,
1384 sample.cpu, sample.raw_size);
1385 continue;
1386 }
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001387
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001388 handler = evsel->handler.func;
1389 handler(trace, evsel, &sample);
Arnaldo Carvalho de Melo20c5f102013-09-03 11:55:07 -03001390
1391 if (done)
1392 goto out_unmap_evlist;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001393 }
1394 }
1395
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03001396 if (trace->nr_events == before) {
Namhyung Kimf15eb532012-10-05 14:02:16 +09001397 if (done)
Namhyung Kim3beb0862013-03-15 14:48:50 +09001398 goto out_unmap_evlist;
Namhyung Kimf15eb532012-10-05 14:02:16 +09001399
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001400 poll(evlist->pollfd, evlist->nr_fds, -1);
Namhyung Kimf15eb532012-10-05 14:02:16 +09001401 }
1402
1403 if (done)
1404 perf_evlist__disable(evlist);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001405
1406 goto again;
1407
Namhyung Kim3beb0862013-03-15 14:48:50 +09001408out_unmap_evlist:
1409 perf_evlist__munmap(evlist);
1410out_close_evlist:
1411 perf_evlist__close(evlist);
1412out_delete_maps:
1413 perf_evlist__delete_maps(evlist);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001414out_delete_evlist:
1415 perf_evlist__delete(evlist);
1416out:
1417 return err;
1418}
1419
David Ahern6810fc92013-08-28 22:29:52 -06001420static int trace__replay(struct trace *trace)
1421{
1422 const struct perf_evsel_str_handler handlers[] = {
1423 { "raw_syscalls:sys_enter", trace__sys_enter, },
1424 { "raw_syscalls:sys_exit", trace__sys_exit, },
1425 };
1426
1427 struct perf_session *session;
1428 int err = -1;
1429
1430 trace->tool.sample = trace__process_sample;
1431 trace->tool.mmap = perf_event__process_mmap;
David Ahern384c6712013-09-22 19:44:58 -06001432 trace->tool.mmap2 = perf_event__process_mmap2;
David Ahern6810fc92013-08-28 22:29:52 -06001433 trace->tool.comm = perf_event__process_comm;
1434 trace->tool.exit = perf_event__process_exit;
1435 trace->tool.fork = perf_event__process_fork;
1436 trace->tool.attr = perf_event__process_attr;
1437 trace->tool.tracing_data = perf_event__process_tracing_data;
1438 trace->tool.build_id = perf_event__process_build_id;
1439
1440 trace->tool.ordered_samples = true;
1441 trace->tool.ordering_requires_timestamps = true;
1442
1443 /* add tid to output */
1444 trace->multiple_threads = true;
1445
1446 if (symbol__init() < 0)
1447 return -1;
1448
1449 session = perf_session__new(input_name, O_RDONLY, 0, false,
1450 &trace->tool);
1451 if (session == NULL)
1452 return -ENOMEM;
1453
1454 err = perf_session__set_tracepoints_handlers(session, handlers);
1455 if (err)
1456 goto out;
1457
1458 if (!perf_session__has_tp(session, "raw_syscalls:sys_enter")) {
1459 pr_err("Data file does not have raw_syscalls:sys_enter events\n");
1460 goto out;
1461 }
1462
1463 if (!perf_session__has_tp(session, "raw_syscalls:sys_exit")) {
1464 pr_err("Data file does not have raw_syscalls:sys_exit events\n");
1465 goto out;
1466 }
1467
David Ahernbdc89662013-08-28 22:29:53 -06001468 err = parse_target_str(trace);
1469 if (err != 0)
1470 goto out;
1471
David Ahern6810fc92013-08-28 22:29:52 -06001472 setup_pager();
1473
1474 err = perf_session__process_events(session, &trace->tool);
1475 if (err)
1476 pr_err("Failed to process events, error %d", err);
1477
1478out:
1479 perf_session__delete(session);
1480
1481 return err;
1482}
1483
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001484static size_t trace__fprintf_threads_header(FILE *fp)
1485{
1486 size_t printed;
1487
1488 printed = fprintf(fp, "\n _____________________________________________________________________\n");
1489 printed += fprintf(fp," __) Summary of events (__\n\n");
1490 printed += fprintf(fp," [ task - pid ] [ events ] [ ratio ] [ runtime ]\n");
1491 printed += fprintf(fp," _____________________________________________________________________\n\n");
1492
1493 return printed;
1494}
1495
1496static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp)
1497{
1498 size_t printed = trace__fprintf_threads_header(fp);
1499 struct rb_node *nd;
1500
1501 for (nd = rb_first(&trace->host.threads); nd; nd = rb_next(nd)) {
1502 struct thread *thread = rb_entry(nd, struct thread, rb_node);
1503 struct thread_trace *ttrace = thread->priv;
1504 const char *color;
1505 double ratio;
1506
1507 if (ttrace == NULL)
1508 continue;
1509
1510 ratio = (double)ttrace->nr_events / trace->nr_events * 100.0;
1511
1512 color = PERF_COLOR_NORMAL;
1513 if (ratio > 50.0)
1514 color = PERF_COLOR_RED;
1515 else if (ratio > 25.0)
1516 color = PERF_COLOR_GREEN;
1517 else if (ratio > 5.0)
1518 color = PERF_COLOR_YELLOW;
1519
1520 printed += color_fprintf(fp, color, "%20s", thread->comm);
Adrian Hunter38051232013-07-04 16:20:31 +03001521 printed += fprintf(fp, " - %-5d :%11lu [", thread->tid, ttrace->nr_events);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001522 printed += color_fprintf(fp, color, "%5.1f%%", ratio);
1523 printed += fprintf(fp, " ] %10.3f ms\n", ttrace->runtime_ms);
1524 }
1525
1526 return printed;
1527}
1528
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001529static int trace__set_duration(const struct option *opt, const char *str,
1530 int unset __maybe_unused)
1531{
1532 struct trace *trace = opt->value;
1533
1534 trace->duration_filter = atof(str);
1535 return 0;
1536}
1537
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001538static int trace__open_output(struct trace *trace, const char *filename)
1539{
1540 struct stat st;
1541
1542 if (!stat(filename, &st) && st.st_size) {
1543 char oldname[PATH_MAX];
1544
1545 scnprintf(oldname, sizeof(oldname), "%s.old", filename);
1546 unlink(oldname);
1547 rename(filename, oldname);
1548 }
1549
1550 trace->output = fopen(filename, "w");
1551
1552 return trace->output == NULL ? -errno : 0;
1553}
1554
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001555int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
1556{
1557 const char * const trace_usage[] = {
Namhyung Kimf15eb532012-10-05 14:02:16 +09001558 "perf trace [<options>] [<command>]",
1559 "perf trace [<options>] -- <command> [<options>]",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001560 NULL
1561 };
1562 struct trace trace = {
1563 .audit_machine = audit_detect_machine(),
1564 .syscalls = {
1565 . max = -1,
1566 },
1567 .opts = {
1568 .target = {
1569 .uid = UINT_MAX,
1570 .uses_mmap = true,
1571 },
1572 .user_freq = UINT_MAX,
1573 .user_interval = ULLONG_MAX,
1574 .no_delay = true,
1575 .mmap_pages = 1024,
1576 },
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001577 .output = stdout,
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -03001578 .show_comm = true,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001579 };
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001580 const char *output_name = NULL;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001581 const char *ev_qualifier_str = NULL;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001582 const struct option trace_options[] = {
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -03001583 OPT_BOOLEAN(0, "comm", &trace.show_comm,
1584 "show the thread COMM next to its id"),
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001585 OPT_STRING('e', "expr", &ev_qualifier_str, "expr",
1586 "list of events to trace"),
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001587 OPT_STRING('o', "output", &output_name, "file", "output file name"),
David Ahern6810fc92013-08-28 22:29:52 -06001588 OPT_STRING('i', "input", &input_name, "file", "Analyze events in file"),
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001589 OPT_STRING('p', "pid", &trace.opts.target.pid, "pid",
1590 "trace events on existing process id"),
David Ahernac9be8e2013-08-20 11:15:45 -06001591 OPT_STRING('t', "tid", &trace.opts.target.tid, "tid",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001592 "trace events on existing thread id"),
David Ahernac9be8e2013-08-20 11:15:45 -06001593 OPT_BOOLEAN('a', "all-cpus", &trace.opts.target.system_wide,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001594 "system-wide collection from all CPUs"),
David Ahernac9be8e2013-08-20 11:15:45 -06001595 OPT_STRING('C', "cpu", &trace.opts.target.cpu_list, "cpu",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001596 "list of cpus to monitor"),
David Ahern6810fc92013-08-28 22:29:52 -06001597 OPT_BOOLEAN(0, "no-inherit", &trace.opts.no_inherit,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001598 "child tasks do not inherit counters"),
Jiri Olsa994a1f72013-09-01 12:36:12 +02001599 OPT_CALLBACK('m', "mmap-pages", &trace.opts.mmap_pages, "pages",
1600 "number of mmap data pages",
1601 perf_evlist__parse_mmap_pages),
David Ahernac9be8e2013-08-20 11:15:45 -06001602 OPT_STRING('u', "uid", &trace.opts.target.uid_str, "user",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001603 "user to profile"),
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001604 OPT_CALLBACK(0, "duration", &trace, "float",
1605 "show only events with duration > N.M ms",
1606 trace__set_duration),
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001607 OPT_BOOLEAN(0, "sched", &trace.sched, "show blocking scheduler events"),
Arnaldo Carvalho de Melo7c304ee02013-08-22 16:49:54 -03001608 OPT_INCR('v', "verbose", &verbose, "be more verbose"),
David Ahern4bb09192013-09-04 12:37:43 -06001609 OPT_BOOLEAN('T', "time", &trace.full_time,
1610 "Show full timestamp, not time relative to first start"),
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001611 OPT_END()
1612 };
1613 int err;
Namhyung Kim32caf0d2012-10-05 14:02:13 +09001614 char bf[BUFSIZ];
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001615
1616 argc = parse_options(argc, argv, trace_options, trace_usage, 0);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001617
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001618 if (output_name != NULL) {
1619 err = trace__open_output(&trace, output_name);
1620 if (err < 0) {
1621 perror("failed to create output file");
1622 goto out;
1623 }
1624 }
1625
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001626 if (ev_qualifier_str != NULL) {
Arnaldo Carvalho de Melob059efd2013-08-21 12:56:21 -03001627 const char *s = ev_qualifier_str;
1628
1629 trace.not_ev_qualifier = *s == '!';
1630 if (trace.not_ev_qualifier)
1631 ++s;
1632 trace.ev_qualifier = strlist__new(true, s);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001633 if (trace.ev_qualifier == NULL) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001634 fputs("Not enough memory to parse event qualifier",
1635 trace.output);
1636 err = -ENOMEM;
1637 goto out_close;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001638 }
1639 }
1640
Namhyung Kim32caf0d2012-10-05 14:02:13 +09001641 err = perf_target__validate(&trace.opts.target);
1642 if (err) {
1643 perf_target__strerror(&trace.opts.target, err, bf, sizeof(bf));
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001644 fprintf(trace.output, "%s", bf);
1645 goto out_close;
Namhyung Kim32caf0d2012-10-05 14:02:13 +09001646 }
1647
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001648 err = perf_target__parse_uid(&trace.opts.target);
1649 if (err) {
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001650 perf_target__strerror(&trace.opts.target, err, bf, sizeof(bf));
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001651 fprintf(trace.output, "%s", bf);
1652 goto out_close;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001653 }
1654
Namhyung Kimf15eb532012-10-05 14:02:16 +09001655 if (!argc && perf_target__none(&trace.opts.target))
Namhyung Kimee761202012-10-05 14:02:14 +09001656 trace.opts.target.system_wide = true;
1657
David Ahern6810fc92013-08-28 22:29:52 -06001658 if (input_name)
1659 err = trace__replay(&trace);
1660 else
1661 err = trace__run(&trace, argc, argv);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001662
1663 if (trace.sched && !err)
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001664 trace__fprintf_thread_summary(&trace, trace.output);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001665
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001666out_close:
1667 if (output_name != NULL)
1668 fclose(trace.output);
1669out:
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001670 return err;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001671}