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