]> Git Repo - linux.git/blame - tools/perf/builtin-trace.c
perf strlist: Make parse_list() private
[linux.git] / tools / perf / builtin-trace.c
CommitLineData
4e319027 1#include <traceevent/event-parse.h>
514f1c67 2#include "builtin.h"
752fde44 3#include "util/color.h"
7c304ee0 4#include "util/debug.h"
514f1c67 5#include "util/evlist.h"
752fde44 6#include "util/machine.h"
6810fc91 7#include "util/session.h"
752fde44 8#include "util/thread.h"
514f1c67 9#include "util/parse-options.h"
2ae3a312 10#include "util/strlist.h"
bdc89661 11#include "util/intlist.h"
514f1c67 12#include "util/thread_map.h"
bf2575c1 13#include "util/stat.h"
97978b3e 14#include "trace-event.h"
9aca7f17 15#include "util/parse-events.h"
514f1c67
ACM
16
17#include <libaudit.h>
18#include <stdlib.h>
ae685380 19#include <sys/mman.h>
f9da0b0c 20#include <linux/futex.h>
514f1c67 21
456857bd
IM
22/* For older distros: */
23#ifndef MAP_STACK
24# define MAP_STACK 0x20000
25#endif
26
27#ifndef MADV_HWPOISON
28# define MADV_HWPOISON 100
29#endif
30
31#ifndef MADV_MERGEABLE
32# define MADV_MERGEABLE 12
33#endif
34
35#ifndef MADV_UNMERGEABLE
36# define MADV_UNMERGEABLE 13
37#endif
38
79d26a6a
BH
39#ifndef EFD_SEMAPHORE
40# define EFD_SEMAPHORE 1
41#endif
42
c188e7ac
ACM
43#ifndef EFD_NONBLOCK
44# define EFD_NONBLOCK 00004000
45#endif
46
47#ifndef EFD_CLOEXEC
48# define EFD_CLOEXEC 02000000
49#endif
50
51#ifndef O_CLOEXEC
52# define O_CLOEXEC 02000000
53#endif
54
55#ifndef SOCK_DCCP
56# define SOCK_DCCP 6
57#endif
58
59#ifndef SOCK_CLOEXEC
60# define SOCK_CLOEXEC 02000000
61#endif
62
63#ifndef SOCK_NONBLOCK
64# define SOCK_NONBLOCK 00004000
65#endif
66
67#ifndef MSG_CMSG_CLOEXEC
68# define MSG_CMSG_CLOEXEC 0x40000000
69#endif
70
a1c2552d
ACM
71#ifndef PERF_FLAG_FD_NO_GROUP
72# define PERF_FLAG_FD_NO_GROUP (1UL << 0)
73#endif
74
75#ifndef PERF_FLAG_FD_OUTPUT
76# define PERF_FLAG_FD_OUTPUT (1UL << 1)
77#endif
78
79#ifndef PERF_FLAG_PID_CGROUP
80# define PERF_FLAG_PID_CGROUP (1UL << 2) /* pid=cgroup id, per-cpu mode only */
81#endif
82
83#ifndef PERF_FLAG_FD_CLOEXEC
84# define PERF_FLAG_FD_CLOEXEC (1UL << 3) /* O_CLOEXEC */
85#endif
86
87
77170988
ACM
88struct tp_field {
89 int offset;
90 union {
91 u64 (*integer)(struct tp_field *field, struct perf_sample *sample);
92 void *(*pointer)(struct tp_field *field, struct perf_sample *sample);
93 };
94};
95
96#define TP_UINT_FIELD(bits) \
97static u64 tp_field__u##bits(struct tp_field *field, struct perf_sample *sample) \
98{ \
55d43bca
DA
99 u##bits value; \
100 memcpy(&value, sample->raw_data + field->offset, sizeof(value)); \
101 return value; \
77170988
ACM
102}
103
104TP_UINT_FIELD(8);
105TP_UINT_FIELD(16);
106TP_UINT_FIELD(32);
107TP_UINT_FIELD(64);
108
109#define TP_UINT_FIELD__SWAPPED(bits) \
110static u64 tp_field__swapped_u##bits(struct tp_field *field, struct perf_sample *sample) \
111{ \
55d43bca
DA
112 u##bits value; \
113 memcpy(&value, sample->raw_data + field->offset, sizeof(value)); \
77170988
ACM
114 return bswap_##bits(value);\
115}
116
117TP_UINT_FIELD__SWAPPED(16);
118TP_UINT_FIELD__SWAPPED(32);
119TP_UINT_FIELD__SWAPPED(64);
120
121static int tp_field__init_uint(struct tp_field *field,
122 struct format_field *format_field,
123 bool needs_swap)
124{
125 field->offset = format_field->offset;
126
127 switch (format_field->size) {
128 case 1:
129 field->integer = tp_field__u8;
130 break;
131 case 2:
132 field->integer = needs_swap ? tp_field__swapped_u16 : tp_field__u16;
133 break;
134 case 4:
135 field->integer = needs_swap ? tp_field__swapped_u32 : tp_field__u32;
136 break;
137 case 8:
138 field->integer = needs_swap ? tp_field__swapped_u64 : tp_field__u64;
139 break;
140 default:
141 return -1;
142 }
143
144 return 0;
145}
146
147static void *tp_field__ptr(struct tp_field *field, struct perf_sample *sample)
148{
149 return sample->raw_data + field->offset;
150}
151
152static int tp_field__init_ptr(struct tp_field *field, struct format_field *format_field)
153{
154 field->offset = format_field->offset;
155 field->pointer = tp_field__ptr;
156 return 0;
157}
158
159struct syscall_tp {
160 struct tp_field id;
161 union {
162 struct tp_field args, ret;
163 };
164};
165
166static int perf_evsel__init_tp_uint_field(struct perf_evsel *evsel,
167 struct tp_field *field,
168 const char *name)
169{
170 struct format_field *format_field = perf_evsel__field(evsel, name);
171
172 if (format_field == NULL)
173 return -1;
174
175 return tp_field__init_uint(field, format_field, evsel->needs_swap);
176}
177
178#define perf_evsel__init_sc_tp_uint_field(evsel, name) \
179 ({ struct syscall_tp *sc = evsel->priv;\
180 perf_evsel__init_tp_uint_field(evsel, &sc->name, #name); })
181
182static int perf_evsel__init_tp_ptr_field(struct perf_evsel *evsel,
183 struct tp_field *field,
184 const char *name)
185{
186 struct format_field *format_field = perf_evsel__field(evsel, name);
187
188 if (format_field == NULL)
189 return -1;
190
191 return tp_field__init_ptr(field, format_field);
192}
193
194#define perf_evsel__init_sc_tp_ptr_field(evsel, name) \
195 ({ struct syscall_tp *sc = evsel->priv;\
196 perf_evsel__init_tp_ptr_field(evsel, &sc->name, #name); })
197
198static void perf_evsel__delete_priv(struct perf_evsel *evsel)
199{
04662523 200 zfree(&evsel->priv);
77170988
ACM
201 perf_evsel__delete(evsel);
202}
203
96695d44
NK
204static int perf_evsel__init_syscall_tp(struct perf_evsel *evsel, void *handler)
205{
206 evsel->priv = malloc(sizeof(struct syscall_tp));
207 if (evsel->priv != NULL) {
208 if (perf_evsel__init_sc_tp_uint_field(evsel, id))
209 goto out_delete;
210
211 evsel->handler = handler;
212 return 0;
213 }
214
215 return -ENOMEM;
216
217out_delete:
04662523 218 zfree(&evsel->priv);
96695d44
NK
219 return -ENOENT;
220}
221
ef503831 222static struct perf_evsel *perf_evsel__syscall_newtp(const char *direction, void *handler)
77170988 223{
ef503831 224 struct perf_evsel *evsel = perf_evsel__newtp("raw_syscalls", direction);
77170988 225
9aca7f17
DA
226 /* older kernel (e.g., RHEL6) use syscalls:{enter,exit} */
227 if (evsel == NULL)
228 evsel = perf_evsel__newtp("syscalls", direction);
229
77170988 230 if (evsel) {
96695d44 231 if (perf_evsel__init_syscall_tp(evsel, handler))
77170988 232 goto out_delete;
77170988
ACM
233 }
234
235 return evsel;
236
237out_delete:
238 perf_evsel__delete_priv(evsel);
239 return NULL;
240}
241
242#define perf_evsel__sc_tp_uint(evsel, name, sample) \
243 ({ struct syscall_tp *fields = evsel->priv; \
244 fields->name.integer(&fields->name, sample); })
245
246#define perf_evsel__sc_tp_ptr(evsel, name, sample) \
247 ({ struct syscall_tp *fields = evsel->priv; \
248 fields->name.pointer(&fields->name, sample); })
249
01533e97
ACM
250struct syscall_arg {
251 unsigned long val;
75b757ca
ACM
252 struct thread *thread;
253 struct trace *trace;
1f115cb7 254 void *parm;
01533e97
ACM
255 u8 idx;
256 u8 mask;
257};
258
1f115cb7 259struct strarray {
03e3adc9 260 int offset;
1f115cb7
ACM
261 int nr_entries;
262 const char **entries;
263};
264
265#define DEFINE_STRARRAY(array) struct strarray strarray__##array = { \
266 .nr_entries = ARRAY_SIZE(array), \
267 .entries = array, \
268}
269
03e3adc9
ACM
270#define DEFINE_STRARRAY_OFFSET(array, off) struct strarray strarray__##array = { \
271 .offset = off, \
272 .nr_entries = ARRAY_SIZE(array), \
273 .entries = array, \
274}
275
975b7c2f
ACM
276static size_t __syscall_arg__scnprintf_strarray(char *bf, size_t size,
277 const char *intfmt,
278 struct syscall_arg *arg)
1f115cb7 279{
1f115cb7 280 struct strarray *sa = arg->parm;
03e3adc9 281 int idx = arg->val - sa->offset;
1f115cb7
ACM
282
283 if (idx < 0 || idx >= sa->nr_entries)
975b7c2f 284 return scnprintf(bf, size, intfmt, arg->val);
1f115cb7
ACM
285
286 return scnprintf(bf, size, "%s", sa->entries[idx]);
287}
288
975b7c2f
ACM
289static size_t syscall_arg__scnprintf_strarray(char *bf, size_t size,
290 struct syscall_arg *arg)
291{
292 return __syscall_arg__scnprintf_strarray(bf, size, "%d", arg);
293}
294
1f115cb7
ACM
295#define SCA_STRARRAY syscall_arg__scnprintf_strarray
296
844ae5b4
ACM
297#if defined(__i386__) || defined(__x86_64__)
298/*
299 * FIXME: Make this available to all arches as soon as the ioctl beautifier
300 * gets rewritten to support all arches.
301 */
78645cf3
ACM
302static size_t syscall_arg__scnprintf_strhexarray(char *bf, size_t size,
303 struct syscall_arg *arg)
304{
305 return __syscall_arg__scnprintf_strarray(bf, size, "%#x", arg);
306}
307
308#define SCA_STRHEXARRAY syscall_arg__scnprintf_strhexarray
844ae5b4 309#endif /* defined(__i386__) || defined(__x86_64__) */
78645cf3 310
75b757ca
ACM
311static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
312 struct syscall_arg *arg);
313
314#define SCA_FD syscall_arg__scnprintf_fd
315
316static size_t syscall_arg__scnprintf_fd_at(char *bf, size_t size,
317 struct syscall_arg *arg)
318{
319 int fd = arg->val;
320
321 if (fd == AT_FDCWD)
322 return scnprintf(bf, size, "CWD");
323
324 return syscall_arg__scnprintf_fd(bf, size, arg);
325}
326
327#define SCA_FDAT syscall_arg__scnprintf_fd_at
328
329static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
330 struct syscall_arg *arg);
331
332#define SCA_CLOSE_FD syscall_arg__scnprintf_close_fd
333
6e7eeb51 334static size_t syscall_arg__scnprintf_hex(char *bf, size_t size,
01533e97 335 struct syscall_arg *arg)
13d4ff3e 336{
01533e97 337 return scnprintf(bf, size, "%#lx", arg->val);
13d4ff3e
ACM
338}
339
beccb2b5
ACM
340#define SCA_HEX syscall_arg__scnprintf_hex
341
a1c2552d
ACM
342static size_t syscall_arg__scnprintf_int(char *bf, size_t size,
343 struct syscall_arg *arg)
344{
345 return scnprintf(bf, size, "%d", arg->val);
346}
347
348#define SCA_INT syscall_arg__scnprintf_int
349
6e7eeb51 350static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size,
01533e97 351 struct syscall_arg *arg)
ae685380 352{
01533e97 353 int printed = 0, prot = arg->val;
ae685380
ACM
354
355 if (prot == PROT_NONE)
356 return scnprintf(bf, size, "NONE");
357#define P_MMAP_PROT(n) \
358 if (prot & PROT_##n) { \
359 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
360 prot &= ~PROT_##n; \
361 }
362
363 P_MMAP_PROT(EXEC);
364 P_MMAP_PROT(READ);
365 P_MMAP_PROT(WRITE);
366#ifdef PROT_SEM
367 P_MMAP_PROT(SEM);
368#endif
369 P_MMAP_PROT(GROWSDOWN);
370 P_MMAP_PROT(GROWSUP);
371#undef P_MMAP_PROT
372
373 if (prot)
374 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", prot);
375
376 return printed;
377}
378
379#define SCA_MMAP_PROT syscall_arg__scnprintf_mmap_prot
380
6e7eeb51 381static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size,
01533e97 382 struct syscall_arg *arg)
941557e0 383{
01533e97 384 int printed = 0, flags = arg->val;
941557e0
ACM
385
386#define P_MMAP_FLAG(n) \
387 if (flags & MAP_##n) { \
388 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
389 flags &= ~MAP_##n; \
390 }
391
392 P_MMAP_FLAG(SHARED);
393 P_MMAP_FLAG(PRIVATE);
41817815 394#ifdef MAP_32BIT
941557e0 395 P_MMAP_FLAG(32BIT);
41817815 396#endif
941557e0
ACM
397 P_MMAP_FLAG(ANONYMOUS);
398 P_MMAP_FLAG(DENYWRITE);
399 P_MMAP_FLAG(EXECUTABLE);
400 P_MMAP_FLAG(FILE);
401 P_MMAP_FLAG(FIXED);
402 P_MMAP_FLAG(GROWSDOWN);
f2935f3e 403#ifdef MAP_HUGETLB
941557e0 404 P_MMAP_FLAG(HUGETLB);
f2935f3e 405#endif
941557e0
ACM
406 P_MMAP_FLAG(LOCKED);
407 P_MMAP_FLAG(NONBLOCK);
408 P_MMAP_FLAG(NORESERVE);
409 P_MMAP_FLAG(POPULATE);
410 P_MMAP_FLAG(STACK);
411#ifdef MAP_UNINITIALIZED
412 P_MMAP_FLAG(UNINITIALIZED);
413#endif
414#undef P_MMAP_FLAG
415
416 if (flags)
417 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
418
419 return printed;
420}
421
422#define SCA_MMAP_FLAGS syscall_arg__scnprintf_mmap_flags
423
86998dda
AS
424static size_t syscall_arg__scnprintf_mremap_flags(char *bf, size_t size,
425 struct syscall_arg *arg)
426{
427 int printed = 0, flags = arg->val;
428
429#define P_MREMAP_FLAG(n) \
430 if (flags & MREMAP_##n) { \
431 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
432 flags &= ~MREMAP_##n; \
433 }
434
435 P_MREMAP_FLAG(MAYMOVE);
436#ifdef MREMAP_FIXED
437 P_MREMAP_FLAG(FIXED);
438#endif
439#undef P_MREMAP_FLAG
440
441 if (flags)
442 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
443
444 return printed;
445}
446
447#define SCA_MREMAP_FLAGS syscall_arg__scnprintf_mremap_flags
448
6e7eeb51 449static size_t syscall_arg__scnprintf_madvise_behavior(char *bf, size_t size,
01533e97 450 struct syscall_arg *arg)
9e9716d1 451{
01533e97 452 int behavior = arg->val;
9e9716d1
ACM
453
454 switch (behavior) {
455#define P_MADV_BHV(n) case MADV_##n: return scnprintf(bf, size, #n)
456 P_MADV_BHV(NORMAL);
457 P_MADV_BHV(RANDOM);
458 P_MADV_BHV(SEQUENTIAL);
459 P_MADV_BHV(WILLNEED);
460 P_MADV_BHV(DONTNEED);
461 P_MADV_BHV(REMOVE);
462 P_MADV_BHV(DONTFORK);
463 P_MADV_BHV(DOFORK);
464 P_MADV_BHV(HWPOISON);
465#ifdef MADV_SOFT_OFFLINE
466 P_MADV_BHV(SOFT_OFFLINE);
467#endif
468 P_MADV_BHV(MERGEABLE);
469 P_MADV_BHV(UNMERGEABLE);
f2935f3e 470#ifdef MADV_HUGEPAGE
9e9716d1 471 P_MADV_BHV(HUGEPAGE);
f2935f3e
DA
472#endif
473#ifdef MADV_NOHUGEPAGE
9e9716d1 474 P_MADV_BHV(NOHUGEPAGE);
f2935f3e 475#endif
9e9716d1
ACM
476#ifdef MADV_DONTDUMP
477 P_MADV_BHV(DONTDUMP);
478#endif
479#ifdef MADV_DODUMP
480 P_MADV_BHV(DODUMP);
481#endif
482#undef P_MADV_PHV
483 default: break;
484 }
485
486 return scnprintf(bf, size, "%#x", behavior);
487}
488
489#define SCA_MADV_BHV syscall_arg__scnprintf_madvise_behavior
490
5cea6ff2
ACM
491static size_t syscall_arg__scnprintf_flock(char *bf, size_t size,
492 struct syscall_arg *arg)
493{
494 int printed = 0, op = arg->val;
495
496 if (op == 0)
497 return scnprintf(bf, size, "NONE");
498#define P_CMD(cmd) \
499 if ((op & LOCK_##cmd) == LOCK_##cmd) { \
500 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #cmd); \
501 op &= ~LOCK_##cmd; \
502 }
503
504 P_CMD(SH);
505 P_CMD(EX);
506 P_CMD(NB);
507 P_CMD(UN);
508 P_CMD(MAND);
509 P_CMD(RW);
510 P_CMD(READ);
511 P_CMD(WRITE);
512#undef P_OP
513
514 if (op)
515 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", op);
516
517 return printed;
518}
519
520#define SCA_FLOCK syscall_arg__scnprintf_flock
521
01533e97 522static size_t syscall_arg__scnprintf_futex_op(char *bf, size_t size, struct syscall_arg *arg)
f9da0b0c
ACM
523{
524 enum syscall_futex_args {
525 SCF_UADDR = (1 << 0),
526 SCF_OP = (1 << 1),
527 SCF_VAL = (1 << 2),
528 SCF_TIMEOUT = (1 << 3),
529 SCF_UADDR2 = (1 << 4),
530 SCF_VAL3 = (1 << 5),
531 };
01533e97 532 int op = arg->val;
f9da0b0c
ACM
533 int cmd = op & FUTEX_CMD_MASK;
534 size_t printed = 0;
535
536 switch (cmd) {
537#define P_FUTEX_OP(n) case FUTEX_##n: printed = scnprintf(bf, size, #n);
01533e97
ACM
538 P_FUTEX_OP(WAIT); arg->mask |= SCF_VAL3|SCF_UADDR2; break;
539 P_FUTEX_OP(WAKE); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
540 P_FUTEX_OP(FD); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
541 P_FUTEX_OP(REQUEUE); arg->mask |= SCF_VAL3|SCF_TIMEOUT; break;
542 P_FUTEX_OP(CMP_REQUEUE); arg->mask |= SCF_TIMEOUT; break;
543 P_FUTEX_OP(CMP_REQUEUE_PI); arg->mask |= SCF_TIMEOUT; break;
f9da0b0c 544 P_FUTEX_OP(WAKE_OP); break;
01533e97
ACM
545 P_FUTEX_OP(LOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
546 P_FUTEX_OP(UNLOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
547 P_FUTEX_OP(TRYLOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2; break;
548 P_FUTEX_OP(WAIT_BITSET); arg->mask |= SCF_UADDR2; break;
549 P_FUTEX_OP(WAKE_BITSET); arg->mask |= SCF_UADDR2; break;
f9da0b0c
ACM
550 P_FUTEX_OP(WAIT_REQUEUE_PI); break;
551 default: printed = scnprintf(bf, size, "%#x", cmd); break;
552 }
553
554 if (op & FUTEX_PRIVATE_FLAG)
555 printed += scnprintf(bf + printed, size - printed, "|PRIV");
556
557 if (op & FUTEX_CLOCK_REALTIME)
558 printed += scnprintf(bf + printed, size - printed, "|CLKRT");
559
560 return printed;
561}
562
efe6b882
ACM
563#define SCA_FUTEX_OP syscall_arg__scnprintf_futex_op
564
03e3adc9
ACM
565static const char *epoll_ctl_ops[] = { "ADD", "DEL", "MOD", };
566static DEFINE_STRARRAY_OFFSET(epoll_ctl_ops, 1);
eac032c5 567
1f115cb7
ACM
568static const char *itimers[] = { "REAL", "VIRTUAL", "PROF", };
569static DEFINE_STRARRAY(itimers);
570
efe6b882
ACM
571static const char *whences[] = { "SET", "CUR", "END",
572#ifdef SEEK_DATA
573"DATA",
574#endif
575#ifdef SEEK_HOLE
576"HOLE",
577#endif
578};
579static DEFINE_STRARRAY(whences);
f9da0b0c 580
80f587d5
ACM
581static const char *fcntl_cmds[] = {
582 "DUPFD", "GETFD", "SETFD", "GETFL", "SETFL", "GETLK", "SETLK",
583 "SETLKW", "SETOWN", "GETOWN", "SETSIG", "GETSIG", "F_GETLK64",
584 "F_SETLK64", "F_SETLKW64", "F_SETOWN_EX", "F_GETOWN_EX",
585 "F_GETOWNER_UIDS",
586};
587static DEFINE_STRARRAY(fcntl_cmds);
588
c045bf02
ACM
589static const char *rlimit_resources[] = {
590 "CPU", "FSIZE", "DATA", "STACK", "CORE", "RSS", "NPROC", "NOFILE",
591 "MEMLOCK", "AS", "LOCKS", "SIGPENDING", "MSGQUEUE", "NICE", "RTPRIO",
592 "RTTIME",
593};
594static DEFINE_STRARRAY(rlimit_resources);
595
eb5b1b14
ACM
596static const char *sighow[] = { "BLOCK", "UNBLOCK", "SETMASK", };
597static DEFINE_STRARRAY(sighow);
598
4f8c1b74
DA
599static const char *clockid[] = {
600 "REALTIME", "MONOTONIC", "PROCESS_CPUTIME_ID", "THREAD_CPUTIME_ID",
601 "MONOTONIC_RAW", "REALTIME_COARSE", "MONOTONIC_COARSE",
602};
603static DEFINE_STRARRAY(clockid);
604
e10bce81
ACM
605static const char *socket_families[] = {
606 "UNSPEC", "LOCAL", "INET", "AX25", "IPX", "APPLETALK", "NETROM",
607 "BRIDGE", "ATMPVC", "X25", "INET6", "ROSE", "DECnet", "NETBEUI",
608 "SECURITY", "KEY", "NETLINK", "PACKET", "ASH", "ECONET", "ATMSVC",
609 "RDS", "SNA", "IRDA", "PPPOX", "WANPIPE", "LLC", "IB", "CAN", "TIPC",
610 "BLUETOOTH", "IUCV", "RXRPC", "ISDN", "PHONET", "IEEE802154", "CAIF",
611 "ALG", "NFC", "VSOCK",
612};
613static DEFINE_STRARRAY(socket_families);
614
a28b24b2
ACM
615#ifndef SOCK_TYPE_MASK
616#define SOCK_TYPE_MASK 0xf
617#endif
618
619static size_t syscall_arg__scnprintf_socket_type(char *bf, size_t size,
620 struct syscall_arg *arg)
621{
622 size_t printed;
623 int type = arg->val,
624 flags = type & ~SOCK_TYPE_MASK;
625
626 type &= SOCK_TYPE_MASK;
627 /*
628 * Can't use a strarray, MIPS may override for ABI reasons.
629 */
630 switch (type) {
631#define P_SK_TYPE(n) case SOCK_##n: printed = scnprintf(bf, size, #n); break;
632 P_SK_TYPE(STREAM);
633 P_SK_TYPE(DGRAM);
634 P_SK_TYPE(RAW);
635 P_SK_TYPE(RDM);
636 P_SK_TYPE(SEQPACKET);
637 P_SK_TYPE(DCCP);
638 P_SK_TYPE(PACKET);
639#undef P_SK_TYPE
640 default:
641 printed = scnprintf(bf, size, "%#x", type);
642 }
643
644#define P_SK_FLAG(n) \
645 if (flags & SOCK_##n) { \
646 printed += scnprintf(bf + printed, size - printed, "|%s", #n); \
647 flags &= ~SOCK_##n; \
648 }
649
650 P_SK_FLAG(CLOEXEC);
651 P_SK_FLAG(NONBLOCK);
652#undef P_SK_FLAG
653
654 if (flags)
655 printed += scnprintf(bf + printed, size - printed, "|%#x", flags);
656
657 return printed;
658}
659
660#define SCA_SK_TYPE syscall_arg__scnprintf_socket_type
661
b2cc99fd
ACM
662#ifndef MSG_PROBE
663#define MSG_PROBE 0x10
664#endif
b6e8f8f4
DA
665#ifndef MSG_WAITFORONE
666#define MSG_WAITFORONE 0x10000
667#endif
b2cc99fd
ACM
668#ifndef MSG_SENDPAGE_NOTLAST
669#define MSG_SENDPAGE_NOTLAST 0x20000
670#endif
671#ifndef MSG_FASTOPEN
672#define MSG_FASTOPEN 0x20000000
673#endif
674
675static size_t syscall_arg__scnprintf_msg_flags(char *bf, size_t size,
676 struct syscall_arg *arg)
677{
678 int printed = 0, flags = arg->val;
679
680 if (flags == 0)
681 return scnprintf(bf, size, "NONE");
682#define P_MSG_FLAG(n) \
683 if (flags & MSG_##n) { \
684 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
685 flags &= ~MSG_##n; \
686 }
687
688 P_MSG_FLAG(OOB);
689 P_MSG_FLAG(PEEK);
690 P_MSG_FLAG(DONTROUTE);
691 P_MSG_FLAG(TRYHARD);
692 P_MSG_FLAG(CTRUNC);
693 P_MSG_FLAG(PROBE);
694 P_MSG_FLAG(TRUNC);
695 P_MSG_FLAG(DONTWAIT);
696 P_MSG_FLAG(EOR);
697 P_MSG_FLAG(WAITALL);
698 P_MSG_FLAG(FIN);
699 P_MSG_FLAG(SYN);
700 P_MSG_FLAG(CONFIRM);
701 P_MSG_FLAG(RST);
702 P_MSG_FLAG(ERRQUEUE);
703 P_MSG_FLAG(NOSIGNAL);
704 P_MSG_FLAG(MORE);
705 P_MSG_FLAG(WAITFORONE);
706 P_MSG_FLAG(SENDPAGE_NOTLAST);
707 P_MSG_FLAG(FASTOPEN);
708 P_MSG_FLAG(CMSG_CLOEXEC);
709#undef P_MSG_FLAG
710
711 if (flags)
712 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
713
714 return printed;
715}
716
717#define SCA_MSG_FLAGS syscall_arg__scnprintf_msg_flags
718
51108999
ACM
719static size_t syscall_arg__scnprintf_access_mode(char *bf, size_t size,
720 struct syscall_arg *arg)
721{
722 size_t printed = 0;
723 int mode = arg->val;
724
725 if (mode == F_OK) /* 0 */
726 return scnprintf(bf, size, "F");
727#define P_MODE(n) \
728 if (mode & n##_OK) { \
729 printed += scnprintf(bf + printed, size - printed, "%s", #n); \
730 mode &= ~n##_OK; \
731 }
732
733 P_MODE(R);
734 P_MODE(W);
735 P_MODE(X);
736#undef P_MODE
737
738 if (mode)
739 printed += scnprintf(bf + printed, size - printed, "|%#x", mode);
740
741 return printed;
742}
743
744#define SCA_ACCMODE syscall_arg__scnprintf_access_mode
745
be65a89a 746static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
01533e97 747 struct syscall_arg *arg)
be65a89a 748{
01533e97 749 int printed = 0, flags = arg->val;
be65a89a
ACM
750
751 if (!(flags & O_CREAT))
01533e97 752 arg->mask |= 1 << (arg->idx + 1); /* Mask the mode parm */
be65a89a
ACM
753
754 if (flags == 0)
755 return scnprintf(bf, size, "RDONLY");
756#define P_FLAG(n) \
757 if (flags & O_##n) { \
758 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
759 flags &= ~O_##n; \
760 }
761
762 P_FLAG(APPEND);
763 P_FLAG(ASYNC);
764 P_FLAG(CLOEXEC);
765 P_FLAG(CREAT);
766 P_FLAG(DIRECT);
767 P_FLAG(DIRECTORY);
768 P_FLAG(EXCL);
769 P_FLAG(LARGEFILE);
770 P_FLAG(NOATIME);
771 P_FLAG(NOCTTY);
772#ifdef O_NONBLOCK
773 P_FLAG(NONBLOCK);
774#elif O_NDELAY
775 P_FLAG(NDELAY);
776#endif
777#ifdef O_PATH
778 P_FLAG(PATH);
779#endif
780 P_FLAG(RDWR);
781#ifdef O_DSYNC
782 if ((flags & O_SYNC) == O_SYNC)
783 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", "SYNC");
784 else {
785 P_FLAG(DSYNC);
786 }
787#else
788 P_FLAG(SYNC);
789#endif
790 P_FLAG(TRUNC);
791 P_FLAG(WRONLY);
792#undef P_FLAG
793
794 if (flags)
795 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
796
797 return printed;
798}
799
800#define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags
801
a1c2552d
ACM
802static size_t syscall_arg__scnprintf_perf_flags(char *bf, size_t size,
803 struct syscall_arg *arg)
804{
805 int printed = 0, flags = arg->val;
806
807 if (flags == 0)
808 return 0;
809
810#define P_FLAG(n) \
811 if (flags & PERF_FLAG_##n) { \
812 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
813 flags &= ~PERF_FLAG_##n; \
814 }
815
816 P_FLAG(FD_NO_GROUP);
817 P_FLAG(FD_OUTPUT);
818 P_FLAG(PID_CGROUP);
819 P_FLAG(FD_CLOEXEC);
820#undef P_FLAG
821
822 if (flags)
823 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
824
825 return printed;
826}
827
828#define SCA_PERF_FLAGS syscall_arg__scnprintf_perf_flags
829
49af9e93
ACM
830static size_t syscall_arg__scnprintf_eventfd_flags(char *bf, size_t size,
831 struct syscall_arg *arg)
832{
833 int printed = 0, flags = arg->val;
834
835 if (flags == 0)
836 return scnprintf(bf, size, "NONE");
837#define P_FLAG(n) \
838 if (flags & EFD_##n) { \
839 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
840 flags &= ~EFD_##n; \
841 }
842
843 P_FLAG(SEMAPHORE);
844 P_FLAG(CLOEXEC);
845 P_FLAG(NONBLOCK);
846#undef P_FLAG
847
848 if (flags)
849 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
850
851 return printed;
852}
853
854#define SCA_EFD_FLAGS syscall_arg__scnprintf_eventfd_flags
855
46cce19b
ACM
856static size_t syscall_arg__scnprintf_pipe_flags(char *bf, size_t size,
857 struct syscall_arg *arg)
858{
859 int printed = 0, flags = arg->val;
860
861#define P_FLAG(n) \
862 if (flags & O_##n) { \
863 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
864 flags &= ~O_##n; \
865 }
866
867 P_FLAG(CLOEXEC);
868 P_FLAG(NONBLOCK);
869#undef P_FLAG
870
871 if (flags)
872 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
873
874 return printed;
875}
876
877#define SCA_PIPE_FLAGS syscall_arg__scnprintf_pipe_flags
878
8bad5b0a
ACM
879static size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscall_arg *arg)
880{
881 int sig = arg->val;
882
883 switch (sig) {
884#define P_SIGNUM(n) case SIG##n: return scnprintf(bf, size, #n)
885 P_SIGNUM(HUP);
886 P_SIGNUM(INT);
887 P_SIGNUM(QUIT);
888 P_SIGNUM(ILL);
889 P_SIGNUM(TRAP);
890 P_SIGNUM(ABRT);
891 P_SIGNUM(BUS);
892 P_SIGNUM(FPE);
893 P_SIGNUM(KILL);
894 P_SIGNUM(USR1);
895 P_SIGNUM(SEGV);
896 P_SIGNUM(USR2);
897 P_SIGNUM(PIPE);
898 P_SIGNUM(ALRM);
899 P_SIGNUM(TERM);
8bad5b0a
ACM
900 P_SIGNUM(CHLD);
901 P_SIGNUM(CONT);
902 P_SIGNUM(STOP);
903 P_SIGNUM(TSTP);
904 P_SIGNUM(TTIN);
905 P_SIGNUM(TTOU);
906 P_SIGNUM(URG);
907 P_SIGNUM(XCPU);
908 P_SIGNUM(XFSZ);
909 P_SIGNUM(VTALRM);
910 P_SIGNUM(PROF);
911 P_SIGNUM(WINCH);
912 P_SIGNUM(IO);
913 P_SIGNUM(PWR);
914 P_SIGNUM(SYS);
02c5bb4a
BH
915#ifdef SIGEMT
916 P_SIGNUM(EMT);
917#endif
918#ifdef SIGSTKFLT
919 P_SIGNUM(STKFLT);
920#endif
921#ifdef SIGSWI
922 P_SIGNUM(SWI);
923#endif
8bad5b0a
ACM
924 default: break;
925 }
926
927 return scnprintf(bf, size, "%#x", sig);
928}
929
930#define SCA_SIGNUM syscall_arg__scnprintf_signum
931
844ae5b4
ACM
932#if defined(__i386__) || defined(__x86_64__)
933/*
934 * FIXME: Make this available to all arches.
935 */
78645cf3
ACM
936#define TCGETS 0x5401
937
938static const char *tioctls[] = {
939 "TCGETS", "TCSETS", "TCSETSW", "TCSETSF", "TCGETA", "TCSETA", "TCSETAW",
940 "TCSETAF", "TCSBRK", "TCXONC", "TCFLSH", "TIOCEXCL", "TIOCNXCL",
941 "TIOCSCTTY", "TIOCGPGRP", "TIOCSPGRP", "TIOCOUTQ", "TIOCSTI",
942 "TIOCGWINSZ", "TIOCSWINSZ", "TIOCMGET", "TIOCMBIS", "TIOCMBIC",
943 "TIOCMSET", "TIOCGSOFTCAR", "TIOCSSOFTCAR", "FIONREAD", "TIOCLINUX",
944 "TIOCCONS", "TIOCGSERIAL", "TIOCSSERIAL", "TIOCPKT", "FIONBIO",
945 "TIOCNOTTY", "TIOCSETD", "TIOCGETD", "TCSBRKP", [0x27] = "TIOCSBRK",
946 "TIOCCBRK", "TIOCGSID", "TCGETS2", "TCSETS2", "TCSETSW2", "TCSETSF2",
947 "TIOCGRS485", "TIOCSRS485", "TIOCGPTN", "TIOCSPTLCK",
948 "TIOCGDEV||TCGETX", "TCSETX", "TCSETXF", "TCSETXW", "TIOCSIG",
949 "TIOCVHANGUP", "TIOCGPKT", "TIOCGPTLCK", "TIOCGEXCL",
950 [0x50] = "FIONCLEX", "FIOCLEX", "FIOASYNC", "TIOCSERCONFIG",
951 "TIOCSERGWILD", "TIOCSERSWILD", "TIOCGLCKTRMIOS", "TIOCSLCKTRMIOS",
952 "TIOCSERGSTRUCT", "TIOCSERGETLSR", "TIOCSERGETMULTI", "TIOCSERSETMULTI",
953 "TIOCMIWAIT", "TIOCGICOUNT", [0x60] = "FIOQSIZE",
954};
955
956static DEFINE_STRARRAY_OFFSET(tioctls, 0x5401);
844ae5b4 957#endif /* defined(__i386__) || defined(__x86_64__) */
78645cf3 958
453350dd
ACM
959#define STRARRAY(arg, name, array) \
960 .arg_scnprintf = { [arg] = SCA_STRARRAY, }, \
961 .arg_parm = { [arg] = &strarray__##array, }
962
514f1c67
ACM
963static struct syscall_fmt {
964 const char *name;
aec1930b 965 const char *alias;
01533e97 966 size_t (*arg_scnprintf[6])(char *bf, size_t size, struct syscall_arg *arg);
1f115cb7 967 void *arg_parm[6];
514f1c67
ACM
968 bool errmsg;
969 bool timeout;
04b34729 970 bool hexret;
514f1c67 971} syscall_fmts[] = {
51108999
ACM
972 { .name = "access", .errmsg = true,
973 .arg_scnprintf = { [1] = SCA_ACCMODE, /* mode */ }, },
aec1930b 974 { .name = "arch_prctl", .errmsg = true, .alias = "prctl", },
beccb2b5
ACM
975 { .name = "brk", .hexret = true,
976 .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, },
4f8c1b74 977 { .name = "clock_gettime", .errmsg = true, STRARRAY(0, clk_id, clockid), },
75b757ca 978 { .name = "close", .errmsg = true,
48000a1a 979 .arg_scnprintf = { [0] = SCA_CLOSE_FD, /* fd */ }, },
a14bb860 980 { .name = "connect", .errmsg = true, },
75b757ca 981 { .name = "dup", .errmsg = true,
48000a1a 982 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
75b757ca 983 { .name = "dup2", .errmsg = true,
48000a1a 984 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
75b757ca 985 { .name = "dup3", .errmsg = true,
48000a1a 986 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
453350dd 987 { .name = "epoll_ctl", .errmsg = true, STRARRAY(1, op, epoll_ctl_ops), },
49af9e93
ACM
988 { .name = "eventfd2", .errmsg = true,
989 .arg_scnprintf = { [1] = SCA_EFD_FLAGS, /* flags */ }, },
75b757ca
ACM
990 { .name = "faccessat", .errmsg = true,
991 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
992 { .name = "fadvise64", .errmsg = true,
48000a1a 993 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
75b757ca 994 { .name = "fallocate", .errmsg = true,
48000a1a 995 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
75b757ca 996 { .name = "fchdir", .errmsg = true,
48000a1a 997 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
75b757ca 998 { .name = "fchmod", .errmsg = true,
48000a1a 999 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
75b757ca 1000 { .name = "fchmodat", .errmsg = true,
48000a1a 1001 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
75b757ca 1002 { .name = "fchown", .errmsg = true,
48000a1a 1003 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
75b757ca 1004 { .name = "fchownat", .errmsg = true,
48000a1a 1005 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
75b757ca
ACM
1006 { .name = "fcntl", .errmsg = true,
1007 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1008 [1] = SCA_STRARRAY, /* cmd */ },
1009 .arg_parm = { [1] = &strarray__fcntl_cmds, /* cmd */ }, },
1010 { .name = "fdatasync", .errmsg = true,
48000a1a 1011 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
5cea6ff2 1012 { .name = "flock", .errmsg = true,
75b757ca
ACM
1013 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1014 [1] = SCA_FLOCK, /* cmd */ }, },
1015 { .name = "fsetxattr", .errmsg = true,
48000a1a 1016 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
75b757ca 1017 { .name = "fstat", .errmsg = true, .alias = "newfstat",
48000a1a 1018 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
75b757ca 1019 { .name = "fstatat", .errmsg = true, .alias = "newfstatat",
48000a1a 1020 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
75b757ca 1021 { .name = "fstatfs", .errmsg = true,
48000a1a 1022 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
75b757ca 1023 { .name = "fsync", .errmsg = true,
48000a1a 1024 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
75b757ca 1025 { .name = "ftruncate", .errmsg = true,
48000a1a 1026 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
f9da0b0c
ACM
1027 { .name = "futex", .errmsg = true,
1028 .arg_scnprintf = { [1] = SCA_FUTEX_OP, /* op */ }, },
75b757ca 1029 { .name = "futimesat", .errmsg = true,
48000a1a 1030 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
75b757ca 1031 { .name = "getdents", .errmsg = true,
48000a1a 1032 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
75b757ca 1033 { .name = "getdents64", .errmsg = true,
48000a1a 1034 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
453350dd
ACM
1035 { .name = "getitimer", .errmsg = true, STRARRAY(0, which, itimers), },
1036 { .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
beccb2b5 1037 { .name = "ioctl", .errmsg = true,
48000a1a 1038 .arg_scnprintf = { [0] = SCA_FD, /* fd */
844ae5b4
ACM
1039#if defined(__i386__) || defined(__x86_64__)
1040/*
1041 * FIXME: Make this available to all arches.
1042 */
78645cf3
ACM
1043 [1] = SCA_STRHEXARRAY, /* cmd */
1044 [2] = SCA_HEX, /* arg */ },
1045 .arg_parm = { [1] = &strarray__tioctls, /* cmd */ }, },
844ae5b4
ACM
1046#else
1047 [2] = SCA_HEX, /* arg */ }, },
1048#endif
8bad5b0a
ACM
1049 { .name = "kill", .errmsg = true,
1050 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
75b757ca 1051 { .name = "linkat", .errmsg = true,
48000a1a 1052 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
75b757ca
ACM
1053 { .name = "lseek", .errmsg = true,
1054 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1055 [2] = SCA_STRARRAY, /* whence */ },
1056 .arg_parm = { [2] = &strarray__whences, /* whence */ }, },
e5959683 1057 { .name = "lstat", .errmsg = true, .alias = "newlstat", },
9e9716d1
ACM
1058 { .name = "madvise", .errmsg = true,
1059 .arg_scnprintf = { [0] = SCA_HEX, /* start */
1060 [2] = SCA_MADV_BHV, /* behavior */ }, },
75b757ca 1061 { .name = "mkdirat", .errmsg = true,
48000a1a 1062 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
75b757ca 1063 { .name = "mknodat", .errmsg = true,
48000a1a 1064 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
3d903aa7
ACM
1065 { .name = "mlock", .errmsg = true,
1066 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
1067 { .name = "mlockall", .errmsg = true,
1068 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
beccb2b5 1069 { .name = "mmap", .hexret = true,
ae685380 1070 .arg_scnprintf = { [0] = SCA_HEX, /* addr */
941557e0 1071 [2] = SCA_MMAP_PROT, /* prot */
73faab3a
NK
1072 [3] = SCA_MMAP_FLAGS, /* flags */
1073 [4] = SCA_FD, /* fd */ }, },
beccb2b5 1074 { .name = "mprotect", .errmsg = true,
ae685380
ACM
1075 .arg_scnprintf = { [0] = SCA_HEX, /* start */
1076 [2] = SCA_MMAP_PROT, /* prot */ }, },
1077 { .name = "mremap", .hexret = true,
1078 .arg_scnprintf = { [0] = SCA_HEX, /* addr */
86998dda 1079 [3] = SCA_MREMAP_FLAGS, /* flags */
ae685380 1080 [4] = SCA_HEX, /* new_addr */ }, },
3d903aa7
ACM
1081 { .name = "munlock", .errmsg = true,
1082 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
beccb2b5
ACM
1083 { .name = "munmap", .errmsg = true,
1084 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
75b757ca 1085 { .name = "name_to_handle_at", .errmsg = true,
48000a1a 1086 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
75b757ca 1087 { .name = "newfstatat", .errmsg = true,
48000a1a 1088 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
be65a89a
ACM
1089 { .name = "open", .errmsg = true,
1090 .arg_scnprintf = { [1] = SCA_OPEN_FLAGS, /* flags */ }, },
31cd3855 1091 { .name = "open_by_handle_at", .errmsg = true,
75b757ca
ACM
1092 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
1093 [2] = SCA_OPEN_FLAGS, /* flags */ }, },
31cd3855 1094 { .name = "openat", .errmsg = true,
75b757ca
ACM
1095 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
1096 [2] = SCA_OPEN_FLAGS, /* flags */ }, },
a1c2552d
ACM
1097 { .name = "perf_event_open", .errmsg = true,
1098 .arg_scnprintf = { [1] = SCA_INT, /* pid */
1099 [2] = SCA_INT, /* cpu */
1100 [3] = SCA_FD, /* group_fd */
1101 [4] = SCA_PERF_FLAGS, /* flags */ }, },
46cce19b
ACM
1102 { .name = "pipe2", .errmsg = true,
1103 .arg_scnprintf = { [1] = SCA_PIPE_FLAGS, /* flags */ }, },
aec1930b
ACM
1104 { .name = "poll", .errmsg = true, .timeout = true, },
1105 { .name = "ppoll", .errmsg = true, .timeout = true, },
75b757ca 1106 { .name = "pread", .errmsg = true, .alias = "pread64",
48000a1a 1107 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
75b757ca 1108 { .name = "preadv", .errmsg = true, .alias = "pread",
48000a1a 1109 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
453350dd 1110 { .name = "prlimit64", .errmsg = true, STRARRAY(1, resource, rlimit_resources), },
75b757ca 1111 { .name = "pwrite", .errmsg = true, .alias = "pwrite64",
48000a1a 1112 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
75b757ca 1113 { .name = "pwritev", .errmsg = true,
48000a1a 1114 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
75b757ca 1115 { .name = "read", .errmsg = true,
48000a1a 1116 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
75b757ca 1117 { .name = "readlinkat", .errmsg = true,
48000a1a 1118 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
75b757ca 1119 { .name = "readv", .errmsg = true,
48000a1a 1120 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
b2cc99fd
ACM
1121 { .name = "recvfrom", .errmsg = true,
1122 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
1123 { .name = "recvmmsg", .errmsg = true,
1124 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
1125 { .name = "recvmsg", .errmsg = true,
1126 .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, },
75b757ca 1127 { .name = "renameat", .errmsg = true,
48000a1a 1128 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
8bad5b0a
ACM
1129 { .name = "rt_sigaction", .errmsg = true,
1130 .arg_scnprintf = { [0] = SCA_SIGNUM, /* sig */ }, },
453350dd 1131 { .name = "rt_sigprocmask", .errmsg = true, STRARRAY(0, how, sighow), },
8bad5b0a
ACM
1132 { .name = "rt_sigqueueinfo", .errmsg = true,
1133 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
1134 { .name = "rt_tgsigqueueinfo", .errmsg = true,
1135 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
aec1930b 1136 { .name = "select", .errmsg = true, .timeout = true, },
b2cc99fd
ACM
1137 { .name = "sendmmsg", .errmsg = true,
1138 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
1139 { .name = "sendmsg", .errmsg = true,
1140 .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, },
1141 { .name = "sendto", .errmsg = true,
1142 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
453350dd
ACM
1143 { .name = "setitimer", .errmsg = true, STRARRAY(0, which, itimers), },
1144 { .name = "setrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
75b757ca 1145 { .name = "shutdown", .errmsg = true,
48000a1a 1146 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
e10bce81 1147 { .name = "socket", .errmsg = true,
a28b24b2
ACM
1148 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
1149 [1] = SCA_SK_TYPE, /* type */ },
07120aa5
ACM
1150 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, },
1151 { .name = "socketpair", .errmsg = true,
1152 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
1153 [1] = SCA_SK_TYPE, /* type */ },
e10bce81 1154 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, },
aec1930b 1155 { .name = "stat", .errmsg = true, .alias = "newstat", },
75b757ca 1156 { .name = "symlinkat", .errmsg = true,
48000a1a 1157 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
8bad5b0a
ACM
1158 { .name = "tgkill", .errmsg = true,
1159 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
1160 { .name = "tkill", .errmsg = true,
1161 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
e5959683 1162 { .name = "uname", .errmsg = true, .alias = "newuname", },
75b757ca
ACM
1163 { .name = "unlinkat", .errmsg = true,
1164 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
1165 { .name = "utimensat", .errmsg = true,
1166 .arg_scnprintf = { [0] = SCA_FDAT, /* dirfd */ }, },
1167 { .name = "write", .errmsg = true,
48000a1a 1168 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
75b757ca 1169 { .name = "writev", .errmsg = true,
48000a1a 1170 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
514f1c67
ACM
1171};
1172
1173static int syscall_fmt__cmp(const void *name, const void *fmtp)
1174{
1175 const struct syscall_fmt *fmt = fmtp;
1176 return strcmp(name, fmt->name);
1177}
1178
1179static struct syscall_fmt *syscall_fmt__find(const char *name)
1180{
1181 const int nmemb = ARRAY_SIZE(syscall_fmts);
1182 return bsearch(name, syscall_fmts, nmemb, sizeof(struct syscall_fmt), syscall_fmt__cmp);
1183}
1184
1185struct syscall {
1186 struct event_format *tp_format;
f208bd8d
ACM
1187 int nr_args;
1188 struct format_field *args;
514f1c67 1189 const char *name;
5089f20e 1190 bool is_exit;
514f1c67 1191 struct syscall_fmt *fmt;
01533e97 1192 size_t (**arg_scnprintf)(char *bf, size_t size, struct syscall_arg *arg);
1f115cb7 1193 void **arg_parm;
514f1c67
ACM
1194};
1195
60c907ab
ACM
1196static size_t fprintf_duration(unsigned long t, FILE *fp)
1197{
1198 double duration = (double)t / NSEC_PER_MSEC;
1199 size_t printed = fprintf(fp, "(");
1200
1201 if (duration >= 1.0)
1202 printed += color_fprintf(fp, PERF_COLOR_RED, "%6.3f ms", duration);
1203 else if (duration >= 0.01)
1204 printed += color_fprintf(fp, PERF_COLOR_YELLOW, "%6.3f ms", duration);
1205 else
1206 printed += color_fprintf(fp, PERF_COLOR_NORMAL, "%6.3f ms", duration);
c24ff998 1207 return printed + fprintf(fp, "): ");
60c907ab
ACM
1208}
1209
752fde44
ACM
1210struct thread_trace {
1211 u64 entry_time;
1212 u64 exit_time;
1213 bool entry_pending;
efd5745e 1214 unsigned long nr_events;
a2ea67d7 1215 unsigned long pfmaj, pfmin;
752fde44 1216 char *entry_str;
1302d88e 1217 double runtime_ms;
75b757ca
ACM
1218 struct {
1219 int max;
1220 char **table;
1221 } paths;
bf2575c1
DA
1222
1223 struct intlist *syscall_stats;
752fde44
ACM
1224};
1225
1226static struct thread_trace *thread_trace__new(void)
1227{
75b757ca
ACM
1228 struct thread_trace *ttrace = zalloc(sizeof(struct thread_trace));
1229
1230 if (ttrace)
1231 ttrace->paths.max = -1;
1232
bf2575c1
DA
1233 ttrace->syscall_stats = intlist__new(NULL);
1234
75b757ca 1235 return ttrace;
752fde44
ACM
1236}
1237
c24ff998 1238static struct thread_trace *thread__trace(struct thread *thread, FILE *fp)
752fde44 1239{
efd5745e
ACM
1240 struct thread_trace *ttrace;
1241
752fde44
ACM
1242 if (thread == NULL)
1243 goto fail;
1244
89dceb22
NK
1245 if (thread__priv(thread) == NULL)
1246 thread__set_priv(thread, thread_trace__new());
48000a1a 1247
89dceb22 1248 if (thread__priv(thread) == NULL)
752fde44
ACM
1249 goto fail;
1250
89dceb22 1251 ttrace = thread__priv(thread);
efd5745e
ACM
1252 ++ttrace->nr_events;
1253
1254 return ttrace;
752fde44 1255fail:
c24ff998 1256 color_fprintf(fp, PERF_COLOR_RED,
752fde44
ACM
1257 "WARNING: not enough memory, dropping samples!\n");
1258 return NULL;
1259}
1260
598d02c5
SF
1261#define TRACE_PFMAJ (1 << 0)
1262#define TRACE_PFMIN (1 << 1)
1263
514f1c67 1264struct trace {
c24ff998 1265 struct perf_tool tool;
c522739d
ACM
1266 struct {
1267 int machine;
1268 int open_id;
1269 } audit;
514f1c67
ACM
1270 struct {
1271 int max;
1272 struct syscall *table;
c27366f0 1273 struct {
8b3ce757
ACM
1274 struct perf_evsel *sys_enter,
1275 *sys_exit;
c27366f0 1276 } events;
514f1c67 1277 } syscalls;
b4006796 1278 struct record_opts opts;
14a052df 1279 struct perf_evlist *evlist;
8fb598e5 1280 struct machine *host;
e596663e 1281 struct thread *current;
752fde44 1282 u64 base_time;
c24ff998 1283 FILE *output;
efd5745e 1284 unsigned long nr_events;
b059efdf 1285 struct strlist *ev_qualifier;
8b3ce757
ACM
1286 struct {
1287 size_t nr;
1288 int *entries;
1289 } ev_qualifier_ids;
c522739d 1290 const char *last_vfs_getname;
bdc89661
DA
1291 struct intlist *tid_list;
1292 struct intlist *pid_list;
f078c385
ACM
1293 struct {
1294 size_t nr;
1295 pid_t *entries;
1296 } filter_pids;
98eafce6
ACM
1297 double duration_filter;
1298 double runtime_ms;
1299 struct {
1300 u64 vfs_getname,
1301 proc_getname;
1302 } stats;
1303 bool not_ev_qualifier;
1304 bool live;
1305 bool full_time;
1302d88e 1306 bool sched;
752fde44 1307 bool multiple_threads;
bf2575c1 1308 bool summary;
fd2eabaf 1309 bool summary_only;
50c95cbd 1310 bool show_comm;
c522739d 1311 bool show_tool_stats;
e281a960 1312 bool trace_syscalls;
e366a6d8 1313 bool force;
598d02c5 1314 int trace_pgfaults;
514f1c67
ACM
1315};
1316
97119f37 1317static int trace__set_fd_pathname(struct thread *thread, int fd, const char *pathname)
75b757ca 1318{
89dceb22 1319 struct thread_trace *ttrace = thread__priv(thread);
75b757ca
ACM
1320
1321 if (fd > ttrace->paths.max) {
1322 char **npath = realloc(ttrace->paths.table, (fd + 1) * sizeof(char *));
1323
1324 if (npath == NULL)
1325 return -1;
1326
1327 if (ttrace->paths.max != -1) {
1328 memset(npath + ttrace->paths.max + 1, 0,
1329 (fd - ttrace->paths.max) * sizeof(char *));
1330 } else {
1331 memset(npath, 0, (fd + 1) * sizeof(char *));
1332 }
1333
1334 ttrace->paths.table = npath;
1335 ttrace->paths.max = fd;
1336 }
1337
1338 ttrace->paths.table[fd] = strdup(pathname);
1339
1340 return ttrace->paths.table[fd] != NULL ? 0 : -1;
1341}
1342
97119f37
ACM
1343static int thread__read_fd_path(struct thread *thread, int fd)
1344{
1345 char linkname[PATH_MAX], pathname[PATH_MAX];
1346 struct stat st;
1347 int ret;
1348
1349 if (thread->pid_ == thread->tid) {
1350 scnprintf(linkname, sizeof(linkname),
1351 "/proc/%d/fd/%d", thread->pid_, fd);
1352 } else {
1353 scnprintf(linkname, sizeof(linkname),
1354 "/proc/%d/task/%d/fd/%d", thread->pid_, thread->tid, fd);
1355 }
1356
1357 if (lstat(linkname, &st) < 0 || st.st_size + 1 > (off_t)sizeof(pathname))
1358 return -1;
1359
1360 ret = readlink(linkname, pathname, sizeof(pathname));
1361
1362 if (ret < 0 || ret > st.st_size)
1363 return -1;
1364
1365 pathname[ret] = '\0';
1366 return trace__set_fd_pathname(thread, fd, pathname);
1367}
1368
c522739d
ACM
1369static const char *thread__fd_path(struct thread *thread, int fd,
1370 struct trace *trace)
75b757ca 1371{
89dceb22 1372 struct thread_trace *ttrace = thread__priv(thread);
75b757ca
ACM
1373
1374 if (ttrace == NULL)
1375 return NULL;
1376
1377 if (fd < 0)
1378 return NULL;
1379
cdcd1e6b 1380 if ((fd > ttrace->paths.max || ttrace->paths.table[fd] == NULL)) {
c522739d
ACM
1381 if (!trace->live)
1382 return NULL;
1383 ++trace->stats.proc_getname;
cdcd1e6b 1384 if (thread__read_fd_path(thread, fd))
c522739d
ACM
1385 return NULL;
1386 }
75b757ca
ACM
1387
1388 return ttrace->paths.table[fd];
1389}
1390
1391static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
1392 struct syscall_arg *arg)
1393{
1394 int fd = arg->val;
1395 size_t printed = scnprintf(bf, size, "%d", fd);
c522739d 1396 const char *path = thread__fd_path(arg->thread, fd, arg->trace);
75b757ca
ACM
1397
1398 if (path)
1399 printed += scnprintf(bf + printed, size - printed, "<%s>", path);
1400
1401 return printed;
1402}
1403
1404static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
1405 struct syscall_arg *arg)
1406{
1407 int fd = arg->val;
1408 size_t printed = syscall_arg__scnprintf_fd(bf, size, arg);
89dceb22 1409 struct thread_trace *ttrace = thread__priv(arg->thread);
75b757ca 1410
04662523
ACM
1411 if (ttrace && fd >= 0 && fd <= ttrace->paths.max)
1412 zfree(&ttrace->paths.table[fd]);
75b757ca
ACM
1413
1414 return printed;
1415}
1416
ae9ed035
ACM
1417static bool trace__filter_duration(struct trace *trace, double t)
1418{
1419 return t < (trace->duration_filter * NSEC_PER_MSEC);
1420}
1421
752fde44
ACM
1422static size_t trace__fprintf_tstamp(struct trace *trace, u64 tstamp, FILE *fp)
1423{
1424 double ts = (double)(tstamp - trace->base_time) / NSEC_PER_MSEC;
1425
60c907ab 1426 return fprintf(fp, "%10.3f ", ts);
752fde44
ACM
1427}
1428
f15eb531 1429static bool done = false;
ba209f85 1430static bool interrupted = false;
f15eb531 1431
ba209f85 1432static void sig_handler(int sig)
f15eb531
NK
1433{
1434 done = true;
ba209f85 1435 interrupted = sig == SIGINT;
f15eb531
NK
1436}
1437
752fde44 1438static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thread,
60c907ab 1439 u64 duration, u64 tstamp, FILE *fp)
752fde44
ACM
1440{
1441 size_t printed = trace__fprintf_tstamp(trace, tstamp, fp);
60c907ab 1442 printed += fprintf_duration(duration, fp);
752fde44 1443
50c95cbd
ACM
1444 if (trace->multiple_threads) {
1445 if (trace->show_comm)
1902efe7 1446 printed += fprintf(fp, "%.14s/", thread__comm_str(thread));
38051234 1447 printed += fprintf(fp, "%d ", thread->tid);
50c95cbd 1448 }
752fde44
ACM
1449
1450 return printed;
1451}
1452
c24ff998 1453static int trace__process_event(struct trace *trace, struct machine *machine,
162f0bef 1454 union perf_event *event, struct perf_sample *sample)
752fde44
ACM
1455{
1456 int ret = 0;
1457
1458 switch (event->header.type) {
1459 case PERF_RECORD_LOST:
c24ff998 1460 color_fprintf(trace->output, PERF_COLOR_RED,
752fde44 1461 "LOST %" PRIu64 " events!\n", event->lost.lost);
162f0bef 1462 ret = machine__process_lost_event(machine, event, sample);
752fde44 1463 default:
162f0bef 1464 ret = machine__process_event(machine, event, sample);
752fde44
ACM
1465 break;
1466 }
1467
1468 return ret;
1469}
1470
c24ff998 1471static int trace__tool_process(struct perf_tool *tool,
752fde44 1472 union perf_event *event,
162f0bef 1473 struct perf_sample *sample,
752fde44
ACM
1474 struct machine *machine)
1475{
c24ff998 1476 struct trace *trace = container_of(tool, struct trace, tool);
162f0bef 1477 return trace__process_event(trace, machine, event, sample);
752fde44
ACM
1478}
1479
1480static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
1481{
0a7e6d1b 1482 int err = symbol__init(NULL);
752fde44
ACM
1483
1484 if (err)
1485 return err;
1486
8fb598e5
DA
1487 trace->host = machine__new_host();
1488 if (trace->host == NULL)
1489 return -ENOMEM;
752fde44 1490
a33fbd56 1491 err = __machine__synthesize_threads(trace->host, &trace->tool, &trace->opts.target,
9d9cad76
KL
1492 evlist->threads, trace__tool_process, false,
1493 trace->opts.proc_map_timeout);
752fde44
ACM
1494 if (err)
1495 symbol__exit();
1496
1497 return err;
1498}
1499
13d4ff3e
ACM
1500static int syscall__set_arg_fmts(struct syscall *sc)
1501{
1502 struct format_field *field;
1503 int idx = 0;
1504
f208bd8d 1505 sc->arg_scnprintf = calloc(sc->nr_args, sizeof(void *));
13d4ff3e
ACM
1506 if (sc->arg_scnprintf == NULL)
1507 return -1;
1508
1f115cb7
ACM
1509 if (sc->fmt)
1510 sc->arg_parm = sc->fmt->arg_parm;
1511
f208bd8d 1512 for (field = sc->args; field; field = field->next) {
beccb2b5
ACM
1513 if (sc->fmt && sc->fmt->arg_scnprintf[idx])
1514 sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx];
1515 else if (field->flags & FIELD_IS_POINTER)
13d4ff3e
ACM
1516 sc->arg_scnprintf[idx] = syscall_arg__scnprintf_hex;
1517 ++idx;
1518 }
1519
1520 return 0;
1521}
1522
514f1c67
ACM
1523static int trace__read_syscall_info(struct trace *trace, int id)
1524{
1525 char tp_name[128];
1526 struct syscall *sc;
c522739d 1527 const char *name = audit_syscall_to_name(id, trace->audit.machine);
3a531260
ACM
1528
1529 if (name == NULL)
1530 return -1;
514f1c67
ACM
1531
1532 if (id > trace->syscalls.max) {
1533 struct syscall *nsyscalls = realloc(trace->syscalls.table, (id + 1) * sizeof(*sc));
1534
1535 if (nsyscalls == NULL)
1536 return -1;
1537
1538 if (trace->syscalls.max != -1) {
1539 memset(nsyscalls + trace->syscalls.max + 1, 0,
1540 (id - trace->syscalls.max) * sizeof(*sc));
1541 } else {
1542 memset(nsyscalls, 0, (id + 1) * sizeof(*sc));
1543 }
1544
1545 trace->syscalls.table = nsyscalls;
1546 trace->syscalls.max = id;
1547 }
1548
1549 sc = trace->syscalls.table + id;
3a531260 1550 sc->name = name;
2ae3a312 1551
3a531260 1552 sc->fmt = syscall_fmt__find(sc->name);
514f1c67 1553
aec1930b 1554 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name);
97978b3e 1555 sc->tp_format = trace_event__tp_format("syscalls", tp_name);
aec1930b
ACM
1556
1557 if (sc->tp_format == NULL && sc->fmt && sc->fmt->alias) {
1558 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->fmt->alias);
97978b3e 1559 sc->tp_format = trace_event__tp_format("syscalls", tp_name);
aec1930b 1560 }
514f1c67 1561
13d4ff3e
ACM
1562 if (sc->tp_format == NULL)
1563 return -1;
1564
f208bd8d
ACM
1565 sc->args = sc->tp_format->format.fields;
1566 sc->nr_args = sc->tp_format->format.nr_fields;
1567 /* drop nr field - not relevant here; does not exist on older kernels */
1568 if (sc->args && strcmp(sc->args->name, "nr") == 0) {
1569 sc->args = sc->args->next;
1570 --sc->nr_args;
1571 }
1572
5089f20e
ACM
1573 sc->is_exit = !strcmp(name, "exit_group") || !strcmp(name, "exit");
1574
13d4ff3e 1575 return syscall__set_arg_fmts(sc);
514f1c67
ACM
1576}
1577
d0cc439b
ACM
1578static int trace__validate_ev_qualifier(struct trace *trace)
1579{
8b3ce757 1580 int err = 0, i;
d0cc439b
ACM
1581 struct str_node *pos;
1582
8b3ce757
ACM
1583 trace->ev_qualifier_ids.nr = strlist__nr_entries(trace->ev_qualifier);
1584 trace->ev_qualifier_ids.entries = malloc(trace->ev_qualifier_ids.nr *
1585 sizeof(trace->ev_qualifier_ids.entries[0]));
1586
1587 if (trace->ev_qualifier_ids.entries == NULL) {
1588 fputs("Error:\tNot enough memory for allocating events qualifier ids\n",
1589 trace->output);
1590 err = -EINVAL;
1591 goto out;
1592 }
1593
1594 i = 0;
1595
d0cc439b
ACM
1596 strlist__for_each(pos, trace->ev_qualifier) {
1597 const char *sc = pos->s;
8b3ce757 1598 int id = audit_name_to_syscall(sc, trace->audit.machine);
d0cc439b 1599
8b3ce757 1600 if (id < 0) {
d0cc439b
ACM
1601 if (err == 0) {
1602 fputs("Error:\tInvalid syscall ", trace->output);
1603 err = -EINVAL;
1604 } else {
1605 fputs(", ", trace->output);
1606 }
1607
1608 fputs(sc, trace->output);
1609 }
8b3ce757
ACM
1610
1611 trace->ev_qualifier_ids.entries[i++] = id;
d0cc439b
ACM
1612 }
1613
1614 if (err < 0) {
1615 fputs("\nHint:\ttry 'perf list syscalls:sys_enter_*'"
1616 "\nHint:\tand: 'man syscalls'\n", trace->output);
8b3ce757
ACM
1617 zfree(&trace->ev_qualifier_ids.entries);
1618 trace->ev_qualifier_ids.nr = 0;
d0cc439b 1619 }
8b3ce757 1620out:
d0cc439b
ACM
1621 return err;
1622}
1623
55d43bca
DA
1624/*
1625 * args is to be interpreted as a series of longs but we need to handle
1626 * 8-byte unaligned accesses. args points to raw_data within the event
1627 * and raw_data is guaranteed to be 8-byte unaligned because it is
1628 * preceded by raw_size which is a u32. So we need to copy args to a temp
1629 * variable to read it. Most notably this avoids extended load instructions
1630 * on unaligned addresses
1631 */
1632
752fde44 1633static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
55d43bca 1634 unsigned char *args, struct trace *trace,
75b757ca 1635 struct thread *thread)
514f1c67 1636{
514f1c67 1637 size_t printed = 0;
55d43bca
DA
1638 unsigned char *p;
1639 unsigned long val;
514f1c67 1640
f208bd8d 1641 if (sc->args != NULL) {
514f1c67 1642 struct format_field *field;
01533e97
ACM
1643 u8 bit = 1;
1644 struct syscall_arg arg = {
75b757ca
ACM
1645 .idx = 0,
1646 .mask = 0,
1647 .trace = trace,
1648 .thread = thread,
01533e97 1649 };
6e7eeb51 1650
f208bd8d 1651 for (field = sc->args; field;
01533e97
ACM
1652 field = field->next, ++arg.idx, bit <<= 1) {
1653 if (arg.mask & bit)
6e7eeb51 1654 continue;
55d43bca
DA
1655
1656 /* special care for unaligned accesses */
1657 p = args + sizeof(unsigned long) * arg.idx;
1658 memcpy(&val, p, sizeof(val));
1659
4aa58232
ACM
1660 /*
1661 * Suppress this argument if its value is zero and
1662 * and we don't have a string associated in an
1663 * strarray for it.
1664 */
55d43bca 1665 if (val == 0 &&
4aa58232
ACM
1666 !(sc->arg_scnprintf &&
1667 sc->arg_scnprintf[arg.idx] == SCA_STRARRAY &&
1668 sc->arg_parm[arg.idx]))
22ae5cf1
ACM
1669 continue;
1670
752fde44 1671 printed += scnprintf(bf + printed, size - printed,
13d4ff3e 1672 "%s%s: ", printed ? ", " : "", field->name);
01533e97 1673 if (sc->arg_scnprintf && sc->arg_scnprintf[arg.idx]) {
55d43bca 1674 arg.val = val;
1f115cb7
ACM
1675 if (sc->arg_parm)
1676 arg.parm = sc->arg_parm[arg.idx];
01533e97
ACM
1677 printed += sc->arg_scnprintf[arg.idx](bf + printed,
1678 size - printed, &arg);
6e7eeb51 1679 } else {
13d4ff3e 1680 printed += scnprintf(bf + printed, size - printed,
55d43bca 1681 "%ld", val);
6e7eeb51 1682 }
514f1c67
ACM
1683 }
1684 } else {
01533e97
ACM
1685 int i = 0;
1686
514f1c67 1687 while (i < 6) {
55d43bca
DA
1688 /* special care for unaligned accesses */
1689 p = args + sizeof(unsigned long) * i;
1690 memcpy(&val, p, sizeof(val));
752fde44
ACM
1691 printed += scnprintf(bf + printed, size - printed,
1692 "%sarg%d: %ld",
55d43bca 1693 printed ? ", " : "", i, val);
514f1c67
ACM
1694 ++i;
1695 }
1696 }
1697
1698 return printed;
1699}
1700
ba3d7dee 1701typedef int (*tracepoint_handler)(struct trace *trace, struct perf_evsel *evsel,
0c82adcf 1702 union perf_event *event,
ba3d7dee
ACM
1703 struct perf_sample *sample);
1704
1705static struct syscall *trace__syscall_info(struct trace *trace,
bf2575c1 1706 struct perf_evsel *evsel, int id)
ba3d7dee 1707{
ba3d7dee
ACM
1708
1709 if (id < 0) {
adaa18bf
ACM
1710
1711 /*
1712 * XXX: Noticed on x86_64, reproduced as far back as 3.0.36, haven't tried
1713 * before that, leaving at a higher verbosity level till that is
1714 * explained. Reproduced with plain ftrace with:
1715 *
1716 * echo 1 > /t/events/raw_syscalls/sys_exit/enable
1717 * grep "NR -1 " /t/trace_pipe
1718 *
1719 * After generating some load on the machine.
1720 */
1721 if (verbose > 1) {
1722 static u64 n;
1723 fprintf(trace->output, "Invalid syscall %d id, skipping (%s, %" PRIu64 ") ...\n",
1724 id, perf_evsel__name(evsel), ++n);
1725 }
ba3d7dee
ACM
1726 return NULL;
1727 }
1728
1729 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL) &&
1730 trace__read_syscall_info(trace, id))
1731 goto out_cant_read;
1732
1733 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL))
1734 goto out_cant_read;
1735
1736 return &trace->syscalls.table[id];
1737
1738out_cant_read:
7c304ee0
ACM
1739 if (verbose) {
1740 fprintf(trace->output, "Problems reading syscall %d", id);
1741 if (id <= trace->syscalls.max && trace->syscalls.table[id].name != NULL)
1742 fprintf(trace->output, "(%s)", trace->syscalls.table[id].name);
1743 fputs(" information\n", trace->output);
1744 }
ba3d7dee
ACM
1745 return NULL;
1746}
1747
bf2575c1
DA
1748static void thread__update_stats(struct thread_trace *ttrace,
1749 int id, struct perf_sample *sample)
1750{
1751 struct int_node *inode;
1752 struct stats *stats;
1753 u64 duration = 0;
1754
1755 inode = intlist__findnew(ttrace->syscall_stats, id);
1756 if (inode == NULL)
1757 return;
1758
1759 stats = inode->priv;
1760 if (stats == NULL) {
1761 stats = malloc(sizeof(struct stats));
1762 if (stats == NULL)
1763 return;
1764 init_stats(stats);
1765 inode->priv = stats;
1766 }
1767
1768 if (ttrace->entry_time && sample->time > ttrace->entry_time)
1769 duration = sample->time - ttrace->entry_time;
1770
1771 update_stats(stats, duration);
1772}
1773
e596663e
ACM
1774static int trace__printf_interrupted_entry(struct trace *trace, struct perf_sample *sample)
1775{
1776 struct thread_trace *ttrace;
1777 u64 duration;
1778 size_t printed;
1779
1780 if (trace->current == NULL)
1781 return 0;
1782
1783 ttrace = thread__priv(trace->current);
1784
1785 if (!ttrace->entry_pending)
1786 return 0;
1787
1788 duration = sample->time - ttrace->entry_time;
1789
1790 printed = trace__fprintf_entry_head(trace, trace->current, duration, sample->time, trace->output);
1791 printed += fprintf(trace->output, "%-70s) ...\n", ttrace->entry_str);
1792 ttrace->entry_pending = false;
1793
1794 return printed;
1795}
1796
ba3d7dee 1797static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
0c82adcf 1798 union perf_event *event __maybe_unused,
ba3d7dee
ACM
1799 struct perf_sample *sample)
1800{
752fde44 1801 char *msg;
ba3d7dee 1802 void *args;
752fde44 1803 size_t printed = 0;
2ae3a312 1804 struct thread *thread;
b91fc39f 1805 int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
bf2575c1 1806 struct syscall *sc = trace__syscall_info(trace, evsel, id);
2ae3a312
ACM
1807 struct thread_trace *ttrace;
1808
1809 if (sc == NULL)
1810 return -1;
ba3d7dee 1811
8fb598e5 1812 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
c24ff998 1813 ttrace = thread__trace(thread, trace->output);
2ae3a312 1814 if (ttrace == NULL)
b91fc39f 1815 goto out_put;
ba3d7dee 1816
77170988 1817 args = perf_evsel__sc_tp_ptr(evsel, args, sample);
752fde44
ACM
1818
1819 if (ttrace->entry_str == NULL) {
1820 ttrace->entry_str = malloc(1024);
1821 if (!ttrace->entry_str)
b91fc39f 1822 goto out_put;
752fde44
ACM
1823 }
1824
13f22a2d 1825 if (!trace->summary_only)
6ebad5c1 1826 trace__printf_interrupted_entry(trace, sample);
e596663e 1827
752fde44
ACM
1828 ttrace->entry_time = sample->time;
1829 msg = ttrace->entry_str;
1830 printed += scnprintf(msg + printed, 1024 - printed, "%s(", sc->name);
1831
75b757ca
ACM
1832 printed += syscall__scnprintf_args(sc, msg + printed, 1024 - printed,
1833 args, trace, thread);
752fde44 1834
5089f20e 1835 if (sc->is_exit) {
fd2eabaf 1836 if (!trace->duration_filter && !trace->summary_only) {
c24ff998
ACM
1837 trace__fprintf_entry_head(trace, thread, 1, sample->time, trace->output);
1838 fprintf(trace->output, "%-70s\n", ttrace->entry_str);
ae9ed035 1839 }
752fde44
ACM
1840 } else
1841 ttrace->entry_pending = true;
ba3d7dee 1842
f3b623b8
ACM
1843 if (trace->current != thread) {
1844 thread__put(trace->current);
1845 trace->current = thread__get(thread);
1846 }
b91fc39f
ACM
1847 err = 0;
1848out_put:
1849 thread__put(thread);
1850 return err;
ba3d7dee
ACM
1851}
1852
1853static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
0c82adcf 1854 union perf_event *event __maybe_unused,
ba3d7dee
ACM
1855 struct perf_sample *sample)
1856{
2c82c3ad 1857 long ret;
60c907ab 1858 u64 duration = 0;
2ae3a312 1859 struct thread *thread;
b91fc39f 1860 int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
bf2575c1 1861 struct syscall *sc = trace__syscall_info(trace, evsel, id);
2ae3a312
ACM
1862 struct thread_trace *ttrace;
1863
1864 if (sc == NULL)
1865 return -1;
ba3d7dee 1866
8fb598e5 1867 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
c24ff998 1868 ttrace = thread__trace(thread, trace->output);
2ae3a312 1869 if (ttrace == NULL)
b91fc39f 1870 goto out_put;
ba3d7dee 1871
bf2575c1
DA
1872 if (trace->summary)
1873 thread__update_stats(ttrace, id, sample);
1874
77170988 1875 ret = perf_evsel__sc_tp_uint(evsel, ret, sample);
ba3d7dee 1876
c522739d
ACM
1877 if (id == trace->audit.open_id && ret >= 0 && trace->last_vfs_getname) {
1878 trace__set_fd_pathname(thread, ret, trace->last_vfs_getname);
1879 trace->last_vfs_getname = NULL;
1880 ++trace->stats.vfs_getname;
1881 }
1882
752fde44
ACM
1883 ttrace->exit_time = sample->time;
1884
ae9ed035 1885 if (ttrace->entry_time) {
60c907ab 1886 duration = sample->time - ttrace->entry_time;
ae9ed035
ACM
1887 if (trace__filter_duration(trace, duration))
1888 goto out;
1889 } else if (trace->duration_filter)
1890 goto out;
60c907ab 1891
fd2eabaf
DA
1892 if (trace->summary_only)
1893 goto out;
1894
c24ff998 1895 trace__fprintf_entry_head(trace, thread, duration, sample->time, trace->output);
752fde44
ACM
1896
1897 if (ttrace->entry_pending) {
c24ff998 1898 fprintf(trace->output, "%-70s", ttrace->entry_str);
752fde44 1899 } else {
c24ff998
ACM
1900 fprintf(trace->output, " ... [");
1901 color_fprintf(trace->output, PERF_COLOR_YELLOW, "continued");
1902 fprintf(trace->output, "]: %s()", sc->name);
752fde44
ACM
1903 }
1904
da3c9a44
ACM
1905 if (sc->fmt == NULL) {
1906signed_print:
2c82c3ad 1907 fprintf(trace->output, ") = %ld", ret);
da3c9a44 1908 } else if (ret < 0 && sc->fmt->errmsg) {
942a91ed 1909 char bf[STRERR_BUFSIZE];
ba3d7dee
ACM
1910 const char *emsg = strerror_r(-ret, bf, sizeof(bf)),
1911 *e = audit_errno_to_name(-ret);
1912
c24ff998 1913 fprintf(trace->output, ") = -1 %s %s", e, emsg);
da3c9a44 1914 } else if (ret == 0 && sc->fmt->timeout)
c24ff998 1915 fprintf(trace->output, ") = 0 Timeout");
04b34729 1916 else if (sc->fmt->hexret)
2c82c3ad 1917 fprintf(trace->output, ") = %#lx", ret);
ba3d7dee 1918 else
da3c9a44 1919 goto signed_print;
ba3d7dee 1920
c24ff998 1921 fputc('\n', trace->output);
ae9ed035 1922out:
752fde44 1923 ttrace->entry_pending = false;
b91fc39f
ACM
1924 err = 0;
1925out_put:
1926 thread__put(thread);
1927 return err;
ba3d7dee
ACM
1928}
1929
c522739d 1930static int trace__vfs_getname(struct trace *trace, struct perf_evsel *evsel,
0c82adcf 1931 union perf_event *event __maybe_unused,
c522739d
ACM
1932 struct perf_sample *sample)
1933{
1934 trace->last_vfs_getname = perf_evsel__rawptr(evsel, sample, "pathname");
1935 return 0;
1936}
1937
1302d88e 1938static int trace__sched_stat_runtime(struct trace *trace, struct perf_evsel *evsel,
0c82adcf 1939 union perf_event *event __maybe_unused,
1302d88e
ACM
1940 struct perf_sample *sample)
1941{
1942 u64 runtime = perf_evsel__intval(evsel, sample, "runtime");
1943 double runtime_ms = (double)runtime / NSEC_PER_MSEC;
8fb598e5 1944 struct thread *thread = machine__findnew_thread(trace->host,
314add6b
AH
1945 sample->pid,
1946 sample->tid);
c24ff998 1947 struct thread_trace *ttrace = thread__trace(thread, trace->output);
1302d88e
ACM
1948
1949 if (ttrace == NULL)
1950 goto out_dump;
1951
1952 ttrace->runtime_ms += runtime_ms;
1953 trace->runtime_ms += runtime_ms;
b91fc39f 1954 thread__put(thread);
1302d88e
ACM
1955 return 0;
1956
1957out_dump:
c24ff998 1958 fprintf(trace->output, "%s: comm=%s,pid=%u,runtime=%" PRIu64 ",vruntime=%" PRIu64 ")\n",
1302d88e
ACM
1959 evsel->name,
1960 perf_evsel__strval(evsel, sample, "comm"),
1961 (pid_t)perf_evsel__intval(evsel, sample, "pid"),
1962 runtime,
1963 perf_evsel__intval(evsel, sample, "vruntime"));
b91fc39f 1964 thread__put(thread);
1302d88e
ACM
1965 return 0;
1966}
1967
14a052df
ACM
1968static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
1969 union perf_event *event __maybe_unused,
1970 struct perf_sample *sample)
1971{
1972 trace__printf_interrupted_entry(trace, sample);
1973 trace__fprintf_tstamp(trace, sample->time, trace->output);
0808921a
ACM
1974
1975 if (trace->trace_syscalls)
1976 fprintf(trace->output, "( ): ");
1977
1978 fprintf(trace->output, "%s:", evsel->name);
14a052df
ACM
1979
1980 if (evsel->tp_format) {
1981 event_format__fprintf(evsel->tp_format, sample->cpu,
1982 sample->raw_data, sample->raw_size,
1983 trace->output);
1984 }
1985
1986 fprintf(trace->output, ")\n");
1987 return 0;
1988}
1989
598d02c5
SF
1990static void print_location(FILE *f, struct perf_sample *sample,
1991 struct addr_location *al,
1992 bool print_dso, bool print_sym)
1993{
1994
1995 if ((verbose || print_dso) && al->map)
1996 fprintf(f, "%s@", al->map->dso->long_name);
1997
1998 if ((verbose || print_sym) && al->sym)
4414a3c5 1999 fprintf(f, "%s+0x%" PRIx64, al->sym->name,
598d02c5
SF
2000 al->addr - al->sym->start);
2001 else if (al->map)
4414a3c5 2002 fprintf(f, "0x%" PRIx64, al->addr);
598d02c5 2003 else
4414a3c5 2004 fprintf(f, "0x%" PRIx64, sample->addr);
598d02c5
SF
2005}
2006
2007static int trace__pgfault(struct trace *trace,
2008 struct perf_evsel *evsel,
2009 union perf_event *event,
2010 struct perf_sample *sample)
2011{
2012 struct thread *thread;
2013 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
2014 struct addr_location al;
2015 char map_type = 'd';
a2ea67d7 2016 struct thread_trace *ttrace;
b91fc39f 2017 int err = -1;
598d02c5
SF
2018
2019 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
a2ea67d7
SF
2020 ttrace = thread__trace(thread, trace->output);
2021 if (ttrace == NULL)
b91fc39f 2022 goto out_put;
a2ea67d7
SF
2023
2024 if (evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ)
2025 ttrace->pfmaj++;
2026 else
2027 ttrace->pfmin++;
2028
2029 if (trace->summary_only)
b91fc39f 2030 goto out;
598d02c5 2031
bb871a9c 2032 thread__find_addr_location(thread, cpumode, MAP__FUNCTION,
598d02c5
SF
2033 sample->ip, &al);
2034
2035 trace__fprintf_entry_head(trace, thread, 0, sample->time, trace->output);
2036
2037 fprintf(trace->output, "%sfault [",
2038 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ?
2039 "maj" : "min");
2040
2041 print_location(trace->output, sample, &al, false, true);
2042
2043 fprintf(trace->output, "] => ");
2044
bb871a9c 2045 thread__find_addr_location(thread, cpumode, MAP__VARIABLE,
598d02c5
SF
2046 sample->addr, &al);
2047
2048 if (!al.map) {
bb871a9c 2049 thread__find_addr_location(thread, cpumode,
598d02c5
SF
2050 MAP__FUNCTION, sample->addr, &al);
2051
2052 if (al.map)
2053 map_type = 'x';
2054 else
2055 map_type = '?';
2056 }
2057
2058 print_location(trace->output, sample, &al, true, false);
2059
2060 fprintf(trace->output, " (%c%c)\n", map_type, al.level);
b91fc39f
ACM
2061out:
2062 err = 0;
2063out_put:
2064 thread__put(thread);
2065 return err;
598d02c5
SF
2066}
2067
bdc89661
DA
2068static bool skip_sample(struct trace *trace, struct perf_sample *sample)
2069{
2070 if ((trace->pid_list && intlist__find(trace->pid_list, sample->pid)) ||
2071 (trace->tid_list && intlist__find(trace->tid_list, sample->tid)))
2072 return false;
2073
2074 if (trace->pid_list || trace->tid_list)
2075 return true;
2076
2077 return false;
2078}
2079
6810fc91 2080static int trace__process_sample(struct perf_tool *tool,
0c82adcf 2081 union perf_event *event,
6810fc91
DA
2082 struct perf_sample *sample,
2083 struct perf_evsel *evsel,
2084 struct machine *machine __maybe_unused)
2085{
2086 struct trace *trace = container_of(tool, struct trace, tool);
2087 int err = 0;
2088
744a9719 2089 tracepoint_handler handler = evsel->handler;
6810fc91 2090
bdc89661
DA
2091 if (skip_sample(trace, sample))
2092 return 0;
2093
4bb09192 2094 if (!trace->full_time && trace->base_time == 0)
6810fc91
DA
2095 trace->base_time = sample->time;
2096
3160565f
DA
2097 if (handler) {
2098 ++trace->nr_events;
0c82adcf 2099 handler(trace, evsel, event, sample);
3160565f 2100 }
6810fc91
DA
2101
2102 return err;
2103}
2104
bdc89661
DA
2105static int parse_target_str(struct trace *trace)
2106{
2107 if (trace->opts.target.pid) {
2108 trace->pid_list = intlist__new(trace->opts.target.pid);
2109 if (trace->pid_list == NULL) {
2110 pr_err("Error parsing process id string\n");
2111 return -EINVAL;
2112 }
2113 }
2114
2115 if (trace->opts.target.tid) {
2116 trace->tid_list = intlist__new(trace->opts.target.tid);
2117 if (trace->tid_list == NULL) {
2118 pr_err("Error parsing thread id string\n");
2119 return -EINVAL;
2120 }
2121 }
2122
2123 return 0;
2124}
2125
1e28fe0a 2126static int trace__record(struct trace *trace, int argc, const char **argv)
5e2485b1
DA
2127{
2128 unsigned int rec_argc, i, j;
2129 const char **rec_argv;
2130 const char * const record_args[] = {
2131 "record",
2132 "-R",
2133 "-m", "1024",
2134 "-c", "1",
5e2485b1
DA
2135 };
2136
1e28fe0a
SF
2137 const char * const sc_args[] = { "-e", };
2138 unsigned int sc_args_nr = ARRAY_SIZE(sc_args);
2139 const char * const majpf_args[] = { "-e", "major-faults" };
2140 unsigned int majpf_args_nr = ARRAY_SIZE(majpf_args);
2141 const char * const minpf_args[] = { "-e", "minor-faults" };
2142 unsigned int minpf_args_nr = ARRAY_SIZE(minpf_args);
2143
9aca7f17 2144 /* +1 is for the event string below */
1e28fe0a
SF
2145 rec_argc = ARRAY_SIZE(record_args) + sc_args_nr + 1 +
2146 majpf_args_nr + minpf_args_nr + argc;
5e2485b1
DA
2147 rec_argv = calloc(rec_argc + 1, sizeof(char *));
2148
2149 if (rec_argv == NULL)
2150 return -ENOMEM;
2151
1e28fe0a 2152 j = 0;
5e2485b1 2153 for (i = 0; i < ARRAY_SIZE(record_args); i++)
1e28fe0a
SF
2154 rec_argv[j++] = record_args[i];
2155
e281a960
SF
2156 if (trace->trace_syscalls) {
2157 for (i = 0; i < sc_args_nr; i++)
2158 rec_argv[j++] = sc_args[i];
2159
2160 /* event string may be different for older kernels - e.g., RHEL6 */
2161 if (is_valid_tracepoint("raw_syscalls:sys_enter"))
2162 rec_argv[j++] = "raw_syscalls:sys_enter,raw_syscalls:sys_exit";
2163 else if (is_valid_tracepoint("syscalls:sys_enter"))
2164 rec_argv[j++] = "syscalls:sys_enter,syscalls:sys_exit";
2165 else {
2166 pr_err("Neither raw_syscalls nor syscalls events exist.\n");
2167 return -1;
2168 }
9aca7f17 2169 }
9aca7f17 2170
1e28fe0a
SF
2171 if (trace->trace_pgfaults & TRACE_PFMAJ)
2172 for (i = 0; i < majpf_args_nr; i++)
2173 rec_argv[j++] = majpf_args[i];
2174
2175 if (trace->trace_pgfaults & TRACE_PFMIN)
2176 for (i = 0; i < minpf_args_nr; i++)
2177 rec_argv[j++] = minpf_args[i];
2178
2179 for (i = 0; i < (unsigned int)argc; i++)
2180 rec_argv[j++] = argv[i];
5e2485b1 2181
1e28fe0a 2182 return cmd_record(j, rec_argv, NULL);
5e2485b1
DA
2183}
2184
bf2575c1
DA
2185static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp);
2186
c522739d
ACM
2187static void perf_evlist__add_vfs_getname(struct perf_evlist *evlist)
2188{
ef503831 2189 struct perf_evsel *evsel = perf_evsel__newtp("probe", "vfs_getname");
c522739d
ACM
2190 if (evsel == NULL)
2191 return;
2192
2193 if (perf_evsel__field(evsel, "pathname") == NULL) {
2194 perf_evsel__delete(evsel);
2195 return;
2196 }
2197
744a9719 2198 evsel->handler = trace__vfs_getname;
c522739d
ACM
2199 perf_evlist__add(evlist, evsel);
2200}
2201
598d02c5
SF
2202static int perf_evlist__add_pgfault(struct perf_evlist *evlist,
2203 u64 config)
2204{
2205 struct perf_evsel *evsel;
2206 struct perf_event_attr attr = {
2207 .type = PERF_TYPE_SOFTWARE,
2208 .mmap_data = 1,
598d02c5
SF
2209 };
2210
2211 attr.config = config;
0524798c 2212 attr.sample_period = 1;
598d02c5
SF
2213
2214 event_attr_init(&attr);
2215
2216 evsel = perf_evsel__new(&attr);
2217 if (!evsel)
2218 return -ENOMEM;
2219
2220 evsel->handler = trace__pgfault;
2221 perf_evlist__add(evlist, evsel);
2222
2223 return 0;
2224}
2225
ddbb1b13
ACM
2226static void trace__handle_event(struct trace *trace, union perf_event *event, struct perf_sample *sample)
2227{
2228 const u32 type = event->header.type;
2229 struct perf_evsel *evsel;
2230
2231 if (!trace->full_time && trace->base_time == 0)
2232 trace->base_time = sample->time;
2233
2234 if (type != PERF_RECORD_SAMPLE) {
2235 trace__process_event(trace, trace->host, event, sample);
2236 return;
2237 }
2238
2239 evsel = perf_evlist__id2evsel(trace->evlist, sample->id);
2240 if (evsel == NULL) {
2241 fprintf(trace->output, "Unknown tp ID %" PRIu64 ", skipping...\n", sample->id);
2242 return;
2243 }
2244
2245 if (evsel->attr.type == PERF_TYPE_TRACEPOINT &&
2246 sample->raw_data == NULL) {
2247 fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n",
2248 perf_evsel__name(evsel), sample->tid,
2249 sample->cpu, sample->raw_size);
2250 } else {
2251 tracepoint_handler handler = evsel->handler;
2252 handler(trace, evsel, event, sample);
2253 }
2254}
2255
c27366f0
ACM
2256static int trace__add_syscall_newtp(struct trace *trace)
2257{
2258 int ret = -1;
2259 struct perf_evlist *evlist = trace->evlist;
2260 struct perf_evsel *sys_enter, *sys_exit;
2261
2262 sys_enter = perf_evsel__syscall_newtp("sys_enter", trace__sys_enter);
2263 if (sys_enter == NULL)
2264 goto out;
2265
2266 if (perf_evsel__init_sc_tp_ptr_field(sys_enter, args))
2267 goto out_delete_sys_enter;
2268
2269 sys_exit = perf_evsel__syscall_newtp("sys_exit", trace__sys_exit);
2270 if (sys_exit == NULL)
2271 goto out_delete_sys_enter;
2272
2273 if (perf_evsel__init_sc_tp_uint_field(sys_exit, ret))
2274 goto out_delete_sys_exit;
2275
2276 perf_evlist__add(evlist, sys_enter);
2277 perf_evlist__add(evlist, sys_exit);
2278
8b3ce757
ACM
2279 trace->syscalls.events.sys_enter = sys_enter;
2280 trace->syscalls.events.sys_exit = sys_exit;
c27366f0
ACM
2281
2282 ret = 0;
2283out:
2284 return ret;
2285
2286out_delete_sys_exit:
2287 perf_evsel__delete_priv(sys_exit);
2288out_delete_sys_enter:
2289 perf_evsel__delete_priv(sys_enter);
2290 goto out;
2291}
2292
19867b61
ACM
2293static int trace__set_ev_qualifier_filter(struct trace *trace)
2294{
2295 int err = -1;
2296 char *filter = asprintf_expr_inout_ints("id", !trace->not_ev_qualifier,
2297 trace->ev_qualifier_ids.nr,
2298 trace->ev_qualifier_ids.entries);
2299
2300 if (filter == NULL)
2301 goto out_enomem;
2302
2303 if (!perf_evsel__append_filter(trace->syscalls.events.sys_enter, "&&", filter))
2304 err = perf_evsel__append_filter(trace->syscalls.events.sys_exit, "&&", filter);
2305
2306 free(filter);
2307out:
2308 return err;
2309out_enomem:
2310 errno = ENOMEM;
2311 goto out;
2312}
c27366f0 2313
f15eb531 2314static int trace__run(struct trace *trace, int argc, const char **argv)
514f1c67 2315{
14a052df 2316 struct perf_evlist *evlist = trace->evlist;
94ad89bc 2317 struct perf_evsel *evsel;
efd5745e
ACM
2318 int err = -1, i;
2319 unsigned long before;
f15eb531 2320 const bool forks = argc > 0;
46fb3c21 2321 bool draining = false;
514f1c67 2322
75b757ca
ACM
2323 trace->live = true;
2324
c27366f0 2325 if (trace->trace_syscalls && trace__add_syscall_newtp(trace))
801c67b0 2326 goto out_error_raw_syscalls;
514f1c67 2327
e281a960
SF
2328 if (trace->trace_syscalls)
2329 perf_evlist__add_vfs_getname(evlist);
c522739d 2330
598d02c5 2331 if ((trace->trace_pgfaults & TRACE_PFMAJ) &&
e2726d99 2332 perf_evlist__add_pgfault(evlist, PERF_COUNT_SW_PAGE_FAULTS_MAJ)) {
5ed08dae 2333 goto out_error_mem;
e2726d99 2334 }
598d02c5
SF
2335
2336 if ((trace->trace_pgfaults & TRACE_PFMIN) &&
2337 perf_evlist__add_pgfault(evlist, PERF_COUNT_SW_PAGE_FAULTS_MIN))
5ed08dae 2338 goto out_error_mem;
598d02c5 2339
1302d88e 2340 if (trace->sched &&
2cc990ba
ACM
2341 perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime",
2342 trace__sched_stat_runtime))
2343 goto out_error_sched_stat_runtime;
1302d88e 2344
514f1c67
ACM
2345 err = perf_evlist__create_maps(evlist, &trace->opts.target);
2346 if (err < 0) {
c24ff998 2347 fprintf(trace->output, "Problems parsing the target to trace, check your options!\n");
514f1c67
ACM
2348 goto out_delete_evlist;
2349 }
2350
752fde44
ACM
2351 err = trace__symbols_init(trace, evlist);
2352 if (err < 0) {
c24ff998 2353 fprintf(trace->output, "Problems initializing symbol libraries!\n");
03ad9747 2354 goto out_delete_evlist;
752fde44
ACM
2355 }
2356
f77a9518 2357 perf_evlist__config(evlist, &trace->opts);
514f1c67 2358
f15eb531
NK
2359 signal(SIGCHLD, sig_handler);
2360 signal(SIGINT, sig_handler);
2361
2362 if (forks) {
6ef73ec4 2363 err = perf_evlist__prepare_workload(evlist, &trace->opts.target,
735f7e0b 2364 argv, false, NULL);
f15eb531 2365 if (err < 0) {
c24ff998 2366 fprintf(trace->output, "Couldn't run the workload!\n");
03ad9747 2367 goto out_delete_evlist;
f15eb531
NK
2368 }
2369 }
2370
514f1c67 2371 err = perf_evlist__open(evlist);
a8f23d8f
ACM
2372 if (err < 0)
2373 goto out_error_open;
514f1c67 2374
241b057c
ACM
2375 /*
2376 * Better not use !target__has_task() here because we need to cover the
2377 * case where no threads were specified in the command line, but a
2378 * workload was, and in that case we will fill in the thread_map when
2379 * we fork the workload in perf_evlist__prepare_workload.
2380 */
f078c385
ACM
2381 if (trace->filter_pids.nr > 0)
2382 err = perf_evlist__set_filter_pids(evlist, trace->filter_pids.nr, trace->filter_pids.entries);
e13798c7 2383 else if (thread_map__pid(evlist->threads, 0) == -1)
f078c385
ACM
2384 err = perf_evlist__set_filter_pid(evlist, getpid());
2385
94ad89bc
ACM
2386 if (err < 0)
2387 goto out_error_mem;
2388
19867b61
ACM
2389 if (trace->ev_qualifier_ids.nr > 0) {
2390 err = trace__set_ev_qualifier_filter(trace);
2391 if (err < 0)
2392 goto out_errno;
2393 }
2394
2395 pr_debug("%s\n", trace->syscalls.events.sys_exit->filter);
2396
94ad89bc
ACM
2397 err = perf_evlist__apply_filters(evlist, &evsel);
2398 if (err < 0)
2399 goto out_error_apply_filters;
241b057c 2400
f885037e 2401 err = perf_evlist__mmap(evlist, trace->opts.mmap_pages, false);
e09b18d4
ACM
2402 if (err < 0)
2403 goto out_error_mmap;
514f1c67 2404
cb24d01d
ACM
2405 if (!target__none(&trace->opts.target))
2406 perf_evlist__enable(evlist);
2407
f15eb531
NK
2408 if (forks)
2409 perf_evlist__start_workload(evlist);
2410
e13798c7 2411 trace->multiple_threads = thread_map__pid(evlist->threads, 0) == -1 ||
42052bea
ACM
2412 evlist->threads->nr > 1 ||
2413 perf_evlist__first(evlist)->attr.inherit;
514f1c67 2414again:
efd5745e 2415 before = trace->nr_events;
514f1c67
ACM
2416
2417 for (i = 0; i < evlist->nr_mmaps; i++) {
2418 union perf_event *event;
2419
2420 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
514f1c67 2421 struct perf_sample sample;
514f1c67 2422
efd5745e 2423 ++trace->nr_events;
514f1c67 2424
514f1c67
ACM
2425 err = perf_evlist__parse_sample(evlist, event, &sample);
2426 if (err) {
c24ff998 2427 fprintf(trace->output, "Can't parse sample, err = %d, skipping...\n", err);
8e50d384 2428 goto next_event;
514f1c67
ACM
2429 }
2430
ddbb1b13 2431 trace__handle_event(trace, event, &sample);
8e50d384
ZZ
2432next_event:
2433 perf_evlist__mmap_consume(evlist, i);
20c5f10e 2434
ba209f85
ACM
2435 if (interrupted)
2436 goto out_disable;
02ac5421
ACM
2437
2438 if (done && !draining) {
2439 perf_evlist__disable(evlist);
2440 draining = true;
2441 }
514f1c67
ACM
2442 }
2443 }
2444
efd5745e 2445 if (trace->nr_events == before) {
ba209f85 2446 int timeout = done ? 100 : -1;
f15eb531 2447
46fb3c21
ACM
2448 if (!draining && perf_evlist__poll(evlist, timeout) > 0) {
2449 if (perf_evlist__filter_pollfd(evlist, POLLERR | POLLHUP) == 0)
2450 draining = true;
2451
ba209f85 2452 goto again;
46fb3c21 2453 }
ba209f85
ACM
2454 } else {
2455 goto again;
f15eb531
NK
2456 }
2457
ba209f85 2458out_disable:
f3b623b8
ACM
2459 thread__zput(trace->current);
2460
ba209f85 2461 perf_evlist__disable(evlist);
514f1c67 2462
c522739d
ACM
2463 if (!err) {
2464 if (trace->summary)
2465 trace__fprintf_thread_summary(trace, trace->output);
2466
2467 if (trace->show_tool_stats) {
2468 fprintf(trace->output, "Stats:\n "
2469 " vfs_getname : %" PRIu64 "\n"
2470 " proc_getname: %" PRIu64 "\n",
2471 trace->stats.vfs_getname,
2472 trace->stats.proc_getname);
2473 }
2474 }
bf2575c1 2475
514f1c67
ACM
2476out_delete_evlist:
2477 perf_evlist__delete(evlist);
14a052df 2478 trace->evlist = NULL;
75b757ca 2479 trace->live = false;
514f1c67 2480 return err;
6ef068cb
ACM
2481{
2482 char errbuf[BUFSIZ];
a8f23d8f 2483
2cc990ba
ACM
2484out_error_sched_stat_runtime:
2485 debugfs__strerror_open_tp(errno, errbuf, sizeof(errbuf), "sched", "sched_stat_runtime");
2486 goto out_error;
2487
801c67b0 2488out_error_raw_syscalls:
2cc990ba 2489 debugfs__strerror_open_tp(errno, errbuf, sizeof(errbuf), "raw_syscalls", "sys_(enter|exit)");
a8f23d8f
ACM
2490 goto out_error;
2491
e09b18d4
ACM
2492out_error_mmap:
2493 perf_evlist__strerror_mmap(evlist, errno, errbuf, sizeof(errbuf));
2494 goto out_error;
2495
a8f23d8f
ACM
2496out_error_open:
2497 perf_evlist__strerror_open(evlist, errno, errbuf, sizeof(errbuf));
2498
2499out_error:
6ef068cb 2500 fprintf(trace->output, "%s\n", errbuf);
87f91868 2501 goto out_delete_evlist;
94ad89bc
ACM
2502
2503out_error_apply_filters:
2504 fprintf(trace->output,
2505 "Failed to set filter \"%s\" on event %s with %d (%s)\n",
2506 evsel->filter, perf_evsel__name(evsel), errno,
2507 strerror_r(errno, errbuf, sizeof(errbuf)));
2508 goto out_delete_evlist;
514f1c67 2509}
5ed08dae
ACM
2510out_error_mem:
2511 fprintf(trace->output, "Not enough memory to run!\n");
2512 goto out_delete_evlist;
19867b61
ACM
2513
2514out_errno:
2515 fprintf(trace->output, "errno=%d,%s\n", errno, strerror(errno));
2516 goto out_delete_evlist;
a8f23d8f 2517}
514f1c67 2518
6810fc91
DA
2519static int trace__replay(struct trace *trace)
2520{
2521 const struct perf_evsel_str_handler handlers[] = {
c522739d 2522 { "probe:vfs_getname", trace__vfs_getname, },
6810fc91 2523 };
f5fc1412
JO
2524 struct perf_data_file file = {
2525 .path = input_name,
2526 .mode = PERF_DATA_MODE_READ,
e366a6d8 2527 .force = trace->force,
f5fc1412 2528 };
6810fc91 2529 struct perf_session *session;
003824e8 2530 struct perf_evsel *evsel;
6810fc91
DA
2531 int err = -1;
2532
2533 trace->tool.sample = trace__process_sample;
2534 trace->tool.mmap = perf_event__process_mmap;
384c671e 2535 trace->tool.mmap2 = perf_event__process_mmap2;
6810fc91
DA
2536 trace->tool.comm = perf_event__process_comm;
2537 trace->tool.exit = perf_event__process_exit;
2538 trace->tool.fork = perf_event__process_fork;
2539 trace->tool.attr = perf_event__process_attr;
2540 trace->tool.tracing_data = perf_event__process_tracing_data;
2541 trace->tool.build_id = perf_event__process_build_id;
2542
0a8cb85c 2543 trace->tool.ordered_events = true;
6810fc91
DA
2544 trace->tool.ordering_requires_timestamps = true;
2545
2546 /* add tid to output */
2547 trace->multiple_threads = true;
2548
f5fc1412 2549 session = perf_session__new(&file, false, &trace->tool);
6810fc91 2550 if (session == NULL)
52e02834 2551 return -1;
6810fc91 2552
0a7e6d1b 2553 if (symbol__init(&session->header.env) < 0)
cb2ffae2
NK
2554 goto out;
2555
8fb598e5
DA
2556 trace->host = &session->machines.host;
2557
6810fc91
DA
2558 err = perf_session__set_tracepoints_handlers(session, handlers);
2559 if (err)
2560 goto out;
2561
003824e8
NK
2562 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2563 "raw_syscalls:sys_enter");
9aca7f17
DA
2564 /* older kernels have syscalls tp versus raw_syscalls */
2565 if (evsel == NULL)
2566 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2567 "syscalls:sys_enter");
003824e8 2568
e281a960
SF
2569 if (evsel &&
2570 (perf_evsel__init_syscall_tp(evsel, trace__sys_enter) < 0 ||
2571 perf_evsel__init_sc_tp_ptr_field(evsel, args))) {
003824e8
NK
2572 pr_err("Error during initialize raw_syscalls:sys_enter event\n");
2573 goto out;
2574 }
2575
2576 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2577 "raw_syscalls:sys_exit");
9aca7f17
DA
2578 if (evsel == NULL)
2579 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2580 "syscalls:sys_exit");
e281a960
SF
2581 if (evsel &&
2582 (perf_evsel__init_syscall_tp(evsel, trace__sys_exit) < 0 ||
2583 perf_evsel__init_sc_tp_uint_field(evsel, ret))) {
003824e8 2584 pr_err("Error during initialize raw_syscalls:sys_exit event\n");
6810fc91
DA
2585 goto out;
2586 }
2587
1e28fe0a
SF
2588 evlist__for_each(session->evlist, evsel) {
2589 if (evsel->attr.type == PERF_TYPE_SOFTWARE &&
2590 (evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ||
2591 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MIN ||
2592 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS))
2593 evsel->handler = trace__pgfault;
2594 }
2595
bdc89661
DA
2596 err = parse_target_str(trace);
2597 if (err != 0)
2598 goto out;
2599
6810fc91
DA
2600 setup_pager();
2601
b7b61cbe 2602 err = perf_session__process_events(session);
6810fc91
DA
2603 if (err)
2604 pr_err("Failed to process events, error %d", err);
2605
bf2575c1
DA
2606 else if (trace->summary)
2607 trace__fprintf_thread_summary(trace, trace->output);
2608
6810fc91
DA
2609out:
2610 perf_session__delete(session);
2611
2612 return err;
2613}
2614
1302d88e
ACM
2615static size_t trace__fprintf_threads_header(FILE *fp)
2616{
2617 size_t printed;
2618
99ff7150 2619 printed = fprintf(fp, "\n Summary of events:\n\n");
bf2575c1
DA
2620
2621 return printed;
2622}
2623
2624static size_t thread__dump_stats(struct thread_trace *ttrace,
2625 struct trace *trace, FILE *fp)
2626{
2627 struct stats *stats;
2628 size_t printed = 0;
2629 struct syscall *sc;
2630 struct int_node *inode = intlist__first(ttrace->syscall_stats);
2631
2632 if (inode == NULL)
2633 return 0;
2634
2635 printed += fprintf(fp, "\n");
2636
27a778b5
PE
2637 printed += fprintf(fp, " syscall calls min avg max stddev\n");
2638 printed += fprintf(fp, " (msec) (msec) (msec) (%%)\n");
2639 printed += fprintf(fp, " --------------- -------- --------- --------- --------- ------\n");
99ff7150 2640
bf2575c1
DA
2641 /* each int_node is a syscall */
2642 while (inode) {
2643 stats = inode->priv;
2644 if (stats) {
2645 double min = (double)(stats->min) / NSEC_PER_MSEC;
2646 double max = (double)(stats->max) / NSEC_PER_MSEC;
2647 double avg = avg_stats(stats);
2648 double pct;
2649 u64 n = (u64) stats->n;
2650
2651 pct = avg ? 100.0 * stddev_stats(stats)/avg : 0.0;
2652 avg /= NSEC_PER_MSEC;
2653
2654 sc = &trace->syscalls.table[inode->i];
99ff7150 2655 printed += fprintf(fp, " %-15s", sc->name);
27a778b5 2656 printed += fprintf(fp, " %8" PRIu64 " %9.3f %9.3f",
7f7a4138 2657 n, min, avg);
27a778b5 2658 printed += fprintf(fp, " %9.3f %9.2f%%\n", max, pct);
bf2575c1
DA
2659 }
2660
2661 inode = intlist__next(inode);
2662 }
2663
2664 printed += fprintf(fp, "\n\n");
1302d88e
ACM
2665
2666 return printed;
2667}
2668
896cbb56
DA
2669/* struct used to pass data to per-thread function */
2670struct summary_data {
2671 FILE *fp;
2672 struct trace *trace;
2673 size_t printed;
2674};
2675
2676static int trace__fprintf_one_thread(struct thread *thread, void *priv)
2677{
2678 struct summary_data *data = priv;
2679 FILE *fp = data->fp;
2680 size_t printed = data->printed;
2681 struct trace *trace = data->trace;
89dceb22 2682 struct thread_trace *ttrace = thread__priv(thread);
896cbb56
DA
2683 double ratio;
2684
2685 if (ttrace == NULL)
2686 return 0;
2687
2688 ratio = (double)ttrace->nr_events / trace->nr_events * 100.0;
2689
15e65c69 2690 printed += fprintf(fp, " %s (%d), ", thread__comm_str(thread), thread->tid);
99ff7150 2691 printed += fprintf(fp, "%lu events, ", ttrace->nr_events);
15e65c69 2692 printed += fprintf(fp, "%.1f%%", ratio);
a2ea67d7
SF
2693 if (ttrace->pfmaj)
2694 printed += fprintf(fp, ", %lu majfaults", ttrace->pfmaj);
2695 if (ttrace->pfmin)
2696 printed += fprintf(fp, ", %lu minfaults", ttrace->pfmin);
99ff7150 2697 printed += fprintf(fp, ", %.3f msec\n", ttrace->runtime_ms);
bf2575c1 2698 printed += thread__dump_stats(ttrace, trace, fp);
896cbb56
DA
2699
2700 data->printed += printed;
2701
2702 return 0;
2703}
2704
1302d88e
ACM
2705static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp)
2706{
896cbb56
DA
2707 struct summary_data data = {
2708 .fp = fp,
2709 .trace = trace
2710 };
2711 data.printed = trace__fprintf_threads_header(fp);
1302d88e 2712
896cbb56
DA
2713 machine__for_each_thread(trace->host, trace__fprintf_one_thread, &data);
2714
2715 return data.printed;
1302d88e
ACM
2716}
2717
ae9ed035
ACM
2718static int trace__set_duration(const struct option *opt, const char *str,
2719 int unset __maybe_unused)
2720{
2721 struct trace *trace = opt->value;
2722
2723 trace->duration_filter = atof(str);
2724 return 0;
2725}
2726
f078c385
ACM
2727static int trace__set_filter_pids(const struct option *opt, const char *str,
2728 int unset __maybe_unused)
2729{
2730 int ret = -1;
2731 size_t i;
2732 struct trace *trace = opt->value;
2733 /*
2734 * FIXME: introduce a intarray class, plain parse csv and create a
2735 * { int nr, int entries[] } struct...
2736 */
2737 struct intlist *list = intlist__new(str);
2738
2739 if (list == NULL)
2740 return -1;
2741
2742 i = trace->filter_pids.nr = intlist__nr_entries(list) + 1;
2743 trace->filter_pids.entries = calloc(i, sizeof(pid_t));
2744
2745 if (trace->filter_pids.entries == NULL)
2746 goto out;
2747
2748 trace->filter_pids.entries[0] = getpid();
2749
2750 for (i = 1; i < trace->filter_pids.nr; ++i)
2751 trace->filter_pids.entries[i] = intlist__entry(list, i - 1)->i;
2752
2753 intlist__delete(list);
2754 ret = 0;
2755out:
2756 return ret;
2757}
2758
c24ff998
ACM
2759static int trace__open_output(struct trace *trace, const char *filename)
2760{
2761 struct stat st;
2762
2763 if (!stat(filename, &st) && st.st_size) {
2764 char oldname[PATH_MAX];
2765
2766 scnprintf(oldname, sizeof(oldname), "%s.old", filename);
2767 unlink(oldname);
2768 rename(filename, oldname);
2769 }
2770
2771 trace->output = fopen(filename, "w");
2772
2773 return trace->output == NULL ? -errno : 0;
2774}
2775
598d02c5
SF
2776static int parse_pagefaults(const struct option *opt, const char *str,
2777 int unset __maybe_unused)
2778{
2779 int *trace_pgfaults = opt->value;
2780
2781 if (strcmp(str, "all") == 0)
2782 *trace_pgfaults |= TRACE_PFMAJ | TRACE_PFMIN;
2783 else if (strcmp(str, "maj") == 0)
2784 *trace_pgfaults |= TRACE_PFMAJ;
2785 else if (strcmp(str, "min") == 0)
2786 *trace_pgfaults |= TRACE_PFMIN;
2787 else
2788 return -1;
2789
2790 return 0;
2791}
2792
14a052df
ACM
2793static void evlist__set_evsel_handler(struct perf_evlist *evlist, void *handler)
2794{
2795 struct perf_evsel *evsel;
2796
2797 evlist__for_each(evlist, evsel)
2798 evsel->handler = handler;
2799}
2800
514f1c67
ACM
2801int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
2802{
6fdd9cb7 2803 const char *trace_usage[] = {
f15eb531
NK
2804 "perf trace [<options>] [<command>]",
2805 "perf trace [<options>] -- <command> [<options>]",
5e2485b1
DA
2806 "perf trace record [<options>] [<command>]",
2807 "perf trace record [<options>] -- <command> [<options>]",
514f1c67
ACM
2808 NULL
2809 };
2810 struct trace trace = {
c522739d
ACM
2811 .audit = {
2812 .machine = audit_detect_machine(),
2813 .open_id = audit_name_to_syscall("open", trace.audit.machine),
2814 },
514f1c67
ACM
2815 .syscalls = {
2816 . max = -1,
2817 },
2818 .opts = {
2819 .target = {
2820 .uid = UINT_MAX,
2821 .uses_mmap = true,
2822 },
2823 .user_freq = UINT_MAX,
2824 .user_interval = ULLONG_MAX,
509051ea 2825 .no_buffering = true,
38d5447d 2826 .mmap_pages = UINT_MAX,
9d9cad76 2827 .proc_map_timeout = 500,
514f1c67 2828 },
c24ff998 2829 .output = stdout,
50c95cbd 2830 .show_comm = true,
e281a960 2831 .trace_syscalls = true,
514f1c67 2832 };
c24ff998 2833 const char *output_name = NULL;
2ae3a312 2834 const char *ev_qualifier_str = NULL;
514f1c67 2835 const struct option trace_options[] = {
14a052df
ACM
2836 OPT_CALLBACK(0, "event", &trace.evlist, "event",
2837 "event selector. use 'perf list' to list available events",
2838 parse_events_option),
50c95cbd
ACM
2839 OPT_BOOLEAN(0, "comm", &trace.show_comm,
2840 "show the thread COMM next to its id"),
c522739d 2841 OPT_BOOLEAN(0, "tool_stats", &trace.show_tool_stats, "show tool stats"),
d303e85a 2842 OPT_STRING('e', "expr", &ev_qualifier_str, "expr", "list of syscalls to trace"),
c24ff998 2843 OPT_STRING('o', "output", &output_name, "file", "output file name"),
6810fc91 2844 OPT_STRING('i', "input", &input_name, "file", "Analyze events in file"),
514f1c67
ACM
2845 OPT_STRING('p', "pid", &trace.opts.target.pid, "pid",
2846 "trace events on existing process id"),
ac9be8ee 2847 OPT_STRING('t', "tid", &trace.opts.target.tid, "tid",
514f1c67 2848 "trace events on existing thread id"),
fa0e4ffe
ACM
2849 OPT_CALLBACK(0, "filter-pids", &trace, "CSV list of pids",
2850 "pids to filter (by the kernel)", trace__set_filter_pids),
ac9be8ee 2851 OPT_BOOLEAN('a', "all-cpus", &trace.opts.target.system_wide,
514f1c67 2852 "system-wide collection from all CPUs"),
ac9be8ee 2853 OPT_STRING('C', "cpu", &trace.opts.target.cpu_list, "cpu",
514f1c67 2854 "list of cpus to monitor"),
6810fc91 2855 OPT_BOOLEAN(0, "no-inherit", &trace.opts.no_inherit,
514f1c67 2856 "child tasks do not inherit counters"),
994a1f78
JO
2857 OPT_CALLBACK('m', "mmap-pages", &trace.opts.mmap_pages, "pages",
2858 "number of mmap data pages",
2859 perf_evlist__parse_mmap_pages),
ac9be8ee 2860 OPT_STRING('u', "uid", &trace.opts.target.uid_str, "user",
514f1c67 2861 "user to profile"),
ae9ed035
ACM
2862 OPT_CALLBACK(0, "duration", &trace, "float",
2863 "show only events with duration > N.M ms",
2864 trace__set_duration),
1302d88e 2865 OPT_BOOLEAN(0, "sched", &trace.sched, "show blocking scheduler events"),
7c304ee0 2866 OPT_INCR('v', "verbose", &verbose, "be more verbose"),
4bb09192
DA
2867 OPT_BOOLEAN('T', "time", &trace.full_time,
2868 "Show full timestamp, not time relative to first start"),
fd2eabaf
DA
2869 OPT_BOOLEAN('s', "summary", &trace.summary_only,
2870 "Show only syscall summary with statistics"),
2871 OPT_BOOLEAN('S', "with-summary", &trace.summary,
2872 "Show all syscalls and summary with statistics"),
598d02c5
SF
2873 OPT_CALLBACK_DEFAULT('F', "pf", &trace.trace_pgfaults, "all|maj|min",
2874 "Trace pagefaults", parse_pagefaults, "maj"),
e281a960 2875 OPT_BOOLEAN(0, "syscalls", &trace.trace_syscalls, "Trace syscalls"),
e366a6d8 2876 OPT_BOOLEAN('f', "force", &trace.force, "don't complain, do it"),
9d9cad76
KL
2877 OPT_UINTEGER(0, "proc-map-timeout", &trace.opts.proc_map_timeout,
2878 "per thread proc mmap processing timeout in ms"),
514f1c67
ACM
2879 OPT_END()
2880 };
6fdd9cb7 2881 const char * const trace_subcommands[] = { "record", NULL };
514f1c67 2882 int err;
32caf0d1 2883 char bf[BUFSIZ];
514f1c67 2884
4d08cb80
ACM
2885 signal(SIGSEGV, sighandler_dump_stack);
2886 signal(SIGFPE, sighandler_dump_stack);
2887
14a052df 2888 trace.evlist = perf_evlist__new();
14a052df
ACM
2889
2890 if (trace.evlist == NULL) {
2891 pr_err("Not enough memory to run!\n");
ff8f695c 2892 err = -ENOMEM;
14a052df
ACM
2893 goto out;
2894 }
2895
6fdd9cb7
YS
2896 argc = parse_options_subcommand(argc, argv, trace_options, trace_subcommands,
2897 trace_usage, PARSE_OPT_STOP_AT_NON_OPTION);
fd2eabaf 2898
598d02c5
SF
2899 if (trace.trace_pgfaults) {
2900 trace.opts.sample_address = true;
2901 trace.opts.sample_time = true;
2902 }
2903
14a052df
ACM
2904 if (trace.evlist->nr_entries > 0)
2905 evlist__set_evsel_handler(trace.evlist, trace__event_handler);
2906
1e28fe0a
SF
2907 if ((argc >= 1) && (strcmp(argv[0], "record") == 0))
2908 return trace__record(&trace, argc-1, &argv[1]);
2909
2910 /* summary_only implies summary option, but don't overwrite summary if set */
2911 if (trace.summary_only)
2912 trace.summary = trace.summary_only;
2913
726f3234
ACM
2914 if (!trace.trace_syscalls && !trace.trace_pgfaults &&
2915 trace.evlist->nr_entries == 0 /* Was --events used? */) {
e281a960
SF
2916 pr_err("Please specify something to trace.\n");
2917 return -1;
2918 }
2919
c24ff998
ACM
2920 if (output_name != NULL) {
2921 err = trace__open_output(&trace, output_name);
2922 if (err < 0) {
2923 perror("failed to create output file");
2924 goto out;
2925 }
2926 }
2927
2ae3a312 2928 if (ev_qualifier_str != NULL) {
b059efdf
ACM
2929 const char *s = ev_qualifier_str;
2930
2931 trace.not_ev_qualifier = *s == '!';
2932 if (trace.not_ev_qualifier)
2933 ++s;
4a77e218 2934 trace.ev_qualifier = strlist__new(s, NULL);
2ae3a312 2935 if (trace.ev_qualifier == NULL) {
c24ff998
ACM
2936 fputs("Not enough memory to parse event qualifier",
2937 trace.output);
2938 err = -ENOMEM;
2939 goto out_close;
2ae3a312 2940 }
d0cc439b
ACM
2941
2942 err = trace__validate_ev_qualifier(&trace);
2943 if (err)
2944 goto out_close;
2ae3a312
ACM
2945 }
2946
602ad878 2947 err = target__validate(&trace.opts.target);
32caf0d1 2948 if (err) {
602ad878 2949 target__strerror(&trace.opts.target, err, bf, sizeof(bf));
c24ff998
ACM
2950 fprintf(trace.output, "%s", bf);
2951 goto out_close;
32caf0d1
NK
2952 }
2953
602ad878 2954 err = target__parse_uid(&trace.opts.target);
514f1c67 2955 if (err) {
602ad878 2956 target__strerror(&trace.opts.target, err, bf, sizeof(bf));
c24ff998
ACM
2957 fprintf(trace.output, "%s", bf);
2958 goto out_close;
514f1c67
ACM
2959 }
2960
602ad878 2961 if (!argc && target__none(&trace.opts.target))
ee76120e
NK
2962 trace.opts.target.system_wide = true;
2963
6810fc91
DA
2964 if (input_name)
2965 err = trace__replay(&trace);
2966 else
2967 err = trace__run(&trace, argc, argv);
1302d88e 2968
c24ff998
ACM
2969out_close:
2970 if (output_name != NULL)
2971 fclose(trace.output);
2972out:
1302d88e 2973 return err;
514f1c67 2974}
This page took 0.583685 seconds and 4 git commands to generate.