blob: 27b0ec88cb23ef013aa7c099b6d1d9bd94d3c79e [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
Arnaldo Carvalho de Meloe10bce82013-09-04 10:27:41 -0300300static const char *socket_families[] = {
301 "UNSPEC", "LOCAL", "INET", "AX25", "IPX", "APPLETALK", "NETROM",
302 "BRIDGE", "ATMPVC", "X25", "INET6", "ROSE", "DECnet", "NETBEUI",
303 "SECURITY", "KEY", "NETLINK", "PACKET", "ASH", "ECONET", "ATMSVC",
304 "RDS", "SNA", "IRDA", "PPPOX", "WANPIPE", "LLC", "IB", "CAN", "TIPC",
305 "BLUETOOTH", "IUCV", "RXRPC", "ISDN", "PHONET", "IEEE802154", "CAIF",
306 "ALG", "NFC", "VSOCK",
307};
308static DEFINE_STRARRAY(socket_families);
309
Arnaldo Carvalho de Meloa28b24b2013-09-04 11:00:44 -0300310#ifndef SOCK_TYPE_MASK
311#define SOCK_TYPE_MASK 0xf
312#endif
313
314static size_t syscall_arg__scnprintf_socket_type(char *bf, size_t size,
315 struct syscall_arg *arg)
316{
317 size_t printed;
318 int type = arg->val,
319 flags = type & ~SOCK_TYPE_MASK;
320
321 type &= SOCK_TYPE_MASK;
322 /*
323 * Can't use a strarray, MIPS may override for ABI reasons.
324 */
325 switch (type) {
326#define P_SK_TYPE(n) case SOCK_##n: printed = scnprintf(bf, size, #n); break;
327 P_SK_TYPE(STREAM);
328 P_SK_TYPE(DGRAM);
329 P_SK_TYPE(RAW);
330 P_SK_TYPE(RDM);
331 P_SK_TYPE(SEQPACKET);
332 P_SK_TYPE(DCCP);
333 P_SK_TYPE(PACKET);
334#undef P_SK_TYPE
335 default:
336 printed = scnprintf(bf, size, "%#x", type);
337 }
338
339#define P_SK_FLAG(n) \
340 if (flags & SOCK_##n) { \
341 printed += scnprintf(bf + printed, size - printed, "|%s", #n); \
342 flags &= ~SOCK_##n; \
343 }
344
345 P_SK_FLAG(CLOEXEC);
346 P_SK_FLAG(NONBLOCK);
347#undef P_SK_FLAG
348
349 if (flags)
350 printed += scnprintf(bf + printed, size - printed, "|%#x", flags);
351
352 return printed;
353}
354
355#define SCA_SK_TYPE syscall_arg__scnprintf_socket_type
356
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -0300357#ifndef MSG_PROBE
358#define MSG_PROBE 0x10
359#endif
360#ifndef MSG_SENDPAGE_NOTLAST
361#define MSG_SENDPAGE_NOTLAST 0x20000
362#endif
363#ifndef MSG_FASTOPEN
364#define MSG_FASTOPEN 0x20000000
365#endif
366
367static size_t syscall_arg__scnprintf_msg_flags(char *bf, size_t size,
368 struct syscall_arg *arg)
369{
370 int printed = 0, flags = arg->val;
371
372 if (flags == 0)
373 return scnprintf(bf, size, "NONE");
374#define P_MSG_FLAG(n) \
375 if (flags & MSG_##n) { \
376 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
377 flags &= ~MSG_##n; \
378 }
379
380 P_MSG_FLAG(OOB);
381 P_MSG_FLAG(PEEK);
382 P_MSG_FLAG(DONTROUTE);
383 P_MSG_FLAG(TRYHARD);
384 P_MSG_FLAG(CTRUNC);
385 P_MSG_FLAG(PROBE);
386 P_MSG_FLAG(TRUNC);
387 P_MSG_FLAG(DONTWAIT);
388 P_MSG_FLAG(EOR);
389 P_MSG_FLAG(WAITALL);
390 P_MSG_FLAG(FIN);
391 P_MSG_FLAG(SYN);
392 P_MSG_FLAG(CONFIRM);
393 P_MSG_FLAG(RST);
394 P_MSG_FLAG(ERRQUEUE);
395 P_MSG_FLAG(NOSIGNAL);
396 P_MSG_FLAG(MORE);
397 P_MSG_FLAG(WAITFORONE);
398 P_MSG_FLAG(SENDPAGE_NOTLAST);
399 P_MSG_FLAG(FASTOPEN);
400 P_MSG_FLAG(CMSG_CLOEXEC);
401#undef P_MSG_FLAG
402
403 if (flags)
404 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
405
406 return printed;
407}
408
409#define SCA_MSG_FLAGS syscall_arg__scnprintf_msg_flags
410
Arnaldo Carvalho de Melo51108992013-09-04 11:42:27 -0300411static size_t syscall_arg__scnprintf_access_mode(char *bf, size_t size,
412 struct syscall_arg *arg)
413{
414 size_t printed = 0;
415 int mode = arg->val;
416
417 if (mode == F_OK) /* 0 */
418 return scnprintf(bf, size, "F");
419#define P_MODE(n) \
420 if (mode & n##_OK) { \
421 printed += scnprintf(bf + printed, size - printed, "%s", #n); \
422 mode &= ~n##_OK; \
423 }
424
425 P_MODE(R);
426 P_MODE(W);
427 P_MODE(X);
428#undef P_MODE
429
430 if (mode)
431 printed += scnprintf(bf + printed, size - printed, "|%#x", mode);
432
433 return printed;
434}
435
436#define SCA_ACCMODE syscall_arg__scnprintf_access_mode
437
Arnaldo Carvalho de Melobe65a892013-09-02 16:22:31 -0300438static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300439 struct syscall_arg *arg)
Arnaldo Carvalho de Melobe65a892013-09-02 16:22:31 -0300440{
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300441 int printed = 0, flags = arg->val;
Arnaldo Carvalho de Melobe65a892013-09-02 16:22:31 -0300442
443 if (!(flags & O_CREAT))
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300444 arg->mask |= 1 << (arg->idx + 1); /* Mask the mode parm */
Arnaldo Carvalho de Melobe65a892013-09-02 16:22:31 -0300445
446 if (flags == 0)
447 return scnprintf(bf, size, "RDONLY");
448#define P_FLAG(n) \
449 if (flags & O_##n) { \
450 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
451 flags &= ~O_##n; \
452 }
453
454 P_FLAG(APPEND);
455 P_FLAG(ASYNC);
456 P_FLAG(CLOEXEC);
457 P_FLAG(CREAT);
458 P_FLAG(DIRECT);
459 P_FLAG(DIRECTORY);
460 P_FLAG(EXCL);
461 P_FLAG(LARGEFILE);
462 P_FLAG(NOATIME);
463 P_FLAG(NOCTTY);
464#ifdef O_NONBLOCK
465 P_FLAG(NONBLOCK);
466#elif O_NDELAY
467 P_FLAG(NDELAY);
468#endif
469#ifdef O_PATH
470 P_FLAG(PATH);
471#endif
472 P_FLAG(RDWR);
473#ifdef O_DSYNC
474 if ((flags & O_SYNC) == O_SYNC)
475 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", "SYNC");
476 else {
477 P_FLAG(DSYNC);
478 }
479#else
480 P_FLAG(SYNC);
481#endif
482 P_FLAG(TRUNC);
483 P_FLAG(WRONLY);
484#undef P_FLAG
485
486 if (flags)
487 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
488
489 return printed;
490}
491
492#define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags
493
Arnaldo Carvalho de Melo49af9e92013-09-12 12:18:56 -0300494static size_t syscall_arg__scnprintf_eventfd_flags(char *bf, size_t size,
495 struct syscall_arg *arg)
496{
497 int printed = 0, flags = arg->val;
498
499 if (flags == 0)
500 return scnprintf(bf, size, "NONE");
501#define P_FLAG(n) \
502 if (flags & EFD_##n) { \
503 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
504 flags &= ~EFD_##n; \
505 }
506
507 P_FLAG(SEMAPHORE);
508 P_FLAG(CLOEXEC);
509 P_FLAG(NONBLOCK);
510#undef P_FLAG
511
512 if (flags)
513 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
514
515 return printed;
516}
517
518#define SCA_EFD_FLAGS syscall_arg__scnprintf_eventfd_flags
519
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -0300520static size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscall_arg *arg)
521{
522 int sig = arg->val;
523
524 switch (sig) {
525#define P_SIGNUM(n) case SIG##n: return scnprintf(bf, size, #n)
526 P_SIGNUM(HUP);
527 P_SIGNUM(INT);
528 P_SIGNUM(QUIT);
529 P_SIGNUM(ILL);
530 P_SIGNUM(TRAP);
531 P_SIGNUM(ABRT);
532 P_SIGNUM(BUS);
533 P_SIGNUM(FPE);
534 P_SIGNUM(KILL);
535 P_SIGNUM(USR1);
536 P_SIGNUM(SEGV);
537 P_SIGNUM(USR2);
538 P_SIGNUM(PIPE);
539 P_SIGNUM(ALRM);
540 P_SIGNUM(TERM);
541 P_SIGNUM(STKFLT);
542 P_SIGNUM(CHLD);
543 P_SIGNUM(CONT);
544 P_SIGNUM(STOP);
545 P_SIGNUM(TSTP);
546 P_SIGNUM(TTIN);
547 P_SIGNUM(TTOU);
548 P_SIGNUM(URG);
549 P_SIGNUM(XCPU);
550 P_SIGNUM(XFSZ);
551 P_SIGNUM(VTALRM);
552 P_SIGNUM(PROF);
553 P_SIGNUM(WINCH);
554 P_SIGNUM(IO);
555 P_SIGNUM(PWR);
556 P_SIGNUM(SYS);
557 default: break;
558 }
559
560 return scnprintf(bf, size, "%#x", sig);
561}
562
563#define SCA_SIGNUM syscall_arg__scnprintf_signum
564
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300565#define STRARRAY(arg, name, array) \
566 .arg_scnprintf = { [arg] = SCA_STRARRAY, }, \
567 .arg_parm = { [arg] = &strarray__##array, }
568
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300569static struct syscall_fmt {
570 const char *name;
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -0300571 const char *alias;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300572 size_t (*arg_scnprintf[6])(char *bf, size_t size, struct syscall_arg *arg);
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300573 void *arg_parm[6];
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300574 bool errmsg;
575 bool timeout;
Arnaldo Carvalho de Melo04b34722013-08-26 11:36:30 -0300576 bool hexret;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300577} syscall_fmts[] = {
Arnaldo Carvalho de Melo51108992013-09-04 11:42:27 -0300578 { .name = "access", .errmsg = true,
579 .arg_scnprintf = { [1] = SCA_ACCMODE, /* mode */ }, },
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -0300580 { .name = "arch_prctl", .errmsg = true, .alias = "prctl", },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -0300581 { .name = "brk", .hexret = true,
582 .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, },
Arnaldo Carvalho de Meloa14bb862013-07-30 16:38:23 -0300583 { .name = "connect", .errmsg = true, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300584 { .name = "epoll_ctl", .errmsg = true, STRARRAY(1, op, epoll_ctl_ops), },
Arnaldo Carvalho de Melo49af9e92013-09-12 12:18:56 -0300585 { .name = "eventfd2", .errmsg = true,
586 .arg_scnprintf = { [1] = SCA_EFD_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300587 { .name = "fcntl", .errmsg = true, STRARRAY(1, cmd, fcntl_cmds), },
Arnaldo Carvalho de Melo5cea6ff2013-09-20 11:49:50 -0300588 { .name = "flock", .errmsg = true,
589 .arg_scnprintf = { [1] = SCA_FLOCK, /* cmd */ }, },
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -0300590 { .name = "fstat", .errmsg = true, .alias = "newfstat", },
591 { .name = "fstatat", .errmsg = true, .alias = "newfstatat", },
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -0300592 { .name = "futex", .errmsg = true,
593 .arg_scnprintf = { [1] = SCA_FUTEX_OP, /* op */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300594 { .name = "getitimer", .errmsg = true, STRARRAY(0, which, itimers), },
595 { .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -0300596 { .name = "ioctl", .errmsg = true,
597 .arg_scnprintf = { [2] = SCA_HEX, /* arg */ }, },
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -0300598 { .name = "kill", .errmsg = true,
599 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300600 { .name = "lseek", .errmsg = true, STRARRAY(2, whence, whences), },
Arnaldo Carvalho de Meloe5959682013-08-26 12:21:41 -0300601 { .name = "lstat", .errmsg = true, .alias = "newlstat", },
Arnaldo Carvalho de Melo9e9716d2013-08-23 10:06:41 -0300602 { .name = "madvise", .errmsg = true,
603 .arg_scnprintf = { [0] = SCA_HEX, /* start */
604 [2] = SCA_MADV_BHV, /* behavior */ }, },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -0300605 { .name = "mmap", .hexret = true,
Arnaldo Carvalho de Meloae685382013-08-20 17:44:42 -0300606 .arg_scnprintf = { [0] = SCA_HEX, /* addr */
Arnaldo Carvalho de Melo941557e2013-08-23 10:48:33 -0300607 [2] = SCA_MMAP_PROT, /* prot */
608 [3] = SCA_MMAP_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -0300609 { .name = "mprotect", .errmsg = true,
Arnaldo Carvalho de Meloae685382013-08-20 17:44:42 -0300610 .arg_scnprintf = { [0] = SCA_HEX, /* start */
611 [2] = SCA_MMAP_PROT, /* prot */ }, },
612 { .name = "mremap", .hexret = true,
613 .arg_scnprintf = { [0] = SCA_HEX, /* addr */
614 [4] = SCA_HEX, /* new_addr */ }, },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -0300615 { .name = "munmap", .errmsg = true,
616 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
Arnaldo Carvalho de Melobe65a892013-09-02 16:22:31 -0300617 { .name = "open", .errmsg = true,
618 .arg_scnprintf = { [1] = SCA_OPEN_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo31cd3852013-09-02 16:40:40 -0300619 { .name = "open_by_handle_at", .errmsg = true,
620 .arg_scnprintf = { [2] = SCA_OPEN_FLAGS, /* flags */ }, },
621 { .name = "openat", .errmsg = true,
622 .arg_scnprintf = { [2] = SCA_OPEN_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -0300623 { .name = "poll", .errmsg = true, .timeout = true, },
624 { .name = "ppoll", .errmsg = true, .timeout = true, },
Arnaldo Carvalho de Meloe5959682013-08-26 12:21:41 -0300625 { .name = "pread", .errmsg = true, .alias = "pread64", },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300626 { .name = "prlimit64", .errmsg = true, STRARRAY(1, resource, rlimit_resources), },
Arnaldo Carvalho de Meloe5959682013-08-26 12:21:41 -0300627 { .name = "pwrite", .errmsg = true, .alias = "pwrite64", },
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -0300628 { .name = "read", .errmsg = true, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -0300629 { .name = "recvfrom", .errmsg = true,
630 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
631 { .name = "recvmmsg", .errmsg = true,
632 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
633 { .name = "recvmsg", .errmsg = true,
634 .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -0300635 { .name = "rt_sigaction", .errmsg = true,
636 .arg_scnprintf = { [0] = SCA_SIGNUM, /* sig */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300637 { .name = "rt_sigprocmask", .errmsg = true, STRARRAY(0, how, sighow), },
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -0300638 { .name = "rt_sigqueueinfo", .errmsg = true,
639 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
640 { .name = "rt_tgsigqueueinfo", .errmsg = true,
641 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -0300642 { .name = "select", .errmsg = true, .timeout = true, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -0300643 { .name = "sendmmsg", .errmsg = true,
644 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
645 { .name = "sendmsg", .errmsg = true,
646 .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, },
647 { .name = "sendto", .errmsg = true,
648 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300649 { .name = "setitimer", .errmsg = true, STRARRAY(0, which, itimers), },
650 { .name = "setrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
Arnaldo Carvalho de Meloe10bce82013-09-04 10:27:41 -0300651 { .name = "socket", .errmsg = true,
Arnaldo Carvalho de Meloa28b24b2013-09-04 11:00:44 -0300652 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
653 [1] = SCA_SK_TYPE, /* type */ },
Arnaldo Carvalho de Meloe10bce82013-09-04 10:27:41 -0300654 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, },
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -0300655 { .name = "stat", .errmsg = true, .alias = "newstat", },
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -0300656 { .name = "tgkill", .errmsg = true,
657 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
658 { .name = "tkill", .errmsg = true,
659 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
Arnaldo Carvalho de Meloe5959682013-08-26 12:21:41 -0300660 { .name = "uname", .errmsg = true, .alias = "newuname", },
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300661};
662
663static int syscall_fmt__cmp(const void *name, const void *fmtp)
664{
665 const struct syscall_fmt *fmt = fmtp;
666 return strcmp(name, fmt->name);
667}
668
669static struct syscall_fmt *syscall_fmt__find(const char *name)
670{
671 const int nmemb = ARRAY_SIZE(syscall_fmts);
672 return bsearch(name, syscall_fmts, nmemb, sizeof(struct syscall_fmt), syscall_fmt__cmp);
673}
674
675struct syscall {
676 struct event_format *tp_format;
677 const char *name;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -0300678 bool filtered;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300679 struct syscall_fmt *fmt;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300680 size_t (**arg_scnprintf)(char *bf, size_t size, struct syscall_arg *arg);
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300681 void **arg_parm;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300682};
683
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -0200684static size_t fprintf_duration(unsigned long t, FILE *fp)
685{
686 double duration = (double)t / NSEC_PER_MSEC;
687 size_t printed = fprintf(fp, "(");
688
689 if (duration >= 1.0)
690 printed += color_fprintf(fp, PERF_COLOR_RED, "%6.3f ms", duration);
691 else if (duration >= 0.01)
692 printed += color_fprintf(fp, PERF_COLOR_YELLOW, "%6.3f ms", duration);
693 else
694 printed += color_fprintf(fp, PERF_COLOR_NORMAL, "%6.3f ms", duration);
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -0300695 return printed + fprintf(fp, "): ");
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -0200696}
697
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300698struct thread_trace {
699 u64 entry_time;
700 u64 exit_time;
701 bool entry_pending;
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -0300702 unsigned long nr_events;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300703 char *entry_str;
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -0300704 double runtime_ms;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300705};
706
707static struct thread_trace *thread_trace__new(void)
708{
709 return zalloc(sizeof(struct thread_trace));
710}
711
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -0300712static struct thread_trace *thread__trace(struct thread *thread, FILE *fp)
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300713{
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -0300714 struct thread_trace *ttrace;
715
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300716 if (thread == NULL)
717 goto fail;
718
719 if (thread->priv == NULL)
720 thread->priv = thread_trace__new();
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -0300721
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300722 if (thread->priv == NULL)
723 goto fail;
724
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -0300725 ttrace = thread->priv;
726 ++ttrace->nr_events;
727
728 return ttrace;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300729fail:
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -0300730 color_fprintf(fp, PERF_COLOR_RED,
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300731 "WARNING: not enough memory, dropping samples!\n");
732 return NULL;
733}
734
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300735struct trace {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -0300736 struct perf_tool tool;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300737 int audit_machine;
738 struct {
739 int max;
740 struct syscall *table;
741 } syscalls;
742 struct perf_record_opts opts;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300743 struct machine host;
744 u64 base_time;
David Ahern4bb09192013-09-04 12:37:43 -0600745 bool full_time;
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -0300746 FILE *output;
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -0300747 unsigned long nr_events;
Arnaldo Carvalho de Melob059efd2013-08-21 12:56:21 -0300748 struct strlist *ev_qualifier;
749 bool not_ev_qualifier;
David Ahernbdc89662013-08-28 22:29:53 -0600750 struct intlist *tid_list;
751 struct intlist *pid_list;
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -0300752 bool sched;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300753 bool multiple_threads;
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -0300754 bool show_comm;
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -0300755 double duration_filter;
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -0300756 double runtime_ms;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300757};
758
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -0300759static bool trace__filter_duration(struct trace *trace, double t)
760{
761 return t < (trace->duration_filter * NSEC_PER_MSEC);
762}
763
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300764static size_t trace__fprintf_tstamp(struct trace *trace, u64 tstamp, FILE *fp)
765{
766 double ts = (double)(tstamp - trace->base_time) / NSEC_PER_MSEC;
767
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -0200768 return fprintf(fp, "%10.3f ", ts);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300769}
770
Namhyung Kimf15eb532012-10-05 14:02:16 +0900771static bool done = false;
772
773static void sig_handler(int sig __maybe_unused)
774{
775 done = true;
776}
777
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300778static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thread,
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -0200779 u64 duration, u64 tstamp, FILE *fp)
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300780{
781 size_t printed = trace__fprintf_tstamp(trace, tstamp, fp);
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -0200782 printed += fprintf_duration(duration, fp);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300783
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -0300784 if (trace->multiple_threads) {
785 if (trace->show_comm)
786 printed += fprintf(fp, "%.14s/", thread->comm);
Adrian Hunter38051232013-07-04 16:20:31 +0300787 printed += fprintf(fp, "%d ", thread->tid);
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -0300788 }
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300789
790 return printed;
791}
792
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -0300793static int trace__process_event(struct trace *trace, struct machine *machine,
794 union perf_event *event)
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300795{
796 int ret = 0;
797
798 switch (event->header.type) {
799 case PERF_RECORD_LOST:
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -0300800 color_fprintf(trace->output, PERF_COLOR_RED,
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300801 "LOST %" PRIu64 " events!\n", event->lost.lost);
802 ret = machine__process_lost_event(machine, event);
803 default:
804 ret = machine__process_event(machine, event);
805 break;
806 }
807
808 return ret;
809}
810
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -0300811static int trace__tool_process(struct perf_tool *tool,
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300812 union perf_event *event,
813 struct perf_sample *sample __maybe_unused,
814 struct machine *machine)
815{
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -0300816 struct trace *trace = container_of(tool, struct trace, tool);
817 return trace__process_event(trace, machine, event);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300818}
819
820static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
821{
822 int err = symbol__init();
823
824 if (err)
825 return err;
826
827 machine__init(&trace->host, "", HOST_KERNEL_ID);
828 machine__create_kernel_maps(&trace->host);
829
830 if (perf_target__has_task(&trace->opts.target)) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -0300831 err = perf_event__synthesize_thread_map(&trace->tool, evlist->threads,
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300832 trace__tool_process,
833 &trace->host);
834 } else {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -0300835 err = perf_event__synthesize_threads(&trace->tool, trace__tool_process,
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300836 &trace->host);
837 }
838
839 if (err)
840 symbol__exit();
841
842 return err;
843}
844
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -0300845static int syscall__set_arg_fmts(struct syscall *sc)
846{
847 struct format_field *field;
848 int idx = 0;
849
850 sc->arg_scnprintf = calloc(sc->tp_format->format.nr_fields - 1, sizeof(void *));
851 if (sc->arg_scnprintf == NULL)
852 return -1;
853
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300854 if (sc->fmt)
855 sc->arg_parm = sc->fmt->arg_parm;
856
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -0300857 for (field = sc->tp_format->format.fields->next; field; field = field->next) {
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -0300858 if (sc->fmt && sc->fmt->arg_scnprintf[idx])
859 sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx];
860 else if (field->flags & FIELD_IS_POINTER)
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -0300861 sc->arg_scnprintf[idx] = syscall_arg__scnprintf_hex;
862 ++idx;
863 }
864
865 return 0;
866}
867
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300868static int trace__read_syscall_info(struct trace *trace, int id)
869{
870 char tp_name[128];
871 struct syscall *sc;
Arnaldo Carvalho de Melo3a531262012-10-20 12:39:03 -0300872 const char *name = audit_syscall_to_name(id, trace->audit_machine);
873
874 if (name == NULL)
875 return -1;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300876
877 if (id > trace->syscalls.max) {
878 struct syscall *nsyscalls = realloc(trace->syscalls.table, (id + 1) * sizeof(*sc));
879
880 if (nsyscalls == NULL)
881 return -1;
882
883 if (trace->syscalls.max != -1) {
884 memset(nsyscalls + trace->syscalls.max + 1, 0,
885 (id - trace->syscalls.max) * sizeof(*sc));
886 } else {
887 memset(nsyscalls, 0, (id + 1) * sizeof(*sc));
888 }
889
890 trace->syscalls.table = nsyscalls;
891 trace->syscalls.max = id;
892 }
893
894 sc = trace->syscalls.table + id;
Arnaldo Carvalho de Melo3a531262012-10-20 12:39:03 -0300895 sc->name = name;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -0300896
Arnaldo Carvalho de Melob059efd2013-08-21 12:56:21 -0300897 if (trace->ev_qualifier) {
898 bool in = strlist__find(trace->ev_qualifier, name) != NULL;
899
900 if (!(in ^ trace->not_ev_qualifier)) {
901 sc->filtered = true;
902 /*
903 * No need to do read tracepoint information since this will be
904 * filtered out.
905 */
906 return 0;
907 }
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -0300908 }
909
Arnaldo Carvalho de Melo3a531262012-10-20 12:39:03 -0300910 sc->fmt = syscall_fmt__find(sc->name);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300911
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -0300912 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name);
913 sc->tp_format = event_format__new("syscalls", tp_name);
914
915 if (sc->tp_format == NULL && sc->fmt && sc->fmt->alias) {
916 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->fmt->alias);
917 sc->tp_format = event_format__new("syscalls", tp_name);
918 }
919
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -0300920 if (sc->tp_format == NULL)
921 return -1;
922
923 return syscall__set_arg_fmts(sc);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300924}
925
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300926static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
927 unsigned long *args)
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300928{
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300929 size_t printed = 0;
930
931 if (sc->tp_format != NULL) {
932 struct format_field *field;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300933 u8 bit = 1;
934 struct syscall_arg arg = {
935 .idx = 0,
936 .mask = 0,
937 };
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300938
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -0300939 for (field = sc->tp_format->format.fields->next; field;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300940 field = field->next, ++arg.idx, bit <<= 1) {
941 if (arg.mask & bit)
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -0300942 continue;
Arnaldo Carvalho de Melo4aa58232013-09-20 12:19:41 -0300943 /*
944 * Suppress this argument if its value is zero and
945 * and we don't have a string associated in an
946 * strarray for it.
947 */
948 if (args[arg.idx] == 0 &&
949 !(sc->arg_scnprintf &&
950 sc->arg_scnprintf[arg.idx] == SCA_STRARRAY &&
951 sc->arg_parm[arg.idx]))
Arnaldo Carvalho de Melo22ae5cf12013-09-12 11:27:34 -0300952 continue;
953
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300954 printed += scnprintf(bf + printed, size - printed,
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -0300955 "%s%s: ", printed ? ", " : "", field->name);
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300956 if (sc->arg_scnprintf && sc->arg_scnprintf[arg.idx]) {
957 arg.val = args[arg.idx];
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300958 if (sc->arg_parm)
959 arg.parm = sc->arg_parm[arg.idx];
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300960 printed += sc->arg_scnprintf[arg.idx](bf + printed,
961 size - printed, &arg);
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -0300962 } else {
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -0300963 printed += scnprintf(bf + printed, size - printed,
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300964 "%ld", args[arg.idx]);
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -0300965 }
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300966 }
967 } else {
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300968 int i = 0;
969
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300970 while (i < 6) {
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300971 printed += scnprintf(bf + printed, size - printed,
972 "%sarg%d: %ld",
973 printed ? ", " : "", i, args[i]);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300974 ++i;
975 }
976 }
977
978 return printed;
979}
980
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -0300981typedef int (*tracepoint_handler)(struct trace *trace, struct perf_evsel *evsel,
982 struct perf_sample *sample);
983
984static struct syscall *trace__syscall_info(struct trace *trace,
985 struct perf_evsel *evsel,
986 struct perf_sample *sample)
987{
988 int id = perf_evsel__intval(evsel, sample, "id");
989
990 if (id < 0) {
Arnaldo Carvalho de Meloadaa18b2013-08-22 17:55:25 -0300991
992 /*
993 * XXX: Noticed on x86_64, reproduced as far back as 3.0.36, haven't tried
994 * before that, leaving at a higher verbosity level till that is
995 * explained. Reproduced with plain ftrace with:
996 *
997 * echo 1 > /t/events/raw_syscalls/sys_exit/enable
998 * grep "NR -1 " /t/trace_pipe
999 *
1000 * After generating some load on the machine.
1001 */
1002 if (verbose > 1) {
1003 static u64 n;
1004 fprintf(trace->output, "Invalid syscall %d id, skipping (%s, %" PRIu64 ") ...\n",
1005 id, perf_evsel__name(evsel), ++n);
1006 }
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001007 return NULL;
1008 }
1009
1010 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL) &&
1011 trace__read_syscall_info(trace, id))
1012 goto out_cant_read;
1013
1014 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL))
1015 goto out_cant_read;
1016
1017 return &trace->syscalls.table[id];
1018
1019out_cant_read:
Arnaldo Carvalho de Melo7c304ee02013-08-22 16:49:54 -03001020 if (verbose) {
1021 fprintf(trace->output, "Problems reading syscall %d", id);
1022 if (id <= trace->syscalls.max && trace->syscalls.table[id].name != NULL)
1023 fprintf(trace->output, "(%s)", trace->syscalls.table[id].name);
1024 fputs(" information\n", trace->output);
1025 }
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001026 return NULL;
1027}
1028
1029static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
1030 struct perf_sample *sample)
1031{
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001032 char *msg;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001033 void *args;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001034 size_t printed = 0;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001035 struct thread *thread;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001036 struct syscall *sc = trace__syscall_info(trace, evsel, sample);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001037 struct thread_trace *ttrace;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001038
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001039 if (sc == NULL)
1040 return -1;
1041
1042 if (sc->filtered)
1043 return 0;
1044
Adrian Hunter314add62013-08-27 11:23:03 +03001045 thread = machine__findnew_thread(&trace->host, sample->pid,
1046 sample->tid);
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001047 ttrace = thread__trace(thread, trace->output);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001048 if (ttrace == NULL)
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001049 return -1;
1050
1051 args = perf_evsel__rawptr(evsel, sample, "args");
1052 if (args == NULL) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001053 fprintf(trace->output, "Problems reading syscall arguments\n");
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001054 return -1;
1055 }
1056
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001057 ttrace = thread->priv;
1058
1059 if (ttrace->entry_str == NULL) {
1060 ttrace->entry_str = malloc(1024);
1061 if (!ttrace->entry_str)
1062 return -1;
1063 }
1064
1065 ttrace->entry_time = sample->time;
1066 msg = ttrace->entry_str;
1067 printed += scnprintf(msg + printed, 1024 - printed, "%s(", sc->name);
1068
1069 printed += syscall__scnprintf_args(sc, msg + printed, 1024 - printed, args);
1070
1071 if (!strcmp(sc->name, "exit_group") || !strcmp(sc->name, "exit")) {
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001072 if (!trace->duration_filter) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001073 trace__fprintf_entry_head(trace, thread, 1, sample->time, trace->output);
1074 fprintf(trace->output, "%-70s\n", ttrace->entry_str);
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001075 }
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001076 } else
1077 ttrace->entry_pending = true;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001078
1079 return 0;
1080}
1081
1082static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
1083 struct perf_sample *sample)
1084{
1085 int ret;
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001086 u64 duration = 0;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001087 struct thread *thread;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001088 struct syscall *sc = trace__syscall_info(trace, evsel, sample);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001089 struct thread_trace *ttrace;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001090
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001091 if (sc == NULL)
1092 return -1;
1093
1094 if (sc->filtered)
1095 return 0;
1096
Adrian Hunter314add62013-08-27 11:23:03 +03001097 thread = machine__findnew_thread(&trace->host, sample->pid,
1098 sample->tid);
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001099 ttrace = thread__trace(thread, trace->output);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001100 if (ttrace == NULL)
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001101 return -1;
1102
1103 ret = perf_evsel__intval(evsel, sample, "ret");
1104
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001105 ttrace = thread->priv;
1106
1107 ttrace->exit_time = sample->time;
1108
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001109 if (ttrace->entry_time) {
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001110 duration = sample->time - ttrace->entry_time;
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001111 if (trace__filter_duration(trace, duration))
1112 goto out;
1113 } else if (trace->duration_filter)
1114 goto out;
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001115
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001116 trace__fprintf_entry_head(trace, thread, duration, sample->time, trace->output);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001117
1118 if (ttrace->entry_pending) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001119 fprintf(trace->output, "%-70s", ttrace->entry_str);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001120 } else {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001121 fprintf(trace->output, " ... [");
1122 color_fprintf(trace->output, PERF_COLOR_YELLOW, "continued");
1123 fprintf(trace->output, "]: %s()", sc->name);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001124 }
1125
Arnaldo Carvalho de Meloda3c9a42013-08-26 11:28:34 -03001126 if (sc->fmt == NULL) {
1127signed_print:
1128 fprintf(trace->output, ") = %d", ret);
1129 } else if (ret < 0 && sc->fmt->errmsg) {
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001130 char bf[256];
1131 const char *emsg = strerror_r(-ret, bf, sizeof(bf)),
1132 *e = audit_errno_to_name(-ret);
1133
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001134 fprintf(trace->output, ") = -1 %s %s", e, emsg);
Arnaldo Carvalho de Meloda3c9a42013-08-26 11:28:34 -03001135 } else if (ret == 0 && sc->fmt->timeout)
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001136 fprintf(trace->output, ") = 0 Timeout");
Arnaldo Carvalho de Melo04b34722013-08-26 11:36:30 -03001137 else if (sc->fmt->hexret)
1138 fprintf(trace->output, ") = %#x", ret);
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001139 else
Arnaldo Carvalho de Meloda3c9a42013-08-26 11:28:34 -03001140 goto signed_print;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001141
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001142 fputc('\n', trace->output);
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001143out:
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001144 ttrace->entry_pending = false;
1145
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001146 return 0;
1147}
1148
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001149static int trace__sched_stat_runtime(struct trace *trace, struct perf_evsel *evsel,
1150 struct perf_sample *sample)
1151{
1152 u64 runtime = perf_evsel__intval(evsel, sample, "runtime");
1153 double runtime_ms = (double)runtime / NSEC_PER_MSEC;
Adrian Hunter314add62013-08-27 11:23:03 +03001154 struct thread *thread = machine__findnew_thread(&trace->host,
1155 sample->pid,
1156 sample->tid);
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001157 struct thread_trace *ttrace = thread__trace(thread, trace->output);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001158
1159 if (ttrace == NULL)
1160 goto out_dump;
1161
1162 ttrace->runtime_ms += runtime_ms;
1163 trace->runtime_ms += runtime_ms;
1164 return 0;
1165
1166out_dump:
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001167 fprintf(trace->output, "%s: comm=%s,pid=%u,runtime=%" PRIu64 ",vruntime=%" PRIu64 ")\n",
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001168 evsel->name,
1169 perf_evsel__strval(evsel, sample, "comm"),
1170 (pid_t)perf_evsel__intval(evsel, sample, "pid"),
1171 runtime,
1172 perf_evsel__intval(evsel, sample, "vruntime"));
1173 return 0;
1174}
1175
David Ahernbdc89662013-08-28 22:29:53 -06001176static bool skip_sample(struct trace *trace, struct perf_sample *sample)
1177{
1178 if ((trace->pid_list && intlist__find(trace->pid_list, sample->pid)) ||
1179 (trace->tid_list && intlist__find(trace->tid_list, sample->tid)))
1180 return false;
1181
1182 if (trace->pid_list || trace->tid_list)
1183 return true;
1184
1185 return false;
1186}
1187
David Ahern6810fc92013-08-28 22:29:52 -06001188static int trace__process_sample(struct perf_tool *tool,
1189 union perf_event *event __maybe_unused,
1190 struct perf_sample *sample,
1191 struct perf_evsel *evsel,
1192 struct machine *machine __maybe_unused)
1193{
1194 struct trace *trace = container_of(tool, struct trace, tool);
1195 int err = 0;
1196
1197 tracepoint_handler handler = evsel->handler.func;
1198
David Ahernbdc89662013-08-28 22:29:53 -06001199 if (skip_sample(trace, sample))
1200 return 0;
1201
David Ahern4bb09192013-09-04 12:37:43 -06001202 if (!trace->full_time && trace->base_time == 0)
David Ahern6810fc92013-08-28 22:29:52 -06001203 trace->base_time = sample->time;
1204
1205 if (handler)
1206 handler(trace, evsel, sample);
1207
1208 return err;
1209}
1210
1211static bool
1212perf_session__has_tp(struct perf_session *session, const char *name)
1213{
1214 struct perf_evsel *evsel;
1215
1216 evsel = perf_evlist__find_tracepoint_by_name(session->evlist, name);
1217
1218 return evsel != NULL;
1219}
1220
David Ahernbdc89662013-08-28 22:29:53 -06001221static int parse_target_str(struct trace *trace)
1222{
1223 if (trace->opts.target.pid) {
1224 trace->pid_list = intlist__new(trace->opts.target.pid);
1225 if (trace->pid_list == NULL) {
1226 pr_err("Error parsing process id string\n");
1227 return -EINVAL;
1228 }
1229 }
1230
1231 if (trace->opts.target.tid) {
1232 trace->tid_list = intlist__new(trace->opts.target.tid);
1233 if (trace->tid_list == NULL) {
1234 pr_err("Error parsing thread id string\n");
1235 return -EINVAL;
1236 }
1237 }
1238
1239 return 0;
1240}
1241
Namhyung Kimf15eb532012-10-05 14:02:16 +09001242static int trace__run(struct trace *trace, int argc, const char **argv)
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001243{
Namhyung Kim334fe7a2013-03-11 16:43:12 +09001244 struct perf_evlist *evlist = perf_evlist__new();
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001245 struct perf_evsel *evsel;
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03001246 int err = -1, i;
1247 unsigned long before;
Namhyung Kimf15eb532012-10-05 14:02:16 +09001248 const bool forks = argc > 0;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001249
1250 if (evlist == NULL) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001251 fprintf(trace->output, "Not enough memory to run!\n");
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001252 goto out;
1253 }
1254
Arnaldo Carvalho de Melo39876e72012-10-03 11:40:22 -03001255 if (perf_evlist__add_newtp(evlist, "raw_syscalls", "sys_enter", trace__sys_enter) ||
1256 perf_evlist__add_newtp(evlist, "raw_syscalls", "sys_exit", trace__sys_exit)) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001257 fprintf(trace->output, "Couldn't read the raw_syscalls tracepoints information!\n");
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001258 goto out_delete_evlist;
1259 }
1260
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001261 if (trace->sched &&
1262 perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime",
1263 trace__sched_stat_runtime)) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001264 fprintf(trace->output, "Couldn't read the sched_stat_runtime tracepoint information!\n");
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001265 goto out_delete_evlist;
1266 }
1267
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001268 err = perf_evlist__create_maps(evlist, &trace->opts.target);
1269 if (err < 0) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001270 fprintf(trace->output, "Problems parsing the target to trace, check your options!\n");
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001271 goto out_delete_evlist;
1272 }
1273
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001274 err = trace__symbols_init(trace, evlist);
1275 if (err < 0) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001276 fprintf(trace->output, "Problems initializing symbol libraries!\n");
Namhyung Kim3beb0862013-03-15 14:48:50 +09001277 goto out_delete_maps;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001278 }
1279
Arnaldo Carvalho de Melof77a9512012-12-10 16:41:31 -03001280 perf_evlist__config(evlist, &trace->opts);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001281
Namhyung Kimf15eb532012-10-05 14:02:16 +09001282 signal(SIGCHLD, sig_handler);
1283 signal(SIGINT, sig_handler);
1284
1285 if (forks) {
Namhyung Kim6ef73ec2013-03-11 16:43:15 +09001286 err = perf_evlist__prepare_workload(evlist, &trace->opts.target,
Namhyung Kim55e162e2013-03-11 16:43:17 +09001287 argv, false, false);
Namhyung Kimf15eb532012-10-05 14:02:16 +09001288 if (err < 0) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001289 fprintf(trace->output, "Couldn't run the workload!\n");
Namhyung Kim3beb0862013-03-15 14:48:50 +09001290 goto out_delete_maps;
Namhyung Kimf15eb532012-10-05 14:02:16 +09001291 }
1292 }
1293
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001294 err = perf_evlist__open(evlist);
1295 if (err < 0) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001296 fprintf(trace->output, "Couldn't create the events: %s\n", strerror(errno));
Namhyung Kim3beb0862013-03-15 14:48:50 +09001297 goto out_delete_maps;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001298 }
1299
1300 err = perf_evlist__mmap(evlist, UINT_MAX, false);
1301 if (err < 0) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001302 fprintf(trace->output, "Couldn't mmap the events: %s\n", strerror(errno));
Namhyung Kim3beb0862013-03-15 14:48:50 +09001303 goto out_close_evlist;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001304 }
1305
1306 perf_evlist__enable(evlist);
Namhyung Kimf15eb532012-10-05 14:02:16 +09001307
1308 if (forks)
1309 perf_evlist__start_workload(evlist);
1310
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001311 trace->multiple_threads = evlist->threads->map[0] == -1 || evlist->threads->nr > 1;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001312again:
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03001313 before = trace->nr_events;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001314
1315 for (i = 0; i < evlist->nr_mmaps; i++) {
1316 union perf_event *event;
1317
1318 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
1319 const u32 type = event->header.type;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001320 tracepoint_handler handler;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001321 struct perf_sample sample;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001322
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03001323 ++trace->nr_events;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001324
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001325 err = perf_evlist__parse_sample(evlist, event, &sample);
1326 if (err) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001327 fprintf(trace->output, "Can't parse sample, err = %d, skipping...\n", err);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001328 continue;
1329 }
1330
David Ahern4bb09192013-09-04 12:37:43 -06001331 if (!trace->full_time && trace->base_time == 0)
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001332 trace->base_time = sample.time;
1333
1334 if (type != PERF_RECORD_SAMPLE) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001335 trace__process_event(trace, &trace->host, event);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001336 continue;
1337 }
1338
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001339 evsel = perf_evlist__id2evsel(evlist, sample.id);
1340 if (evsel == NULL) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001341 fprintf(trace->output, "Unknown tp ID %" PRIu64 ", skipping...\n", sample.id);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001342 continue;
1343 }
1344
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001345 if (sample.raw_data == NULL) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001346 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 -03001347 perf_evsel__name(evsel), sample.tid,
1348 sample.cpu, sample.raw_size);
1349 continue;
1350 }
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001351
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001352 handler = evsel->handler.func;
1353 handler(trace, evsel, &sample);
Arnaldo Carvalho de Melo20c5f102013-09-03 11:55:07 -03001354
1355 if (done)
1356 goto out_unmap_evlist;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001357 }
1358 }
1359
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03001360 if (trace->nr_events == before) {
Namhyung Kimf15eb532012-10-05 14:02:16 +09001361 if (done)
Namhyung Kim3beb0862013-03-15 14:48:50 +09001362 goto out_unmap_evlist;
Namhyung Kimf15eb532012-10-05 14:02:16 +09001363
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001364 poll(evlist->pollfd, evlist->nr_fds, -1);
Namhyung Kimf15eb532012-10-05 14:02:16 +09001365 }
1366
1367 if (done)
1368 perf_evlist__disable(evlist);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001369
1370 goto again;
1371
Namhyung Kim3beb0862013-03-15 14:48:50 +09001372out_unmap_evlist:
1373 perf_evlist__munmap(evlist);
1374out_close_evlist:
1375 perf_evlist__close(evlist);
1376out_delete_maps:
1377 perf_evlist__delete_maps(evlist);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001378out_delete_evlist:
1379 perf_evlist__delete(evlist);
1380out:
1381 return err;
1382}
1383
David Ahern6810fc92013-08-28 22:29:52 -06001384static int trace__replay(struct trace *trace)
1385{
1386 const struct perf_evsel_str_handler handlers[] = {
1387 { "raw_syscalls:sys_enter", trace__sys_enter, },
1388 { "raw_syscalls:sys_exit", trace__sys_exit, },
1389 };
1390
1391 struct perf_session *session;
1392 int err = -1;
1393
1394 trace->tool.sample = trace__process_sample;
1395 trace->tool.mmap = perf_event__process_mmap;
David Ahern384c6712013-09-22 19:44:58 -06001396 trace->tool.mmap2 = perf_event__process_mmap2;
David Ahern6810fc92013-08-28 22:29:52 -06001397 trace->tool.comm = perf_event__process_comm;
1398 trace->tool.exit = perf_event__process_exit;
1399 trace->tool.fork = perf_event__process_fork;
1400 trace->tool.attr = perf_event__process_attr;
1401 trace->tool.tracing_data = perf_event__process_tracing_data;
1402 trace->tool.build_id = perf_event__process_build_id;
1403
1404 trace->tool.ordered_samples = true;
1405 trace->tool.ordering_requires_timestamps = true;
1406
1407 /* add tid to output */
1408 trace->multiple_threads = true;
1409
1410 if (symbol__init() < 0)
1411 return -1;
1412
1413 session = perf_session__new(input_name, O_RDONLY, 0, false,
1414 &trace->tool);
1415 if (session == NULL)
1416 return -ENOMEM;
1417
1418 err = perf_session__set_tracepoints_handlers(session, handlers);
1419 if (err)
1420 goto out;
1421
1422 if (!perf_session__has_tp(session, "raw_syscalls:sys_enter")) {
1423 pr_err("Data file does not have raw_syscalls:sys_enter events\n");
1424 goto out;
1425 }
1426
1427 if (!perf_session__has_tp(session, "raw_syscalls:sys_exit")) {
1428 pr_err("Data file does not have raw_syscalls:sys_exit events\n");
1429 goto out;
1430 }
1431
David Ahernbdc89662013-08-28 22:29:53 -06001432 err = parse_target_str(trace);
1433 if (err != 0)
1434 goto out;
1435
David Ahern6810fc92013-08-28 22:29:52 -06001436 setup_pager();
1437
1438 err = perf_session__process_events(session, &trace->tool);
1439 if (err)
1440 pr_err("Failed to process events, error %d", err);
1441
1442out:
1443 perf_session__delete(session);
1444
1445 return err;
1446}
1447
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001448static size_t trace__fprintf_threads_header(FILE *fp)
1449{
1450 size_t printed;
1451
1452 printed = fprintf(fp, "\n _____________________________________________________________________\n");
1453 printed += fprintf(fp," __) Summary of events (__\n\n");
1454 printed += fprintf(fp," [ task - pid ] [ events ] [ ratio ] [ runtime ]\n");
1455 printed += fprintf(fp," _____________________________________________________________________\n\n");
1456
1457 return printed;
1458}
1459
1460static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp)
1461{
1462 size_t printed = trace__fprintf_threads_header(fp);
1463 struct rb_node *nd;
1464
1465 for (nd = rb_first(&trace->host.threads); nd; nd = rb_next(nd)) {
1466 struct thread *thread = rb_entry(nd, struct thread, rb_node);
1467 struct thread_trace *ttrace = thread->priv;
1468 const char *color;
1469 double ratio;
1470
1471 if (ttrace == NULL)
1472 continue;
1473
1474 ratio = (double)ttrace->nr_events / trace->nr_events * 100.0;
1475
1476 color = PERF_COLOR_NORMAL;
1477 if (ratio > 50.0)
1478 color = PERF_COLOR_RED;
1479 else if (ratio > 25.0)
1480 color = PERF_COLOR_GREEN;
1481 else if (ratio > 5.0)
1482 color = PERF_COLOR_YELLOW;
1483
1484 printed += color_fprintf(fp, color, "%20s", thread->comm);
Adrian Hunter38051232013-07-04 16:20:31 +03001485 printed += fprintf(fp, " - %-5d :%11lu [", thread->tid, ttrace->nr_events);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001486 printed += color_fprintf(fp, color, "%5.1f%%", ratio);
1487 printed += fprintf(fp, " ] %10.3f ms\n", ttrace->runtime_ms);
1488 }
1489
1490 return printed;
1491}
1492
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001493static int trace__set_duration(const struct option *opt, const char *str,
1494 int unset __maybe_unused)
1495{
1496 struct trace *trace = opt->value;
1497
1498 trace->duration_filter = atof(str);
1499 return 0;
1500}
1501
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001502static int trace__open_output(struct trace *trace, const char *filename)
1503{
1504 struct stat st;
1505
1506 if (!stat(filename, &st) && st.st_size) {
1507 char oldname[PATH_MAX];
1508
1509 scnprintf(oldname, sizeof(oldname), "%s.old", filename);
1510 unlink(oldname);
1511 rename(filename, oldname);
1512 }
1513
1514 trace->output = fopen(filename, "w");
1515
1516 return trace->output == NULL ? -errno : 0;
1517}
1518
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001519int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
1520{
1521 const char * const trace_usage[] = {
Namhyung Kimf15eb532012-10-05 14:02:16 +09001522 "perf trace [<options>] [<command>]",
1523 "perf trace [<options>] -- <command> [<options>]",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001524 NULL
1525 };
1526 struct trace trace = {
1527 .audit_machine = audit_detect_machine(),
1528 .syscalls = {
1529 . max = -1,
1530 },
1531 .opts = {
1532 .target = {
1533 .uid = UINT_MAX,
1534 .uses_mmap = true,
1535 },
1536 .user_freq = UINT_MAX,
1537 .user_interval = ULLONG_MAX,
1538 .no_delay = true,
1539 .mmap_pages = 1024,
1540 },
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001541 .output = stdout,
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -03001542 .show_comm = true,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001543 };
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001544 const char *output_name = NULL;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001545 const char *ev_qualifier_str = NULL;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001546 const struct option trace_options[] = {
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -03001547 OPT_BOOLEAN(0, "comm", &trace.show_comm,
1548 "show the thread COMM next to its id"),
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001549 OPT_STRING('e', "expr", &ev_qualifier_str, "expr",
1550 "list of events to trace"),
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001551 OPT_STRING('o', "output", &output_name, "file", "output file name"),
David Ahern6810fc92013-08-28 22:29:52 -06001552 OPT_STRING('i', "input", &input_name, "file", "Analyze events in file"),
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001553 OPT_STRING('p', "pid", &trace.opts.target.pid, "pid",
1554 "trace events on existing process id"),
David Ahernac9be8e2013-08-20 11:15:45 -06001555 OPT_STRING('t', "tid", &trace.opts.target.tid, "tid",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001556 "trace events on existing thread id"),
David Ahernac9be8e2013-08-20 11:15:45 -06001557 OPT_BOOLEAN('a', "all-cpus", &trace.opts.target.system_wide,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001558 "system-wide collection from all CPUs"),
David Ahernac9be8e2013-08-20 11:15:45 -06001559 OPT_STRING('C', "cpu", &trace.opts.target.cpu_list, "cpu",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001560 "list of cpus to monitor"),
David Ahern6810fc92013-08-28 22:29:52 -06001561 OPT_BOOLEAN(0, "no-inherit", &trace.opts.no_inherit,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001562 "child tasks do not inherit counters"),
Jiri Olsa994a1f72013-09-01 12:36:12 +02001563 OPT_CALLBACK('m', "mmap-pages", &trace.opts.mmap_pages, "pages",
1564 "number of mmap data pages",
1565 perf_evlist__parse_mmap_pages),
David Ahernac9be8e2013-08-20 11:15:45 -06001566 OPT_STRING('u', "uid", &trace.opts.target.uid_str, "user",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001567 "user to profile"),
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001568 OPT_CALLBACK(0, "duration", &trace, "float",
1569 "show only events with duration > N.M ms",
1570 trace__set_duration),
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001571 OPT_BOOLEAN(0, "sched", &trace.sched, "show blocking scheduler events"),
Arnaldo Carvalho de Melo7c304ee02013-08-22 16:49:54 -03001572 OPT_INCR('v', "verbose", &verbose, "be more verbose"),
David Ahern4bb09192013-09-04 12:37:43 -06001573 OPT_BOOLEAN('T', "time", &trace.full_time,
1574 "Show full timestamp, not time relative to first start"),
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001575 OPT_END()
1576 };
1577 int err;
Namhyung Kim32caf0d2012-10-05 14:02:13 +09001578 char bf[BUFSIZ];
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001579
1580 argc = parse_options(argc, argv, trace_options, trace_usage, 0);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001581
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001582 if (output_name != NULL) {
1583 err = trace__open_output(&trace, output_name);
1584 if (err < 0) {
1585 perror("failed to create output file");
1586 goto out;
1587 }
1588 }
1589
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001590 if (ev_qualifier_str != NULL) {
Arnaldo Carvalho de Melob059efd2013-08-21 12:56:21 -03001591 const char *s = ev_qualifier_str;
1592
1593 trace.not_ev_qualifier = *s == '!';
1594 if (trace.not_ev_qualifier)
1595 ++s;
1596 trace.ev_qualifier = strlist__new(true, s);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001597 if (trace.ev_qualifier == NULL) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001598 fputs("Not enough memory to parse event qualifier",
1599 trace.output);
1600 err = -ENOMEM;
1601 goto out_close;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001602 }
1603 }
1604
Namhyung Kim32caf0d2012-10-05 14:02:13 +09001605 err = perf_target__validate(&trace.opts.target);
1606 if (err) {
1607 perf_target__strerror(&trace.opts.target, err, bf, sizeof(bf));
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001608 fprintf(trace.output, "%s", bf);
1609 goto out_close;
Namhyung Kim32caf0d2012-10-05 14:02:13 +09001610 }
1611
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001612 err = perf_target__parse_uid(&trace.opts.target);
1613 if (err) {
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001614 perf_target__strerror(&trace.opts.target, err, bf, sizeof(bf));
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001615 fprintf(trace.output, "%s", bf);
1616 goto out_close;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001617 }
1618
Namhyung Kimf15eb532012-10-05 14:02:16 +09001619 if (!argc && perf_target__none(&trace.opts.target))
Namhyung Kimee761202012-10-05 14:02:14 +09001620 trace.opts.target.system_wide = true;
1621
David Ahern6810fc92013-08-28 22:29:52 -06001622 if (input_name)
1623 err = trace__replay(&trace);
1624 else
1625 err = trace__run(&trace, argc, argv);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001626
1627 if (trace.sched && !err)
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001628 trace__fprintf_thread_summary(&trace, trace.output);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001629
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001630out_close:
1631 if (output_name != NULL)
1632 fclose(trace.output);
1633out:
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001634 return err;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001635}