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