Blame view

tools/perf/builtin-trace.c 69.2 KB
4e319027a   Robert Richter   perf tools: Use d...
1
  #include <traceevent/event-parse.h>
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2
  #include "builtin.h"
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
3
  #include "util/color.h"
7c304ee0f   Arnaldo Carvalho de Melo   perf trace: Add -...
4
  #include "util/debug.h"
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
5
  #include "util/evlist.h"
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
6
  #include "util/machine.h"
6810fc915   David Ahern   perf trace: Add o...
7
  #include "util/session.h"
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
8
  #include "util/thread.h"
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
9
  #include "util/parse-options.h"
2ae3a312c   Arnaldo Carvalho de Melo   perf trace: Allow...
10
  #include "util/strlist.h"
bdc896617   David Ahern   perf trace: Honor...
11
  #include "util/intlist.h"
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
12
  #include "util/thread_map.h"
bf2575c12   David Ahern   perf trace: Add s...
13
  #include "util/stat.h"
97978b3e3   Jiri Olsa   perf tools: Add t...
14
  #include "trace-event.h"
9aca7f179   David Ahern   perf trace: Add s...
15
  #include "util/parse-events.h"
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
16
17
18
  
  #include <libaudit.h>
  #include <stdlib.h>
49af9e93a   Arnaldo Carvalho de Melo   perf trace: Beaut...
19
  #include <sys/eventfd.h>
ae685380b   Arnaldo Carvalho de Melo   perf trace: Add b...
20
  #include <sys/mman.h>
f9da0b0c7   Arnaldo Carvalho de Melo   perf trace: Add b...
21
  #include <linux/futex.h>
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
22

456857bde   Ingo Molnar   perf tools: Fill ...
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
  /* For older distros: */
  #ifndef MAP_STACK
  # define MAP_STACK		0x20000
  #endif
  
  #ifndef MADV_HWPOISON
  # define MADV_HWPOISON		100
  #endif
  
  #ifndef MADV_MERGEABLE
  # define MADV_MERGEABLE		12
  #endif
  
  #ifndef MADV_UNMERGEABLE
  # define MADV_UNMERGEABLE	13
  #endif
79d26a6a1   Ben Hutchings   perf trace: Add f...
39
40
41
  #ifndef EFD_SEMAPHORE
  # define EFD_SEMAPHORE		1
  #endif
77170988f   Arnaldo Carvalho de Melo   perf trace: Don't...
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
  struct tp_field {
  	int offset;
  	union {
  		u64 (*integer)(struct tp_field *field, struct perf_sample *sample);
  		void *(*pointer)(struct tp_field *field, struct perf_sample *sample);
  	};
  };
  
  #define TP_UINT_FIELD(bits) \
  static u64 tp_field__u##bits(struct tp_field *field, struct perf_sample *sample) \
  { \
  	return *(u##bits *)(sample->raw_data + field->offset); \
  }
  
  TP_UINT_FIELD(8);
  TP_UINT_FIELD(16);
  TP_UINT_FIELD(32);
  TP_UINT_FIELD(64);
  
  #define TP_UINT_FIELD__SWAPPED(bits) \
  static u64 tp_field__swapped_u##bits(struct tp_field *field, struct perf_sample *sample) \
  { \
  	u##bits value = *(u##bits *)(sample->raw_data + field->offset); \
  	return bswap_##bits(value);\
  }
  
  TP_UINT_FIELD__SWAPPED(16);
  TP_UINT_FIELD__SWAPPED(32);
  TP_UINT_FIELD__SWAPPED(64);
  
  static int tp_field__init_uint(struct tp_field *field,
  			       struct format_field *format_field,
  			       bool needs_swap)
  {
  	field->offset = format_field->offset;
  
  	switch (format_field->size) {
  	case 1:
  		field->integer = tp_field__u8;
  		break;
  	case 2:
  		field->integer = needs_swap ? tp_field__swapped_u16 : tp_field__u16;
  		break;
  	case 4:
  		field->integer = needs_swap ? tp_field__swapped_u32 : tp_field__u32;
  		break;
  	case 8:
  		field->integer = needs_swap ? tp_field__swapped_u64 : tp_field__u64;
  		break;
  	default:
  		return -1;
  	}
  
  	return 0;
  }
  
  static void *tp_field__ptr(struct tp_field *field, struct perf_sample *sample)
  {
  	return sample->raw_data + field->offset;
  }
  
  static int tp_field__init_ptr(struct tp_field *field, struct format_field *format_field)
  {
  	field->offset = format_field->offset;
  	field->pointer = tp_field__ptr;
  	return 0;
  }
  
  struct syscall_tp {
  	struct tp_field id;
  	union {
  		struct tp_field args, ret;
  	};
  };
  
  static int perf_evsel__init_tp_uint_field(struct perf_evsel *evsel,
  					  struct tp_field *field,
  					  const char *name)
  {
  	struct format_field *format_field = perf_evsel__field(evsel, name);
  
  	if (format_field == NULL)
  		return -1;
  
  	return tp_field__init_uint(field, format_field, evsel->needs_swap);
  }
  
  #define perf_evsel__init_sc_tp_uint_field(evsel, name) \
  	({ struct syscall_tp *sc = evsel->priv;\
  	   perf_evsel__init_tp_uint_field(evsel, &sc->name, #name); })
  
  static int perf_evsel__init_tp_ptr_field(struct perf_evsel *evsel,
  					 struct tp_field *field,
  					 const char *name)
  {
  	struct format_field *format_field = perf_evsel__field(evsel, name);
  
  	if (format_field == NULL)
  		return -1;
  
  	return tp_field__init_ptr(field, format_field);
  }
  
  #define perf_evsel__init_sc_tp_ptr_field(evsel, name) \
  	({ struct syscall_tp *sc = evsel->priv;\
  	   perf_evsel__init_tp_ptr_field(evsel, &sc->name, #name); })
  
  static void perf_evsel__delete_priv(struct perf_evsel *evsel)
  {
046625231   Arnaldo Carvalho de Melo   perf tools: Intro...
151
  	zfree(&evsel->priv);
77170988f   Arnaldo Carvalho de Melo   perf trace: Don't...
152
153
  	perf_evsel__delete(evsel);
  }
96695d440   Namhyung Kim   perf trace: Separ...
154
155
156
157
158
159
160
161
162
163
164
165
166
167
  static int perf_evsel__init_syscall_tp(struct perf_evsel *evsel, void *handler)
  {
  	evsel->priv = malloc(sizeof(struct syscall_tp));
  	if (evsel->priv != NULL) {
  		if (perf_evsel__init_sc_tp_uint_field(evsel, id))
  			goto out_delete;
  
  		evsel->handler = handler;
  		return 0;
  	}
  
  	return -ENOMEM;
  
  out_delete:
046625231   Arnaldo Carvalho de Melo   perf tools: Intro...
168
  	zfree(&evsel->priv);
96695d440   Namhyung Kim   perf trace: Separ...
169
170
  	return -ENOENT;
  }
ef503831d   Arnaldo Carvalho de Melo   perf evsel: Remov...
171
  static struct perf_evsel *perf_evsel__syscall_newtp(const char *direction, void *handler)
77170988f   Arnaldo Carvalho de Melo   perf trace: Don't...
172
  {
ef503831d   Arnaldo Carvalho de Melo   perf evsel: Remov...
173
  	struct perf_evsel *evsel = perf_evsel__newtp("raw_syscalls", direction);
77170988f   Arnaldo Carvalho de Melo   perf trace: Don't...
174

9aca7f179   David Ahern   perf trace: Add s...
175
176
177
  	/* older kernel (e.g., RHEL6) use syscalls:{enter,exit} */
  	if (evsel == NULL)
  		evsel = perf_evsel__newtp("syscalls", direction);
77170988f   Arnaldo Carvalho de Melo   perf trace: Don't...
178
  	if (evsel) {
96695d440   Namhyung Kim   perf trace: Separ...
179
  		if (perf_evsel__init_syscall_tp(evsel, handler))
77170988f   Arnaldo Carvalho de Melo   perf trace: Don't...
180
  			goto out_delete;
77170988f   Arnaldo Carvalho de Melo   perf trace: Don't...
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
  	}
  
  	return evsel;
  
  out_delete:
  	perf_evsel__delete_priv(evsel);
  	return NULL;
  }
  
  #define perf_evsel__sc_tp_uint(evsel, name, sample) \
  	({ struct syscall_tp *fields = evsel->priv; \
  	   fields->name.integer(&fields->name, sample); })
  
  #define perf_evsel__sc_tp_ptr(evsel, name, sample) \
  	({ struct syscall_tp *fields = evsel->priv; \
  	   fields->name.pointer(&fields->name, sample); })
  
  static int perf_evlist__add_syscall_newtp(struct perf_evlist *evlist,
  					  void *sys_enter_handler,
  					  void *sys_exit_handler)
  {
  	int ret = -1;
77170988f   Arnaldo Carvalho de Melo   perf trace: Don't...
203
  	struct perf_evsel *sys_enter, *sys_exit;
ef503831d   Arnaldo Carvalho de Melo   perf evsel: Remov...
204
  	sys_enter = perf_evsel__syscall_newtp("sys_enter", sys_enter_handler);
77170988f   Arnaldo Carvalho de Melo   perf trace: Don't...
205
206
207
208
209
  	if (sys_enter == NULL)
  		goto out;
  
  	if (perf_evsel__init_sc_tp_ptr_field(sys_enter, args))
  		goto out_delete_sys_enter;
ef503831d   Arnaldo Carvalho de Melo   perf evsel: Remov...
210
  	sys_exit = perf_evsel__syscall_newtp("sys_exit", sys_exit_handler);
77170988f   Arnaldo Carvalho de Melo   perf trace: Don't...
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
  	if (sys_exit == NULL)
  		goto out_delete_sys_enter;
  
  	if (perf_evsel__init_sc_tp_uint_field(sys_exit, ret))
  		goto out_delete_sys_exit;
  
  	perf_evlist__add(evlist, sys_enter);
  	perf_evlist__add(evlist, sys_exit);
  
  	ret = 0;
  out:
  	return ret;
  
  out_delete_sys_exit:
  	perf_evsel__delete_priv(sys_exit);
  out_delete_sys_enter:
  	perf_evsel__delete_priv(sys_enter);
  	goto out;
  }
01533e972   Arnaldo Carvalho de Melo   perf trace: Put s...
230
231
  struct syscall_arg {
  	unsigned long val;
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
232
233
  	struct thread *thread;
  	struct trace  *trace;
1f115cb72   Arnaldo Carvalho de Melo   perf trace: Allow...
234
  	void	      *parm;
01533e972   Arnaldo Carvalho de Melo   perf trace: Put s...
235
236
237
  	u8	      idx;
  	u8	      mask;
  };
1f115cb72   Arnaldo Carvalho de Melo   perf trace: Allow...
238
  struct strarray {
03e3adc9f   Arnaldo Carvalho de Melo   perf trace: Allow...
239
  	int	    offset;
1f115cb72   Arnaldo Carvalho de Melo   perf trace: Allow...
240
241
242
243
244
245
246
247
  	int	    nr_entries;
  	const char **entries;
  };
  
  #define DEFINE_STRARRAY(array) struct strarray strarray__##array = { \
  	.nr_entries = ARRAY_SIZE(array), \
  	.entries = array, \
  }
03e3adc9f   Arnaldo Carvalho de Melo   perf trace: Allow...
248
249
250
251
252
  #define DEFINE_STRARRAY_OFFSET(array, off) struct strarray strarray__##array = { \
  	.offset	    = off, \
  	.nr_entries = ARRAY_SIZE(array), \
  	.entries = array, \
  }
975b7c2f4   Arnaldo Carvalho de Melo   perf trace: Prepa...
253
254
255
  static size_t __syscall_arg__scnprintf_strarray(char *bf, size_t size,
  						const char *intfmt,
  					        struct syscall_arg *arg)
1f115cb72   Arnaldo Carvalho de Melo   perf trace: Allow...
256
  {
1f115cb72   Arnaldo Carvalho de Melo   perf trace: Allow...
257
  	struct strarray *sa = arg->parm;
03e3adc9f   Arnaldo Carvalho de Melo   perf trace: Allow...
258
  	int idx = arg->val - sa->offset;
1f115cb72   Arnaldo Carvalho de Melo   perf trace: Allow...
259
260
  
  	if (idx < 0 || idx >= sa->nr_entries)
975b7c2f4   Arnaldo Carvalho de Melo   perf trace: Prepa...
261
  		return scnprintf(bf, size, intfmt, arg->val);
1f115cb72   Arnaldo Carvalho de Melo   perf trace: Allow...
262
263
264
  
  	return scnprintf(bf, size, "%s", sa->entries[idx]);
  }
975b7c2f4   Arnaldo Carvalho de Melo   perf trace: Prepa...
265
266
267
268
269
  static size_t syscall_arg__scnprintf_strarray(char *bf, size_t size,
  					      struct syscall_arg *arg)
  {
  	return __syscall_arg__scnprintf_strarray(bf, size, "%d", arg);
  }
1f115cb72   Arnaldo Carvalho de Melo   perf trace: Allow...
270
  #define SCA_STRARRAY syscall_arg__scnprintf_strarray
844ae5b46   Arnaldo Carvalho de Melo   perf trace: Fix i...
271
272
273
274
275
  #if defined(__i386__) || defined(__x86_64__)
  /*
   * FIXME: Make this available to all arches as soon as the ioctl beautifier
   * 	  gets rewritten to support all arches.
   */
78645cf3e   Arnaldo Carvalho de Melo   perf trace: Initi...
276
277
278
279
280
281
282
  static size_t syscall_arg__scnprintf_strhexarray(char *bf, size_t size,
  						 struct syscall_arg *arg)
  {
  	return __syscall_arg__scnprintf_strarray(bf, size, "%#x", arg);
  }
  
  #define SCA_STRHEXARRAY syscall_arg__scnprintf_strhexarray
844ae5b46   Arnaldo Carvalho de Melo   perf trace: Fix i...
283
  #endif /* defined(__i386__) || defined(__x86_64__) */
78645cf3e   Arnaldo Carvalho de Melo   perf trace: Initi...
284

75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
  static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
  					struct syscall_arg *arg);
  
  #define SCA_FD syscall_arg__scnprintf_fd
  
  static size_t syscall_arg__scnprintf_fd_at(char *bf, size_t size,
  					   struct syscall_arg *arg)
  {
  	int fd = arg->val;
  
  	if (fd == AT_FDCWD)
  		return scnprintf(bf, size, "CWD");
  
  	return syscall_arg__scnprintf_fd(bf, size, arg);
  }
  
  #define SCA_FDAT syscall_arg__scnprintf_fd_at
  
  static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
  					      struct syscall_arg *arg);
  
  #define SCA_CLOSE_FD syscall_arg__scnprintf_close_fd
6e7eeb511   Arnaldo Carvalho de Melo   perf trace: Allow...
307
  static size_t syscall_arg__scnprintf_hex(char *bf, size_t size,
01533e972   Arnaldo Carvalho de Melo   perf trace: Put s...
308
  					 struct syscall_arg *arg)
13d4ff3eb   Arnaldo Carvalho de Melo   perf trace: Intro...
309
  {
01533e972   Arnaldo Carvalho de Melo   perf trace: Put s...
310
  	return scnprintf(bf, size, "%#lx", arg->val);
13d4ff3eb   Arnaldo Carvalho de Melo   perf trace: Intro...
311
  }
beccb2b54   Arnaldo Carvalho de Melo   perf trace: Allow...
312
  #define SCA_HEX syscall_arg__scnprintf_hex
6e7eeb511   Arnaldo Carvalho de Melo   perf trace: Allow...
313
  static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size,
01533e972   Arnaldo Carvalho de Melo   perf trace: Put s...
314
  					       struct syscall_arg *arg)
ae685380b   Arnaldo Carvalho de Melo   perf trace: Add b...
315
  {
01533e972   Arnaldo Carvalho de Melo   perf trace: Put s...
316
  	int printed = 0, prot = arg->val;
ae685380b   Arnaldo Carvalho de Melo   perf trace: Add b...
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
  
  	if (prot == PROT_NONE)
  		return scnprintf(bf, size, "NONE");
  #define	P_MMAP_PROT(n) \
  	if (prot & PROT_##n) { \
  		printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
  		prot &= ~PROT_##n; \
  	}
  
  	P_MMAP_PROT(EXEC);
  	P_MMAP_PROT(READ);
  	P_MMAP_PROT(WRITE);
  #ifdef PROT_SEM
  	P_MMAP_PROT(SEM);
  #endif
  	P_MMAP_PROT(GROWSDOWN);
  	P_MMAP_PROT(GROWSUP);
  #undef P_MMAP_PROT
  
  	if (prot)
  		printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", prot);
  
  	return printed;
  }
  
  #define SCA_MMAP_PROT syscall_arg__scnprintf_mmap_prot
6e7eeb511   Arnaldo Carvalho de Melo   perf trace: Allow...
343
  static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size,
01533e972   Arnaldo Carvalho de Melo   perf trace: Put s...
344
  						struct syscall_arg *arg)
941557e0e   Arnaldo Carvalho de Melo   perf trace: Add b...
345
  {
01533e972   Arnaldo Carvalho de Melo   perf trace: Put s...
346
  	int printed = 0, flags = arg->val;
941557e0e   Arnaldo Carvalho de Melo   perf trace: Add b...
347
348
349
350
351
352
353
354
355
  
  #define	P_MMAP_FLAG(n) \
  	if (flags & MAP_##n) { \
  		printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
  		flags &= ~MAP_##n; \
  	}
  
  	P_MMAP_FLAG(SHARED);
  	P_MMAP_FLAG(PRIVATE);
418178156   Kyle McMartin   perf trace: Check...
356
  #ifdef MAP_32BIT
941557e0e   Arnaldo Carvalho de Melo   perf trace: Add b...
357
  	P_MMAP_FLAG(32BIT);
418178156   Kyle McMartin   perf trace: Check...
358
  #endif
941557e0e   Arnaldo Carvalho de Melo   perf trace: Add b...
359
360
361
362
363
364
  	P_MMAP_FLAG(ANONYMOUS);
  	P_MMAP_FLAG(DENYWRITE);
  	P_MMAP_FLAG(EXECUTABLE);
  	P_MMAP_FLAG(FILE);
  	P_MMAP_FLAG(FIXED);
  	P_MMAP_FLAG(GROWSDOWN);
f2935f3e5   David Ahern   perf trace: Handl...
365
  #ifdef MAP_HUGETLB
941557e0e   Arnaldo Carvalho de Melo   perf trace: Add b...
366
  	P_MMAP_FLAG(HUGETLB);
f2935f3e5   David Ahern   perf trace: Handl...
367
  #endif
941557e0e   Arnaldo Carvalho de Melo   perf trace: Add b...
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
  	P_MMAP_FLAG(LOCKED);
  	P_MMAP_FLAG(NONBLOCK);
  	P_MMAP_FLAG(NORESERVE);
  	P_MMAP_FLAG(POPULATE);
  	P_MMAP_FLAG(STACK);
  #ifdef MAP_UNINITIALIZED
  	P_MMAP_FLAG(UNINITIALIZED);
  #endif
  #undef P_MMAP_FLAG
  
  	if (flags)
  		printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
  
  	return printed;
  }
  
  #define SCA_MMAP_FLAGS syscall_arg__scnprintf_mmap_flags
86998dda5   Alex Snast   perf trace: Add b...
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
  static size_t syscall_arg__scnprintf_mremap_flags(char *bf, size_t size,
  						  struct syscall_arg *arg)
  {
  	int printed = 0, flags = arg->val;
  
  #define P_MREMAP_FLAG(n) \
  	if (flags & MREMAP_##n) { \
  		printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
  		flags &= ~MREMAP_##n; \
  	}
  
  	P_MREMAP_FLAG(MAYMOVE);
  #ifdef MREMAP_FIXED
  	P_MREMAP_FLAG(FIXED);
  #endif
  #undef P_MREMAP_FLAG
  
  	if (flags)
  		printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
  
  	return printed;
  }
  
  #define SCA_MREMAP_FLAGS syscall_arg__scnprintf_mremap_flags
6e7eeb511   Arnaldo Carvalho de Melo   perf trace: Allow...
409
  static size_t syscall_arg__scnprintf_madvise_behavior(char *bf, size_t size,
01533e972   Arnaldo Carvalho de Melo   perf trace: Put s...
410
  						      struct syscall_arg *arg)
9e9716d1b   Arnaldo Carvalho de Melo   perf trace: Add b...
411
  {
01533e972   Arnaldo Carvalho de Melo   perf trace: Put s...
412
  	int behavior = arg->val;
9e9716d1b   Arnaldo Carvalho de Melo   perf trace: Add b...
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
  
  	switch (behavior) {
  #define	P_MADV_BHV(n) case MADV_##n: return scnprintf(bf, size, #n)
  	P_MADV_BHV(NORMAL);
  	P_MADV_BHV(RANDOM);
  	P_MADV_BHV(SEQUENTIAL);
  	P_MADV_BHV(WILLNEED);
  	P_MADV_BHV(DONTNEED);
  	P_MADV_BHV(REMOVE);
  	P_MADV_BHV(DONTFORK);
  	P_MADV_BHV(DOFORK);
  	P_MADV_BHV(HWPOISON);
  #ifdef MADV_SOFT_OFFLINE
  	P_MADV_BHV(SOFT_OFFLINE);
  #endif
  	P_MADV_BHV(MERGEABLE);
  	P_MADV_BHV(UNMERGEABLE);
f2935f3e5   David Ahern   perf trace: Handl...
430
  #ifdef MADV_HUGEPAGE
9e9716d1b   Arnaldo Carvalho de Melo   perf trace: Add b...
431
  	P_MADV_BHV(HUGEPAGE);
f2935f3e5   David Ahern   perf trace: Handl...
432
433
  #endif
  #ifdef MADV_NOHUGEPAGE
9e9716d1b   Arnaldo Carvalho de Melo   perf trace: Add b...
434
  	P_MADV_BHV(NOHUGEPAGE);
f2935f3e5   David Ahern   perf trace: Handl...
435
  #endif
9e9716d1b   Arnaldo Carvalho de Melo   perf trace: Add b...
436
437
438
439
440
441
442
443
444
445
446
447
448
449
  #ifdef MADV_DONTDUMP
  	P_MADV_BHV(DONTDUMP);
  #endif
  #ifdef MADV_DODUMP
  	P_MADV_BHV(DODUMP);
  #endif
  #undef P_MADV_PHV
  	default: break;
  	}
  
  	return scnprintf(bf, size, "%#x", behavior);
  }
  
  #define SCA_MADV_BHV syscall_arg__scnprintf_madvise_behavior
5cea6ff26   Arnaldo Carvalho de Melo   perf trace: Beaut...
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
  static size_t syscall_arg__scnprintf_flock(char *bf, size_t size,
  					   struct syscall_arg *arg)
  {
  	int printed = 0, op = arg->val;
  
  	if (op == 0)
  		return scnprintf(bf, size, "NONE");
  #define	P_CMD(cmd) \
  	if ((op & LOCK_##cmd) == LOCK_##cmd) { \
  		printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #cmd); \
  		op &= ~LOCK_##cmd; \
  	}
  
  	P_CMD(SH);
  	P_CMD(EX);
  	P_CMD(NB);
  	P_CMD(UN);
  	P_CMD(MAND);
  	P_CMD(RW);
  	P_CMD(READ);
  	P_CMD(WRITE);
  #undef P_OP
  
  	if (op)
  		printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", op);
  
  	return printed;
  }
  
  #define SCA_FLOCK syscall_arg__scnprintf_flock
01533e972   Arnaldo Carvalho de Melo   perf trace: Put s...
480
  static size_t syscall_arg__scnprintf_futex_op(char *bf, size_t size, struct syscall_arg *arg)
f9da0b0c7   Arnaldo Carvalho de Melo   perf trace: Add b...
481
482
483
484
485
486
487
488
489
  {
  	enum syscall_futex_args {
  		SCF_UADDR   = (1 << 0),
  		SCF_OP	    = (1 << 1),
  		SCF_VAL	    = (1 << 2),
  		SCF_TIMEOUT = (1 << 3),
  		SCF_UADDR2  = (1 << 4),
  		SCF_VAL3    = (1 << 5),
  	};
01533e972   Arnaldo Carvalho de Melo   perf trace: Put s...
490
  	int op = arg->val;
f9da0b0c7   Arnaldo Carvalho de Melo   perf trace: Add b...
491
492
493
494
495
  	int cmd = op & FUTEX_CMD_MASK;
  	size_t printed = 0;
  
  	switch (cmd) {
  #define	P_FUTEX_OP(n) case FUTEX_##n: printed = scnprintf(bf, size, #n);
01533e972   Arnaldo Carvalho de Melo   perf trace: Put s...
496
497
498
499
500
501
  	P_FUTEX_OP(WAIT);	    arg->mask |= SCF_VAL3|SCF_UADDR2;		  break;
  	P_FUTEX_OP(WAKE);	    arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
  	P_FUTEX_OP(FD);		    arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
  	P_FUTEX_OP(REQUEUE);	    arg->mask |= SCF_VAL3|SCF_TIMEOUT;	          break;
  	P_FUTEX_OP(CMP_REQUEUE);    arg->mask |= SCF_TIMEOUT;			  break;
  	P_FUTEX_OP(CMP_REQUEUE_PI); arg->mask |= SCF_TIMEOUT;			  break;
f9da0b0c7   Arnaldo Carvalho de Melo   perf trace: Add b...
502
  	P_FUTEX_OP(WAKE_OP);							  break;
01533e972   Arnaldo Carvalho de Melo   perf trace: Put s...
503
504
505
506
507
  	P_FUTEX_OP(LOCK_PI);	    arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
  	P_FUTEX_OP(UNLOCK_PI);	    arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
  	P_FUTEX_OP(TRYLOCK_PI);	    arg->mask |= SCF_VAL3|SCF_UADDR2;		  break;
  	P_FUTEX_OP(WAIT_BITSET);    arg->mask |= SCF_UADDR2;			  break;
  	P_FUTEX_OP(WAKE_BITSET);    arg->mask |= SCF_UADDR2;			  break;
f9da0b0c7   Arnaldo Carvalho de Melo   perf trace: Add b...
508
509
510
511
512
513
514
515
516
517
518
519
  	P_FUTEX_OP(WAIT_REQUEUE_PI);						  break;
  	default: printed = scnprintf(bf, size, "%#x", cmd);			  break;
  	}
  
  	if (op & FUTEX_PRIVATE_FLAG)
  		printed += scnprintf(bf + printed, size - printed, "|PRIV");
  
  	if (op & FUTEX_CLOCK_REALTIME)
  		printed += scnprintf(bf + printed, size - printed, "|CLKRT");
  
  	return printed;
  }
efe6b882c   Arnaldo Carvalho de Melo   perf trace: Use s...
520
  #define SCA_FUTEX_OP  syscall_arg__scnprintf_futex_op
03e3adc9f   Arnaldo Carvalho de Melo   perf trace: Allow...
521
522
  static const char *epoll_ctl_ops[] = { "ADD", "DEL", "MOD", };
  static DEFINE_STRARRAY_OFFSET(epoll_ctl_ops, 1);
eac032c54   Arnaldo Carvalho de Melo   perf trace: Beaut...
523

1f115cb72   Arnaldo Carvalho de Melo   perf trace: Allow...
524
525
  static const char *itimers[] = { "REAL", "VIRTUAL", "PROF", };
  static DEFINE_STRARRAY(itimers);
efe6b882c   Arnaldo Carvalho de Melo   perf trace: Use s...
526
527
528
529
530
531
532
533
534
  static const char *whences[] = { "SET", "CUR", "END",
  #ifdef SEEK_DATA
  "DATA",
  #endif
  #ifdef SEEK_HOLE
  "HOLE",
  #endif
  };
  static DEFINE_STRARRAY(whences);
f9da0b0c7   Arnaldo Carvalho de Melo   perf trace: Add b...
535

80f587d5f   Arnaldo Carvalho de Melo   perf trace: Beaut...
536
537
538
539
540
541
542
  static const char *fcntl_cmds[] = {
  	"DUPFD", "GETFD", "SETFD", "GETFL", "SETFL", "GETLK", "SETLK",
  	"SETLKW", "SETOWN", "GETOWN", "SETSIG", "GETSIG", "F_GETLK64",
  	"F_SETLK64", "F_SETLKW64", "F_SETOWN_EX", "F_GETOWN_EX",
  	"F_GETOWNER_UIDS",
  };
  static DEFINE_STRARRAY(fcntl_cmds);
c045bf02e   Arnaldo Carvalho de Melo   perf trace: Beaut...
543
544
545
546
547
548
  static const char *rlimit_resources[] = {
  	"CPU", "FSIZE", "DATA", "STACK", "CORE", "RSS", "NPROC", "NOFILE",
  	"MEMLOCK", "AS", "LOCKS", "SIGPENDING", "MSGQUEUE", "NICE", "RTPRIO",
  	"RTTIME",
  };
  static DEFINE_STRARRAY(rlimit_resources);
eb5b1b147   Arnaldo Carvalho de Melo   perf trace: Beaut...
549
550
  static const char *sighow[] = { "BLOCK", "UNBLOCK", "SETMASK", };
  static DEFINE_STRARRAY(sighow);
4f8c1b74c   David Ahern   perf trace: Add b...
551
552
553
554
555
  static const char *clockid[] = {
  	"REALTIME", "MONOTONIC", "PROCESS_CPUTIME_ID", "THREAD_CPUTIME_ID",
  	"MONOTONIC_RAW", "REALTIME_COARSE", "MONOTONIC_COARSE",
  };
  static DEFINE_STRARRAY(clockid);
e10bce815   Arnaldo Carvalho de Melo   perf trace: Beaut...
556
557
558
559
560
561
562
563
564
  static const char *socket_families[] = {
  	"UNSPEC", "LOCAL", "INET", "AX25", "IPX", "APPLETALK", "NETROM",
  	"BRIDGE", "ATMPVC", "X25", "INET6", "ROSE", "DECnet", "NETBEUI",
  	"SECURITY", "KEY", "NETLINK", "PACKET", "ASH", "ECONET", "ATMSVC",
  	"RDS", "SNA", "IRDA", "PPPOX", "WANPIPE", "LLC", "IB", "CAN", "TIPC",
  	"BLUETOOTH", "IUCV", "RXRPC", "ISDN", "PHONET", "IEEE802154", "CAIF",
  	"ALG", "NFC", "VSOCK",
  };
  static DEFINE_STRARRAY(socket_families);
a28b24b27   Arnaldo Carvalho de Melo   perf trace: Beaut...
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
  #ifndef SOCK_TYPE_MASK
  #define SOCK_TYPE_MASK 0xf
  #endif
  
  static size_t syscall_arg__scnprintf_socket_type(char *bf, size_t size,
  						      struct syscall_arg *arg)
  {
  	size_t printed;
  	int type = arg->val,
  	    flags = type & ~SOCK_TYPE_MASK;
  
  	type &= SOCK_TYPE_MASK;
  	/*
   	 * Can't use a strarray, MIPS may override for ABI reasons.
   	 */
  	switch (type) {
  #define	P_SK_TYPE(n) case SOCK_##n: printed = scnprintf(bf, size, #n); break;
  	P_SK_TYPE(STREAM);
  	P_SK_TYPE(DGRAM);
  	P_SK_TYPE(RAW);
  	P_SK_TYPE(RDM);
  	P_SK_TYPE(SEQPACKET);
  	P_SK_TYPE(DCCP);
  	P_SK_TYPE(PACKET);
  #undef P_SK_TYPE
  	default:
  		printed = scnprintf(bf, size, "%#x", type);
  	}
  
  #define	P_SK_FLAG(n) \
  	if (flags & SOCK_##n) { \
  		printed += scnprintf(bf + printed, size - printed, "|%s", #n); \
  		flags &= ~SOCK_##n; \
  	}
  
  	P_SK_FLAG(CLOEXEC);
  	P_SK_FLAG(NONBLOCK);
  #undef P_SK_FLAG
  
  	if (flags)
  		printed += scnprintf(bf + printed, size - printed, "|%#x", flags);
  
  	return printed;
  }
  
  #define SCA_SK_TYPE syscall_arg__scnprintf_socket_type
b2cc99fda   Arnaldo Carvalho de Melo   perf trace: Beaut...
611
612
613
  #ifndef MSG_PROBE
  #define MSG_PROBE	     0x10
  #endif
b6e8f8f46   David Ahern   perf trace: Handl...
614
615
616
  #ifndef MSG_WAITFORONE
  #define MSG_WAITFORONE	0x10000
  #endif
b2cc99fda   Arnaldo Carvalho de Melo   perf trace: Beaut...
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
  #ifndef MSG_SENDPAGE_NOTLAST
  #define MSG_SENDPAGE_NOTLAST 0x20000
  #endif
  #ifndef MSG_FASTOPEN
  #define MSG_FASTOPEN	     0x20000000
  #endif
  
  static size_t syscall_arg__scnprintf_msg_flags(char *bf, size_t size,
  					       struct syscall_arg *arg)
  {
  	int printed = 0, flags = arg->val;
  
  	if (flags == 0)
  		return scnprintf(bf, size, "NONE");
  #define	P_MSG_FLAG(n) \
  	if (flags & MSG_##n) { \
  		printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
  		flags &= ~MSG_##n; \
  	}
  
  	P_MSG_FLAG(OOB);
  	P_MSG_FLAG(PEEK);
  	P_MSG_FLAG(DONTROUTE);
  	P_MSG_FLAG(TRYHARD);
  	P_MSG_FLAG(CTRUNC);
  	P_MSG_FLAG(PROBE);
  	P_MSG_FLAG(TRUNC);
  	P_MSG_FLAG(DONTWAIT);
  	P_MSG_FLAG(EOR);
  	P_MSG_FLAG(WAITALL);
  	P_MSG_FLAG(FIN);
  	P_MSG_FLAG(SYN);
  	P_MSG_FLAG(CONFIRM);
  	P_MSG_FLAG(RST);
  	P_MSG_FLAG(ERRQUEUE);
  	P_MSG_FLAG(NOSIGNAL);
  	P_MSG_FLAG(MORE);
  	P_MSG_FLAG(WAITFORONE);
  	P_MSG_FLAG(SENDPAGE_NOTLAST);
  	P_MSG_FLAG(FASTOPEN);
  	P_MSG_FLAG(CMSG_CLOEXEC);
  #undef P_MSG_FLAG
  
  	if (flags)
  		printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
  
  	return printed;
  }
  
  #define SCA_MSG_FLAGS syscall_arg__scnprintf_msg_flags
511089994   Arnaldo Carvalho de Melo   perf trace: Beaut...
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
  static size_t syscall_arg__scnprintf_access_mode(char *bf, size_t size,
  						 struct syscall_arg *arg)
  {
  	size_t printed = 0;
  	int mode = arg->val;
  
  	if (mode == F_OK) /* 0 */
  		return scnprintf(bf, size, "F");
  #define	P_MODE(n) \
  	if (mode & n##_OK) { \
  		printed += scnprintf(bf + printed, size - printed, "%s", #n); \
  		mode &= ~n##_OK; \
  	}
  
  	P_MODE(R);
  	P_MODE(W);
  	P_MODE(X);
  #undef P_MODE
  
  	if (mode)
  		printed += scnprintf(bf + printed, size - printed, "|%#x", mode);
  
  	return printed;
  }
  
  #define SCA_ACCMODE syscall_arg__scnprintf_access_mode
be65a89a0   Arnaldo Carvalho de Melo   perf trace: Add b...
693
  static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
01533e972   Arnaldo Carvalho de Melo   perf trace: Put s...
694
  					       struct syscall_arg *arg)
be65a89a0   Arnaldo Carvalho de Melo   perf trace: Add b...
695
  {
01533e972   Arnaldo Carvalho de Melo   perf trace: Put s...
696
  	int printed = 0, flags = arg->val;
be65a89a0   Arnaldo Carvalho de Melo   perf trace: Add b...
697
698
  
  	if (!(flags & O_CREAT))
01533e972   Arnaldo Carvalho de Melo   perf trace: Put s...
699
  		arg->mask |= 1 << (arg->idx + 1); /* Mask the mode parm */
be65a89a0   Arnaldo Carvalho de Melo   perf trace: Add b...
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
  
  	if (flags == 0)
  		return scnprintf(bf, size, "RDONLY");
  #define	P_FLAG(n) \
  	if (flags & O_##n) { \
  		printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
  		flags &= ~O_##n; \
  	}
  
  	P_FLAG(APPEND);
  	P_FLAG(ASYNC);
  	P_FLAG(CLOEXEC);
  	P_FLAG(CREAT);
  	P_FLAG(DIRECT);
  	P_FLAG(DIRECTORY);
  	P_FLAG(EXCL);
  	P_FLAG(LARGEFILE);
  	P_FLAG(NOATIME);
  	P_FLAG(NOCTTY);
  #ifdef O_NONBLOCK
  	P_FLAG(NONBLOCK);
  #elif O_NDELAY
  	P_FLAG(NDELAY);
  #endif
  #ifdef O_PATH
  	P_FLAG(PATH);
  #endif
  	P_FLAG(RDWR);
  #ifdef O_DSYNC
  	if ((flags & O_SYNC) == O_SYNC)
  		printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", "SYNC");
  	else {
  		P_FLAG(DSYNC);
  	}
  #else
  	P_FLAG(SYNC);
  #endif
  	P_FLAG(TRUNC);
  	P_FLAG(WRONLY);
  #undef P_FLAG
  
  	if (flags)
  		printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
  
  	return printed;
  }
  
  #define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags
49af9e93a   Arnaldo Carvalho de Melo   perf trace: Beaut...
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
  static size_t syscall_arg__scnprintf_eventfd_flags(char *bf, size_t size,
  						   struct syscall_arg *arg)
  {
  	int printed = 0, flags = arg->val;
  
  	if (flags == 0)
  		return scnprintf(bf, size, "NONE");
  #define	P_FLAG(n) \
  	if (flags & EFD_##n) { \
  		printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
  		flags &= ~EFD_##n; \
  	}
  
  	P_FLAG(SEMAPHORE);
  	P_FLAG(CLOEXEC);
  	P_FLAG(NONBLOCK);
  #undef P_FLAG
  
  	if (flags)
  		printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
  
  	return printed;
  }
  
  #define SCA_EFD_FLAGS syscall_arg__scnprintf_eventfd_flags
46cce19ba   Arnaldo Carvalho de Melo   perf trace: Beaut...
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
  static size_t syscall_arg__scnprintf_pipe_flags(char *bf, size_t size,
  						struct syscall_arg *arg)
  {
  	int printed = 0, flags = arg->val;
  
  #define	P_FLAG(n) \
  	if (flags & O_##n) { \
  		printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
  		flags &= ~O_##n; \
  	}
  
  	P_FLAG(CLOEXEC);
  	P_FLAG(NONBLOCK);
  #undef P_FLAG
  
  	if (flags)
  		printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
  
  	return printed;
  }
  
  #define SCA_PIPE_FLAGS syscall_arg__scnprintf_pipe_flags
8bad5b0ab   Arnaldo Carvalho de Melo   perf trace: Beaut...
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
  static size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscall_arg *arg)
  {
  	int sig = arg->val;
  
  	switch (sig) {
  #define	P_SIGNUM(n) case SIG##n: return scnprintf(bf, size, #n)
  	P_SIGNUM(HUP);
  	P_SIGNUM(INT);
  	P_SIGNUM(QUIT);
  	P_SIGNUM(ILL);
  	P_SIGNUM(TRAP);
  	P_SIGNUM(ABRT);
  	P_SIGNUM(BUS);
  	P_SIGNUM(FPE);
  	P_SIGNUM(KILL);
  	P_SIGNUM(USR1);
  	P_SIGNUM(SEGV);
  	P_SIGNUM(USR2);
  	P_SIGNUM(PIPE);
  	P_SIGNUM(ALRM);
  	P_SIGNUM(TERM);
8bad5b0ab   Arnaldo Carvalho de Melo   perf trace: Beaut...
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
  	P_SIGNUM(CHLD);
  	P_SIGNUM(CONT);
  	P_SIGNUM(STOP);
  	P_SIGNUM(TSTP);
  	P_SIGNUM(TTIN);
  	P_SIGNUM(TTOU);
  	P_SIGNUM(URG);
  	P_SIGNUM(XCPU);
  	P_SIGNUM(XFSZ);
  	P_SIGNUM(VTALRM);
  	P_SIGNUM(PROF);
  	P_SIGNUM(WINCH);
  	P_SIGNUM(IO);
  	P_SIGNUM(PWR);
  	P_SIGNUM(SYS);
02c5bb4a3   Ben Hutchings   perf trace: Decod...
831
832
833
834
835
836
837
838
839
  #ifdef SIGEMT
  	P_SIGNUM(EMT);
  #endif
  #ifdef SIGSTKFLT
  	P_SIGNUM(STKFLT);
  #endif
  #ifdef SIGSWI
  	P_SIGNUM(SWI);
  #endif
8bad5b0ab   Arnaldo Carvalho de Melo   perf trace: Beaut...
840
841
842
843
844
845
846
  	default: break;
  	}
  
  	return scnprintf(bf, size, "%#x", sig);
  }
  
  #define SCA_SIGNUM syscall_arg__scnprintf_signum
844ae5b46   Arnaldo Carvalho de Melo   perf trace: Fix i...
847
848
849
850
  #if defined(__i386__) || defined(__x86_64__)
  /*
   * FIXME: Make this available to all arches.
   */
78645cf3e   Arnaldo Carvalho de Melo   perf trace: Initi...
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
  #define TCGETS		0x5401
  
  static const char *tioctls[] = {
  	"TCGETS", "TCSETS", "TCSETSW", "TCSETSF", "TCGETA", "TCSETA", "TCSETAW",
  	"TCSETAF", "TCSBRK", "TCXONC", "TCFLSH", "TIOCEXCL", "TIOCNXCL",
  	"TIOCSCTTY", "TIOCGPGRP", "TIOCSPGRP", "TIOCOUTQ", "TIOCSTI",
  	"TIOCGWINSZ", "TIOCSWINSZ", "TIOCMGET", "TIOCMBIS", "TIOCMBIC",
  	"TIOCMSET", "TIOCGSOFTCAR", "TIOCSSOFTCAR", "FIONREAD", "TIOCLINUX",
  	"TIOCCONS", "TIOCGSERIAL", "TIOCSSERIAL", "TIOCPKT", "FIONBIO",
  	"TIOCNOTTY", "TIOCSETD", "TIOCGETD", "TCSBRKP", [0x27] = "TIOCSBRK",
  	"TIOCCBRK", "TIOCGSID", "TCGETS2", "TCSETS2", "TCSETSW2", "TCSETSF2",
  	"TIOCGRS485", "TIOCSRS485", "TIOCGPTN", "TIOCSPTLCK",
  	"TIOCGDEV||TCGETX", "TCSETX", "TCSETXF", "TCSETXW", "TIOCSIG",
  	"TIOCVHANGUP", "TIOCGPKT", "TIOCGPTLCK", "TIOCGEXCL",
  	[0x50] = "FIONCLEX", "FIOCLEX", "FIOASYNC", "TIOCSERCONFIG",
  	"TIOCSERGWILD", "TIOCSERSWILD", "TIOCGLCKTRMIOS", "TIOCSLCKTRMIOS",
  	"TIOCSERGSTRUCT", "TIOCSERGETLSR", "TIOCSERGETMULTI", "TIOCSERSETMULTI",
  	"TIOCMIWAIT", "TIOCGICOUNT", [0x60] = "FIOQSIZE",
  };
  
  static DEFINE_STRARRAY_OFFSET(tioctls, 0x5401);
844ae5b46   Arnaldo Carvalho de Melo   perf trace: Fix i...
872
  #endif /* defined(__i386__) || defined(__x86_64__) */
78645cf3e   Arnaldo Carvalho de Melo   perf trace: Initi...
873

453350dd0   Arnaldo Carvalho de Melo   perf trace: Add h...
874
875
876
  #define STRARRAY(arg, name, array) \
  	  .arg_scnprintf = { [arg] = SCA_STRARRAY, }, \
  	  .arg_parm	 = { [arg] = &strarray__##array, }
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
877
878
  static struct syscall_fmt {
  	const char *name;
aec1930b0   Arnaldo Carvalho de Melo   perf trace: Add a...
879
  	const char *alias;
01533e972   Arnaldo Carvalho de Melo   perf trace: Put s...
880
  	size_t	   (*arg_scnprintf[6])(char *bf, size_t size, struct syscall_arg *arg);
1f115cb72   Arnaldo Carvalho de Melo   perf trace: Allow...
881
  	void	   *arg_parm[6];
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
882
883
  	bool	   errmsg;
  	bool	   timeout;
04b34729e   Arnaldo Carvalho de Melo   perf trace: Allow...
884
  	bool	   hexret;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
885
  } syscall_fmts[] = {
511089994   Arnaldo Carvalho de Melo   perf trace: Beaut...
886
887
  	{ .name	    = "access",	    .errmsg = true,
  	  .arg_scnprintf = { [1] = SCA_ACCMODE, /* mode */ }, },
aec1930b0   Arnaldo Carvalho de Melo   perf trace: Add a...
888
  	{ .name	    = "arch_prctl", .errmsg = true, .alias = "prctl", },
beccb2b54   Arnaldo Carvalho de Melo   perf trace: Allow...
889
890
  	{ .name	    = "brk",	    .hexret = true,
  	  .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, },
4f8c1b74c   David Ahern   perf trace: Add b...
891
  	{ .name     = "clock_gettime",  .errmsg = true, STRARRAY(0, clk_id, clockid), },
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
892
893
  	{ .name	    = "close",	    .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_CLOSE_FD, /* fd */ }, }, 
a14bb860a   Arnaldo Carvalho de Melo   perf trace: Beaut...
894
  	{ .name	    = "connect",    .errmsg = true, },
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
895
896
897
898
899
900
  	{ .name	    = "dup",	    .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
  	{ .name	    = "dup2",	    .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
  	{ .name	    = "dup3",	    .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
453350dd0   Arnaldo Carvalho de Melo   perf trace: Add h...
901
  	{ .name	    = "epoll_ctl",  .errmsg = true, STRARRAY(1, op, epoll_ctl_ops), },
49af9e93a   Arnaldo Carvalho de Melo   perf trace: Beaut...
902
903
  	{ .name	    = "eventfd2",   .errmsg = true,
  	  .arg_scnprintf = { [1] = SCA_EFD_FLAGS, /* flags */ }, },
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
  	{ .name	    = "faccessat",  .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
  	{ .name	    = "fadvise64",  .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
  	{ .name	    = "fallocate",  .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
  	{ .name	    = "fchdir",	    .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
  	{ .name	    = "fchmod",	    .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
  	{ .name	    = "fchmodat",   .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, 
  	{ .name	    = "fchown",	    .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
  	{ .name	    = "fchownat",   .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, 
  	{ .name	    = "fcntl",	    .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_FD, /* fd */
  			     [1] = SCA_STRARRAY, /* cmd */ },
  	  .arg_parm	 = { [1] = &strarray__fcntl_cmds, /* cmd */ }, },
  	{ .name	    = "fdatasync",  .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
5cea6ff26   Arnaldo Carvalho de Melo   perf trace: Beaut...
926
  	{ .name	    = "flock",	    .errmsg = true,
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
927
928
929
930
931
932
933
934
935
936
937
938
939
940
  	  .arg_scnprintf = { [0] = SCA_FD, /* fd */
  			     [1] = SCA_FLOCK, /* cmd */ }, },
  	{ .name	    = "fsetxattr",  .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
  	{ .name	    = "fstat",	    .errmsg = true, .alias = "newfstat",
  	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
  	{ .name	    = "fstatat",    .errmsg = true, .alias = "newfstatat",
  	  .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, 
  	{ .name	    = "fstatfs",    .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
  	{ .name	    = "fsync",    .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
  	{ .name	    = "ftruncate", .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
f9da0b0c7   Arnaldo Carvalho de Melo   perf trace: Add b...
941
942
  	{ .name	    = "futex",	    .errmsg = true,
  	  .arg_scnprintf = { [1] = SCA_FUTEX_OP, /* op */ }, },
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
943
944
945
946
947
948
  	{ .name	    = "futimesat", .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, 
  	{ .name	    = "getdents",   .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
  	{ .name	    = "getdents64", .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
453350dd0   Arnaldo Carvalho de Melo   perf trace: Add h...
949
950
  	{ .name	    = "getitimer",  .errmsg = true, STRARRAY(0, which, itimers), },
  	{ .name	    = "getrlimit",  .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
beccb2b54   Arnaldo Carvalho de Melo   perf trace: Allow...
951
  	{ .name	    = "ioctl",	    .errmsg = true,
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
952
  	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ 
844ae5b46   Arnaldo Carvalho de Melo   perf trace: Fix i...
953
954
955
956
  #if defined(__i386__) || defined(__x86_64__)
  /*
   * FIXME: Make this available to all arches.
   */
78645cf3e   Arnaldo Carvalho de Melo   perf trace: Initi...
957
958
959
  			     [1] = SCA_STRHEXARRAY, /* cmd */
  			     [2] = SCA_HEX, /* arg */ },
  	  .arg_parm	 = { [1] = &strarray__tioctls, /* cmd */ }, },
844ae5b46   Arnaldo Carvalho de Melo   perf trace: Fix i...
960
961
962
  #else
  			     [2] = SCA_HEX, /* arg */ }, },
  #endif
8bad5b0ab   Arnaldo Carvalho de Melo   perf trace: Beaut...
963
964
  	{ .name	    = "kill",	    .errmsg = true,
  	  .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
965
966
967
968
969
970
  	{ .name	    = "linkat",	    .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, 
  	{ .name	    = "lseek",	    .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_FD, /* fd */
  			     [2] = SCA_STRARRAY, /* whence */ },
  	  .arg_parm	 = { [2] = &strarray__whences, /* whence */ }, },
e5959683a   Arnaldo Carvalho de Melo   perf trace: Add a...
971
  	{ .name	    = "lstat",	    .errmsg = true, .alias = "newlstat", },
9e9716d1b   Arnaldo Carvalho de Melo   perf trace: Add b...
972
973
974
  	{ .name     = "madvise",    .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_HEX,	 /* start */
  			     [2] = SCA_MADV_BHV, /* behavior */ }, },
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
975
976
977
978
  	{ .name	    = "mkdirat",    .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, 
  	{ .name	    = "mknodat",    .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, 
3d903aa74   Arnaldo Carvalho de Melo   perf trace: Beaut...
979
980
981
982
  	{ .name	    = "mlock",	    .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
  	{ .name	    = "mlockall",   .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
beccb2b54   Arnaldo Carvalho de Melo   perf trace: Allow...
983
  	{ .name	    = "mmap",	    .hexret = true,
ae685380b   Arnaldo Carvalho de Melo   perf trace: Add b...
984
  	  .arg_scnprintf = { [0] = SCA_HEX,	  /* addr */
941557e0e   Arnaldo Carvalho de Melo   perf trace: Add b...
985
  			     [2] = SCA_MMAP_PROT, /* prot */
73faab3a4   Namhyung Kim   perf trace: Beaut...
986
987
  			     [3] = SCA_MMAP_FLAGS, /* flags */
  			     [4] = SCA_FD, 	  /* fd */ }, },
beccb2b54   Arnaldo Carvalho de Melo   perf trace: Allow...
988
  	{ .name	    = "mprotect",   .errmsg = true,
ae685380b   Arnaldo Carvalho de Melo   perf trace: Add b...
989
990
991
992
  	  .arg_scnprintf = { [0] = SCA_HEX, /* start */
  			     [2] = SCA_MMAP_PROT, /* prot */ }, },
  	{ .name	    = "mremap",	    .hexret = true,
  	  .arg_scnprintf = { [0] = SCA_HEX, /* addr */
86998dda5   Alex Snast   perf trace: Add b...
993
  			     [3] = SCA_MREMAP_FLAGS, /* flags */
ae685380b   Arnaldo Carvalho de Melo   perf trace: Add b...
994
  			     [4] = SCA_HEX, /* new_addr */ }, },
3d903aa74   Arnaldo Carvalho de Melo   perf trace: Beaut...
995
996
  	{ .name	    = "munlock",    .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
beccb2b54   Arnaldo Carvalho de Melo   perf trace: Allow...
997
998
  	{ .name	    = "munmap",	    .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
999
1000
1001
1002
  	{ .name	    = "name_to_handle_at", .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, 
  	{ .name	    = "newfstatat", .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, 
be65a89a0   Arnaldo Carvalho de Melo   perf trace: Add b...
1003
1004
  	{ .name	    = "open",	    .errmsg = true,
  	  .arg_scnprintf = { [1] = SCA_OPEN_FLAGS, /* flags */ }, },
31cd3855c   Arnaldo Carvalho de Melo   perf trace: Tell ...
1005
  	{ .name	    = "open_by_handle_at", .errmsg = true,
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
1006
1007
  	  .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
  			     [2] = SCA_OPEN_FLAGS, /* flags */ }, },
31cd3855c   Arnaldo Carvalho de Melo   perf trace: Tell ...
1008
  	{ .name	    = "openat",	    .errmsg = true,
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
1009
1010
  	  .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
  			     [2] = SCA_OPEN_FLAGS, /* flags */ }, },
46cce19ba   Arnaldo Carvalho de Melo   perf trace: Beaut...
1011
1012
  	{ .name	    = "pipe2",	    .errmsg = true,
  	  .arg_scnprintf = { [1] = SCA_PIPE_FLAGS, /* flags */ }, },
aec1930b0   Arnaldo Carvalho de Melo   perf trace: Add a...
1013
1014
  	{ .name	    = "poll",	    .errmsg = true, .timeout = true, },
  	{ .name	    = "ppoll",	    .errmsg = true, .timeout = true, },
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
1015
1016
1017
1018
  	{ .name	    = "pread",	    .errmsg = true, .alias = "pread64",
  	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
  	{ .name	    = "preadv",	    .errmsg = true, .alias = "pread",
  	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
453350dd0   Arnaldo Carvalho de Melo   perf trace: Add h...
1019
  	{ .name	    = "prlimit64",  .errmsg = true, STRARRAY(1, resource, rlimit_resources), },
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
  	{ .name	    = "pwrite",	    .errmsg = true, .alias = "pwrite64",
  	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
  	{ .name	    = "pwritev",    .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
  	{ .name	    = "read",	    .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
  	{ .name	    = "readlinkat", .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, 
  	{ .name	    = "readv",	    .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
b2cc99fda   Arnaldo Carvalho de Melo   perf trace: Beaut...
1030
1031
1032
1033
1034
1035
  	{ .name	    = "recvfrom",   .errmsg = true,
  	  .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
  	{ .name	    = "recvmmsg",   .errmsg = true,
  	  .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
  	{ .name	    = "recvmsg",    .errmsg = true,
  	  .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, },
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
1036
1037
  	{ .name	    = "renameat",   .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, 
8bad5b0ab   Arnaldo Carvalho de Melo   perf trace: Beaut...
1038
1039
  	{ .name	    = "rt_sigaction", .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_SIGNUM, /* sig */ }, },
453350dd0   Arnaldo Carvalho de Melo   perf trace: Add h...
1040
  	{ .name	    = "rt_sigprocmask",  .errmsg = true, STRARRAY(0, how, sighow), },
8bad5b0ab   Arnaldo Carvalho de Melo   perf trace: Beaut...
1041
1042
1043
1044
  	{ .name	    = "rt_sigqueueinfo", .errmsg = true,
  	  .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
  	{ .name	    = "rt_tgsigqueueinfo", .errmsg = true,
  	  .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
aec1930b0   Arnaldo Carvalho de Melo   perf trace: Add a...
1045
  	{ .name	    = "select",	    .errmsg = true, .timeout = true, },
b2cc99fda   Arnaldo Carvalho de Melo   perf trace: Beaut...
1046
1047
1048
1049
1050
1051
  	{ .name	    = "sendmmsg",    .errmsg = true,
  	  .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
  	{ .name	    = "sendmsg",    .errmsg = true,
  	  .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, },
  	{ .name	    = "sendto",	    .errmsg = true,
  	  .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
453350dd0   Arnaldo Carvalho de Melo   perf trace: Add h...
1052
1053
  	{ .name	    = "setitimer",  .errmsg = true, STRARRAY(0, which, itimers), },
  	{ .name	    = "setrlimit",  .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
1054
1055
  	{ .name	    = "shutdown",   .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
e10bce815   Arnaldo Carvalho de Melo   perf trace: Beaut...
1056
  	{ .name	    = "socket",	    .errmsg = true,
a28b24b27   Arnaldo Carvalho de Melo   perf trace: Beaut...
1057
1058
  	  .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
  			     [1] = SCA_SK_TYPE, /* type */ },
07120aa5d   Arnaldo Carvalho de Melo   perf trace: Use s...
1059
1060
1061
1062
  	  .arg_parm	 = { [0] = &strarray__socket_families, /* family */ }, },
  	{ .name	    = "socketpair", .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
  			     [1] = SCA_SK_TYPE, /* type */ },
e10bce815   Arnaldo Carvalho de Melo   perf trace: Beaut...
1063
  	  .arg_parm	 = { [0] = &strarray__socket_families, /* family */ }, },
aec1930b0   Arnaldo Carvalho de Melo   perf trace: Add a...
1064
  	{ .name	    = "stat",	    .errmsg = true, .alias = "newstat", },
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
1065
1066
  	{ .name	    = "symlinkat",  .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, 
8bad5b0ab   Arnaldo Carvalho de Melo   perf trace: Beaut...
1067
1068
1069
1070
  	{ .name	    = "tgkill",	    .errmsg = true,
  	  .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
  	{ .name	    = "tkill",	    .errmsg = true,
  	  .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
e5959683a   Arnaldo Carvalho de Melo   perf trace: Add a...
1071
  	{ .name	    = "uname",	    .errmsg = true, .alias = "newuname", },
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
1072
1073
1074
1075
1076
1077
1078
1079
  	{ .name	    = "unlinkat",   .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
  	{ .name	    = "utimensat",  .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_FDAT, /* dirfd */ }, },
  	{ .name	    = "write",	    .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
  	{ .name	    = "writev",	    .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
  };
  
  static int syscall_fmt__cmp(const void *name, const void *fmtp)
  {
  	const struct syscall_fmt *fmt = fmtp;
  	return strcmp(name, fmt->name);
  }
  
  static struct syscall_fmt *syscall_fmt__find(const char *name)
  {
  	const int nmemb = ARRAY_SIZE(syscall_fmts);
  	return bsearch(name, syscall_fmts, nmemb, sizeof(struct syscall_fmt), syscall_fmt__cmp);
  }
  
  struct syscall {
  	struct event_format *tp_format;
  	const char	    *name;
2ae3a312c   Arnaldo Carvalho de Melo   perf trace: Allow...
1097
  	bool		    filtered;
5089f20ee   Arnaldo Carvalho de Melo   perf trace: Cache...
1098
  	bool		    is_exit;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1099
  	struct syscall_fmt  *fmt;
01533e972   Arnaldo Carvalho de Melo   perf trace: Put s...
1100
  	size_t		    (**arg_scnprintf)(char *bf, size_t size, struct syscall_arg *arg);
1f115cb72   Arnaldo Carvalho de Melo   perf trace: Allow...
1101
  	void		    **arg_parm;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1102
  };
60c907abc   Arnaldo Carvalho de Melo   perf trace: Add a...
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
  static size_t fprintf_duration(unsigned long t, FILE *fp)
  {
  	double duration = (double)t / NSEC_PER_MSEC;
  	size_t printed = fprintf(fp, "(");
  
  	if (duration >= 1.0)
  		printed += color_fprintf(fp, PERF_COLOR_RED, "%6.3f ms", duration);
  	else if (duration >= 0.01)
  		printed += color_fprintf(fp, PERF_COLOR_YELLOW, "%6.3f ms", duration);
  	else
  		printed += color_fprintf(fp, PERF_COLOR_NORMAL, "%6.3f ms", duration);
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1114
  	return printed + fprintf(fp, "): ");
60c907abc   Arnaldo Carvalho de Melo   perf trace: Add a...
1115
  }
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1116
1117
1118
1119
  struct thread_trace {
  	u64		  entry_time;
  	u64		  exit_time;
  	bool		  entry_pending;
efd5745e4   Arnaldo Carvalho de Melo   perf trace: Count...
1120
  	unsigned long	  nr_events;
a2ea67d7b   Stanislav Fomichev   perf trace: Add p...
1121
  	unsigned long	  pfmaj, pfmin;
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1122
  	char		  *entry_str;
1302d88e6   Arnaldo Carvalho de Melo   perf trace: Use s...
1123
  	double		  runtime_ms;
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
1124
1125
1126
1127
  	struct {
  		int	  max;
  		char	  **table;
  	} paths;
bf2575c12   David Ahern   perf trace: Add s...
1128
1129
  
  	struct intlist *syscall_stats;
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1130
1131
1132
1133
  };
  
  static struct thread_trace *thread_trace__new(void)
  {
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
1134
1135
1136
1137
  	struct thread_trace *ttrace =  zalloc(sizeof(struct thread_trace));
  
  	if (ttrace)
  		ttrace->paths.max = -1;
bf2575c12   David Ahern   perf trace: Add s...
1138
  	ttrace->syscall_stats = intlist__new(NULL);
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
1139
  	return ttrace;
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1140
  }
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1141
  static struct thread_trace *thread__trace(struct thread *thread, FILE *fp)
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1142
  {
efd5745e4   Arnaldo Carvalho de Melo   perf trace: Count...
1143
  	struct thread_trace *ttrace;
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1144
1145
  	if (thread == NULL)
  		goto fail;
89dceb22c   Namhyung Kim   perf trace: Use t...
1146
1147
  	if (thread__priv(thread) == NULL)
  		thread__set_priv(thread, thread_trace__new());
efd5745e4   Arnaldo Carvalho de Melo   perf trace: Count...
1148
  		
89dceb22c   Namhyung Kim   perf trace: Use t...
1149
  	if (thread__priv(thread) == NULL)
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1150
  		goto fail;
89dceb22c   Namhyung Kim   perf trace: Use t...
1151
  	ttrace = thread__priv(thread);
efd5745e4   Arnaldo Carvalho de Melo   perf trace: Count...
1152
1153
1154
  	++ttrace->nr_events;
  
  	return ttrace;
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1155
  fail:
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1156
  	color_fprintf(fp, PERF_COLOR_RED,
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1157
1158
1159
1160
  		      "WARNING: not enough memory, dropping samples!
  ");
  	return NULL;
  }
598d02c5a   Stanislav Fomichev   perf trace: Add s...
1161
1162
  #define TRACE_PFMAJ		(1 << 0)
  #define TRACE_PFMIN		(1 << 1)
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1163
  struct trace {
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1164
  	struct perf_tool	tool;
c522739d7   Arnaldo Carvalho de Melo   perf trace: Use v...
1165
1166
1167
1168
  	struct {
  		int		machine;
  		int		open_id;
  	}			audit;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1169
1170
1171
1172
  	struct {
  		int		max;
  		struct syscall  *table;
  	} syscalls;
b40067964   Arnaldo Carvalho de Melo   perf tools: Renam...
1173
  	struct record_opts	opts;
8fb598e5a   David Ahern   perf trace: Fix c...
1174
  	struct machine		*host;
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1175
  	u64			base_time;
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1176
  	FILE			*output;
efd5745e4   Arnaldo Carvalho de Melo   perf trace: Count...
1177
  	unsigned long		nr_events;
b059efdf5   Arnaldo Carvalho de Melo   perf trace: Suppo...
1178
  	struct strlist		*ev_qualifier;
c522739d7   Arnaldo Carvalho de Melo   perf trace: Use v...
1179
  	const char 		*last_vfs_getname;
bdc896617   David Ahern   perf trace: Honor...
1180
1181
  	struct intlist		*tid_list;
  	struct intlist		*pid_list;
98eafce6b   Arnaldo Carvalho de Melo   perf trace: Pack ...
1182
1183
1184
1185
1186
1187
1188
1189
1190
  	double			duration_filter;
  	double			runtime_ms;
  	struct {
  		u64		vfs_getname,
  				proc_getname;
  	} stats;
  	bool			not_ev_qualifier;
  	bool			live;
  	bool			full_time;
1302d88e6   Arnaldo Carvalho de Melo   perf trace: Use s...
1191
  	bool			sched;
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1192
  	bool			multiple_threads;
bf2575c12   David Ahern   perf trace: Add s...
1193
  	bool			summary;
fd2eabaf1   David Ahern   perf trace: Add s...
1194
  	bool			summary_only;
50c95cbd7   Arnaldo Carvalho de Melo   perf trace: Add o...
1195
  	bool			show_comm;
c522739d7   Arnaldo Carvalho de Melo   perf trace: Use v...
1196
  	bool			show_tool_stats;
e281a9606   Stanislav Fomichev   perf trace: Add p...
1197
  	bool			trace_syscalls;
598d02c5a   Stanislav Fomichev   perf trace: Add s...
1198
  	int			trace_pgfaults;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1199
  };
97119f37b   Arnaldo Carvalho de Melo   perf trace: Split...
1200
  static int trace__set_fd_pathname(struct thread *thread, int fd, const char *pathname)
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
1201
  {
89dceb22c   Namhyung Kim   perf trace: Use t...
1202
  	struct thread_trace *ttrace = thread__priv(thread);
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
  
  	if (fd > ttrace->paths.max) {
  		char **npath = realloc(ttrace->paths.table, (fd + 1) * sizeof(char *));
  
  		if (npath == NULL)
  			return -1;
  
  		if (ttrace->paths.max != -1) {
  			memset(npath + ttrace->paths.max + 1, 0,
  			       (fd - ttrace->paths.max) * sizeof(char *));
  		} else {
  			memset(npath, 0, (fd + 1) * sizeof(char *));
  		}
  
  		ttrace->paths.table = npath;
  		ttrace->paths.max   = fd;
  	}
  
  	ttrace->paths.table[fd] = strdup(pathname);
  
  	return ttrace->paths.table[fd] != NULL ? 0 : -1;
  }
97119f37b   Arnaldo Carvalho de Melo   perf trace: Split...
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
  static int thread__read_fd_path(struct thread *thread, int fd)
  {
  	char linkname[PATH_MAX], pathname[PATH_MAX];
  	struct stat st;
  	int ret;
  
  	if (thread->pid_ == thread->tid) {
  		scnprintf(linkname, sizeof(linkname),
  			  "/proc/%d/fd/%d", thread->pid_, fd);
  	} else {
  		scnprintf(linkname, sizeof(linkname),
  			  "/proc/%d/task/%d/fd/%d", thread->pid_, thread->tid, fd);
  	}
  
  	if (lstat(linkname, &st) < 0 || st.st_size + 1 > (off_t)sizeof(pathname))
  		return -1;
  
  	ret = readlink(linkname, pathname, sizeof(pathname));
  
  	if (ret < 0 || ret > st.st_size)
  		return -1;
  
  	pathname[ret] = '\0';
  	return trace__set_fd_pathname(thread, fd, pathname);
  }
c522739d7   Arnaldo Carvalho de Melo   perf trace: Use v...
1250
1251
  static const char *thread__fd_path(struct thread *thread, int fd,
  				   struct trace *trace)
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
1252
  {
89dceb22c   Namhyung Kim   perf trace: Use t...
1253
  	struct thread_trace *ttrace = thread__priv(thread);
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
1254
1255
1256
1257
1258
1259
  
  	if (ttrace == NULL)
  		return NULL;
  
  	if (fd < 0)
  		return NULL;
cdcd1e6bd   Arnaldo Carvalho de Melo   perf trace: Fix u...
1260
  	if ((fd > ttrace->paths.max || ttrace->paths.table[fd] == NULL)) {
c522739d7   Arnaldo Carvalho de Melo   perf trace: Use v...
1261
1262
1263
  		if (!trace->live)
  			return NULL;
  		++trace->stats.proc_getname;
cdcd1e6bd   Arnaldo Carvalho de Melo   perf trace: Fix u...
1264
  		if (thread__read_fd_path(thread, fd))
c522739d7   Arnaldo Carvalho de Melo   perf trace: Use v...
1265
1266
  			return NULL;
  	}
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
1267
1268
1269
1270
1271
1272
1273
1274
1275
  
  	return ttrace->paths.table[fd];
  }
  
  static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
  					struct syscall_arg *arg)
  {
  	int fd = arg->val;
  	size_t printed = scnprintf(bf, size, "%d", fd);
c522739d7   Arnaldo Carvalho de Melo   perf trace: Use v...
1276
  	const char *path = thread__fd_path(arg->thread, fd, arg->trace);
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
  
  	if (path)
  		printed += scnprintf(bf + printed, size - printed, "<%s>", path);
  
  	return printed;
  }
  
  static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
  					      struct syscall_arg *arg)
  {
  	int fd = arg->val;
  	size_t printed = syscall_arg__scnprintf_fd(bf, size, arg);
89dceb22c   Namhyung Kim   perf trace: Use t...
1289
  	struct thread_trace *ttrace = thread__priv(arg->thread);
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
1290

046625231   Arnaldo Carvalho de Melo   perf tools: Intro...
1291
1292
  	if (ttrace && fd >= 0 && fd <= ttrace->paths.max)
  		zfree(&ttrace->paths.table[fd]);
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
1293
1294
1295
  
  	return printed;
  }
ae9ed0357   Arnaldo Carvalho de Melo   perf trace: Add d...
1296
1297
1298
1299
  static bool trace__filter_duration(struct trace *trace, double t)
  {
  	return t < (trace->duration_filter * NSEC_PER_MSEC);
  }
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1300
1301
1302
  static size_t trace__fprintf_tstamp(struct trace *trace, u64 tstamp, FILE *fp)
  {
  	double ts = (double)(tstamp - trace->base_time) / NSEC_PER_MSEC;
60c907abc   Arnaldo Carvalho de Melo   perf trace: Add a...
1303
  	return fprintf(fp, "%10.3f ", ts);
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1304
  }
f15eb531d   Namhyung Kim   perf trace: Add s...
1305
  static bool done = false;
ba209f856   Arnaldo Carvalho de Melo   perf trace: Impro...
1306
  static bool interrupted = false;
f15eb531d   Namhyung Kim   perf trace: Add s...
1307

ba209f856   Arnaldo Carvalho de Melo   perf trace: Impro...
1308
  static void sig_handler(int sig)
f15eb531d   Namhyung Kim   perf trace: Add s...
1309
1310
  {
  	done = true;
ba209f856   Arnaldo Carvalho de Melo   perf trace: Impro...
1311
  	interrupted = sig == SIGINT;
f15eb531d   Namhyung Kim   perf trace: Add s...
1312
  }
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1313
  static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thread,
60c907abc   Arnaldo Carvalho de Melo   perf trace: Add a...
1314
  					u64 duration, u64 tstamp, FILE *fp)
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1315
1316
  {
  	size_t printed = trace__fprintf_tstamp(trace, tstamp, fp);
60c907abc   Arnaldo Carvalho de Melo   perf trace: Add a...
1317
  	printed += fprintf_duration(duration, fp);
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1318

50c95cbd7   Arnaldo Carvalho de Melo   perf trace: Add o...
1319
1320
  	if (trace->multiple_threads) {
  		if (trace->show_comm)
1902efe7f   Frederic Weisbecker   perf tools: Add n...
1321
  			printed += fprintf(fp, "%.14s/", thread__comm_str(thread));
380512345   Adrian Hunter   perf tools: struc...
1322
  		printed += fprintf(fp, "%d ", thread->tid);
50c95cbd7   Arnaldo Carvalho de Melo   perf trace: Add o...
1323
  	}
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1324
1325
1326
  
  	return printed;
  }
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1327
  static int trace__process_event(struct trace *trace, struct machine *machine,
162f0befd   Frederic Weisbecker   perf tools: Add t...
1328
  				union perf_event *event, struct perf_sample *sample)
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1329
1330
1331
1332
1333
  {
  	int ret = 0;
  
  	switch (event->header.type) {
  	case PERF_RECORD_LOST:
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1334
  		color_fprintf(trace->output, PERF_COLOR_RED,
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1335
1336
  			      "LOST %" PRIu64 " events!
  ", event->lost.lost);
162f0befd   Frederic Weisbecker   perf tools: Add t...
1337
  		ret = machine__process_lost_event(machine, event, sample);
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1338
  	default:
162f0befd   Frederic Weisbecker   perf tools: Add t...
1339
  		ret = machine__process_event(machine, event, sample);
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1340
1341
1342
1343
1344
  		break;
  	}
  
  	return ret;
  }
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1345
  static int trace__tool_process(struct perf_tool *tool,
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1346
  			       union perf_event *event,
162f0befd   Frederic Weisbecker   perf tools: Add t...
1347
  			       struct perf_sample *sample,
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1348
1349
  			       struct machine *machine)
  {
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1350
  	struct trace *trace = container_of(tool, struct trace, tool);
162f0befd   Frederic Weisbecker   perf tools: Add t...
1351
  	return trace__process_event(trace, machine, event, sample);
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1352
1353
1354
1355
  }
  
  static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
  {
0a7e6d1b6   Namhyung Kim   perf tools: Check...
1356
  	int err = symbol__init(NULL);
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1357
1358
1359
  
  	if (err)
  		return err;
8fb598e5a   David Ahern   perf trace: Fix c...
1360
1361
1362
  	trace->host = machine__new_host();
  	if (trace->host == NULL)
  		return -ENOMEM;
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1363

a33fbd56e   Arnaldo Carvalho de Melo   perf machine: Sim...
1364
1365
  	err = __machine__synthesize_threads(trace->host, &trace->tool, &trace->opts.target,
  					    evlist->threads, trace__tool_process, false);
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1366
1367
1368
1369
1370
  	if (err)
  		symbol__exit();
  
  	return err;
  }
13d4ff3eb   Arnaldo Carvalho de Melo   perf trace: Intro...
1371
1372
1373
1374
1375
1376
1377
1378
  static int syscall__set_arg_fmts(struct syscall *sc)
  {
  	struct format_field *field;
  	int idx = 0;
  
  	sc->arg_scnprintf = calloc(sc->tp_format->format.nr_fields - 1, sizeof(void *));
  	if (sc->arg_scnprintf == NULL)
  		return -1;
1f115cb72   Arnaldo Carvalho de Melo   perf trace: Allow...
1379
1380
  	if (sc->fmt)
  		sc->arg_parm = sc->fmt->arg_parm;
13d4ff3eb   Arnaldo Carvalho de Melo   perf trace: Intro...
1381
  	for (field = sc->tp_format->format.fields->next; field; field = field->next) {
beccb2b54   Arnaldo Carvalho de Melo   perf trace: Allow...
1382
1383
1384
  		if (sc->fmt && sc->fmt->arg_scnprintf[idx])
  			sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx];
  		else if (field->flags & FIELD_IS_POINTER)
13d4ff3eb   Arnaldo Carvalho de Melo   perf trace: Intro...
1385
1386
1387
1388
1389
1390
  			sc->arg_scnprintf[idx] = syscall_arg__scnprintf_hex;
  		++idx;
  	}
  
  	return 0;
  }
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1391
1392
1393
1394
  static int trace__read_syscall_info(struct trace *trace, int id)
  {
  	char tp_name[128];
  	struct syscall *sc;
c522739d7   Arnaldo Carvalho de Melo   perf trace: Use v...
1395
  	const char *name = audit_syscall_to_name(id, trace->audit.machine);
3a531260a   Arnaldo Carvalho de Melo   perf trace: Valid...
1396
1397
1398
  
  	if (name == NULL)
  		return -1;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
  
  	if (id > trace->syscalls.max) {
  		struct syscall *nsyscalls = realloc(trace->syscalls.table, (id + 1) * sizeof(*sc));
  
  		if (nsyscalls == NULL)
  			return -1;
  
  		if (trace->syscalls.max != -1) {
  			memset(nsyscalls + trace->syscalls.max + 1, 0,
  			       (id - trace->syscalls.max) * sizeof(*sc));
  		} else {
  			memset(nsyscalls, 0, (id + 1) * sizeof(*sc));
  		}
  
  		trace->syscalls.table = nsyscalls;
  		trace->syscalls.max   = id;
  	}
  
  	sc = trace->syscalls.table + id;
3a531260a   Arnaldo Carvalho de Melo   perf trace: Valid...
1418
  	sc->name = name;
2ae3a312c   Arnaldo Carvalho de Melo   perf trace: Allow...
1419

b059efdf5   Arnaldo Carvalho de Melo   perf trace: Suppo...
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
  	if (trace->ev_qualifier) {
  		bool in = strlist__find(trace->ev_qualifier, name) != NULL;
  
  		if (!(in ^ trace->not_ev_qualifier)) {
  			sc->filtered = true;
  			/*
  			 * No need to do read tracepoint information since this will be
  			 * filtered out.
  			 */
  			return 0;
  		}
2ae3a312c   Arnaldo Carvalho de Melo   perf trace: Allow...
1431
  	}
3a531260a   Arnaldo Carvalho de Melo   perf trace: Valid...
1432
  	sc->fmt  = syscall_fmt__find(sc->name);
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1433

aec1930b0   Arnaldo Carvalho de Melo   perf trace: Add a...
1434
  	snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name);
97978b3e3   Jiri Olsa   perf tools: Add t...
1435
  	sc->tp_format = trace_event__tp_format("syscalls", tp_name);
aec1930b0   Arnaldo Carvalho de Melo   perf trace: Add a...
1436
1437
1438
  
  	if (sc->tp_format == NULL && sc->fmt && sc->fmt->alias) {
  		snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->fmt->alias);
97978b3e3   Jiri Olsa   perf tools: Add t...
1439
  		sc->tp_format = trace_event__tp_format("syscalls", tp_name);
aec1930b0   Arnaldo Carvalho de Melo   perf trace: Add a...
1440
  	}
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1441

13d4ff3eb   Arnaldo Carvalho de Melo   perf trace: Intro...
1442
1443
  	if (sc->tp_format == NULL)
  		return -1;
5089f20ee   Arnaldo Carvalho de Melo   perf trace: Cache...
1444
  	sc->is_exit = !strcmp(name, "exit_group") || !strcmp(name, "exit");
13d4ff3eb   Arnaldo Carvalho de Melo   perf trace: Intro...
1445
  	return syscall__set_arg_fmts(sc);
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1446
  }
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1447
  static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
1448
1449
  				      unsigned long *args, struct trace *trace,
  				      struct thread *thread)
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1450
  {
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1451
1452
1453
1454
  	size_t printed = 0;
  
  	if (sc->tp_format != NULL) {
  		struct format_field *field;
01533e972   Arnaldo Carvalho de Melo   perf trace: Put s...
1455
1456
  		u8 bit = 1;
  		struct syscall_arg arg = {
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
1457
1458
1459
1460
  			.idx	= 0,
  			.mask	= 0,
  			.trace  = trace,
  			.thread = thread,
01533e972   Arnaldo Carvalho de Melo   perf trace: Put s...
1461
  		};
6e7eeb511   Arnaldo Carvalho de Melo   perf trace: Allow...
1462
1463
  
  		for (field = sc->tp_format->format.fields->next; field;
01533e972   Arnaldo Carvalho de Melo   perf trace: Put s...
1464
1465
  		     field = field->next, ++arg.idx, bit <<= 1) {
  			if (arg.mask & bit)
6e7eeb511   Arnaldo Carvalho de Melo   perf trace: Allow...
1466
  				continue;
4aa582322   Arnaldo Carvalho de Melo   perf trace: Don't...
1467
1468
1469
1470
1471
1472
1473
1474
1475
  			/*
   			 * Suppress this argument if its value is zero and
   			 * and we don't have a string associated in an
   			 * strarray for it.
   			 */
  			if (args[arg.idx] == 0 &&
  			    !(sc->arg_scnprintf &&
  			      sc->arg_scnprintf[arg.idx] == SCA_STRARRAY &&
  			      sc->arg_parm[arg.idx]))
22ae5cf1c   Arnaldo Carvalho de Melo   perf trace: Don't...
1476
  				continue;
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1477
  			printed += scnprintf(bf + printed, size - printed,
13d4ff3eb   Arnaldo Carvalho de Melo   perf trace: Intro...
1478
  					     "%s%s: ", printed ? ", " : "", field->name);
01533e972   Arnaldo Carvalho de Melo   perf trace: Put s...
1479
1480
  			if (sc->arg_scnprintf && sc->arg_scnprintf[arg.idx]) {
  				arg.val = args[arg.idx];
1f115cb72   Arnaldo Carvalho de Melo   perf trace: Allow...
1481
1482
  				if (sc->arg_parm)
  					arg.parm = sc->arg_parm[arg.idx];
01533e972   Arnaldo Carvalho de Melo   perf trace: Put s...
1483
1484
  				printed += sc->arg_scnprintf[arg.idx](bf + printed,
  								      size - printed, &arg);
6e7eeb511   Arnaldo Carvalho de Melo   perf trace: Allow...
1485
  			} else {
13d4ff3eb   Arnaldo Carvalho de Melo   perf trace: Intro...
1486
  				printed += scnprintf(bf + printed, size - printed,
01533e972   Arnaldo Carvalho de Melo   perf trace: Put s...
1487
  						     "%ld", args[arg.idx]);
6e7eeb511   Arnaldo Carvalho de Melo   perf trace: Allow...
1488
  			}
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1489
1490
  		}
  	} else {
01533e972   Arnaldo Carvalho de Melo   perf trace: Put s...
1491
  		int i = 0;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1492
  		while (i < 6) {
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1493
1494
1495
  			printed += scnprintf(bf + printed, size - printed,
  					     "%sarg%d: %ld",
  					     printed ? ", " : "", i, args[i]);
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1496
1497
1498
1499
1500
1501
  			++i;
  		}
  	}
  
  	return printed;
  }
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1502
  typedef int (*tracepoint_handler)(struct trace *trace, struct perf_evsel *evsel,
0c82adcf1   Stanislav Fomichev   perf trace: Add p...
1503
  				  union perf_event *event,
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1504
1505
1506
  				  struct perf_sample *sample);
  
  static struct syscall *trace__syscall_info(struct trace *trace,
bf2575c12   David Ahern   perf trace: Add s...
1507
  					   struct perf_evsel *evsel, int id)
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1508
  {
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1509
1510
  
  	if (id < 0) {
adaa18bf5   Arnaldo Carvalho de Melo   perf trace: Hide ...
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
  
  		/*
  		 * XXX: Noticed on x86_64, reproduced as far back as 3.0.36, haven't tried
  		 * before that, leaving at a higher verbosity level till that is
  		 * explained. Reproduced with plain ftrace with:
  		 *
  		 * echo 1 > /t/events/raw_syscalls/sys_exit/enable
  		 * grep "NR -1 " /t/trace_pipe
  		 *
  		 * After generating some load on the machine.
   		 */
  		if (verbose > 1) {
  			static u64 n;
  			fprintf(trace->output, "Invalid syscall %d id, skipping (%s, %" PRIu64 ") ...
  ",
  				id, perf_evsel__name(evsel), ++n);
  		}
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
  		return NULL;
  	}
  
  	if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL) &&
  	    trace__read_syscall_info(trace, id))
  		goto out_cant_read;
  
  	if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL))
  		goto out_cant_read;
  
  	return &trace->syscalls.table[id];
  
  out_cant_read:
7c304ee0f   Arnaldo Carvalho de Melo   perf trace: Add -...
1541
1542
1543
1544
1545
1546
1547
  	if (verbose) {
  		fprintf(trace->output, "Problems reading syscall %d", id);
  		if (id <= trace->syscalls.max && trace->syscalls.table[id].name != NULL)
  			fprintf(trace->output, "(%s)", trace->syscalls.table[id].name);
  		fputs(" information
  ", trace->output);
  	}
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1548
1549
  	return NULL;
  }
bf2575c12   David Ahern   perf trace: Add s...
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
  static void thread__update_stats(struct thread_trace *ttrace,
  				 int id, struct perf_sample *sample)
  {
  	struct int_node *inode;
  	struct stats *stats;
  	u64 duration = 0;
  
  	inode = intlist__findnew(ttrace->syscall_stats, id);
  	if (inode == NULL)
  		return;
  
  	stats = inode->priv;
  	if (stats == NULL) {
  		stats = malloc(sizeof(struct stats));
  		if (stats == NULL)
  			return;
  		init_stats(stats);
  		inode->priv = stats;
  	}
  
  	if (ttrace->entry_time && sample->time > ttrace->entry_time)
  		duration = sample->time - ttrace->entry_time;
  
  	update_stats(stats, duration);
  }
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1575
  static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
0c82adcf1   Stanislav Fomichev   perf trace: Add p...
1576
  			    union perf_event *event __maybe_unused,
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1577
1578
  			    struct perf_sample *sample)
  {
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1579
  	char *msg;
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1580
  	void *args;
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1581
  	size_t printed = 0;
2ae3a312c   Arnaldo Carvalho de Melo   perf trace: Allow...
1582
  	struct thread *thread;
77170988f   Arnaldo Carvalho de Melo   perf trace: Don't...
1583
  	int id = perf_evsel__sc_tp_uint(evsel, id, sample);
bf2575c12   David Ahern   perf trace: Add s...
1584
  	struct syscall *sc = trace__syscall_info(trace, evsel, id);
2ae3a312c   Arnaldo Carvalho de Melo   perf trace: Allow...
1585
1586
1587
1588
  	struct thread_trace *ttrace;
  
  	if (sc == NULL)
  		return -1;
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1589

2ae3a312c   Arnaldo Carvalho de Melo   perf trace: Allow...
1590
1591
  	if (sc->filtered)
  		return 0;
8fb598e5a   David Ahern   perf trace: Fix c...
1592
  	thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1593
  	ttrace = thread__trace(thread, trace->output);
2ae3a312c   Arnaldo Carvalho de Melo   perf trace: Allow...
1594
  	if (ttrace == NULL)
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1595
  		return -1;
77170988f   Arnaldo Carvalho de Melo   perf trace: Don't...
1596
  	args = perf_evsel__sc_tp_ptr(evsel, args, sample);
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
  
  	if (ttrace->entry_str == NULL) {
  		ttrace->entry_str = malloc(1024);
  		if (!ttrace->entry_str)
  			return -1;
  	}
  
  	ttrace->entry_time = sample->time;
  	msg = ttrace->entry_str;
  	printed += scnprintf(msg + printed, 1024 - printed, "%s(", sc->name);
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
1607
1608
  	printed += syscall__scnprintf_args(sc, msg + printed, 1024 - printed,
  					   args, trace, thread);
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1609

5089f20ee   Arnaldo Carvalho de Melo   perf trace: Cache...
1610
  	if (sc->is_exit) {
fd2eabaf1   David Ahern   perf trace: Add s...
1611
  		if (!trace->duration_filter && !trace->summary_only) {
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1612
1613
1614
  			trace__fprintf_entry_head(trace, thread, 1, sample->time, trace->output);
  			fprintf(trace->output, "%-70s
  ", ttrace->entry_str);
ae9ed0357   Arnaldo Carvalho de Melo   perf trace: Add d...
1615
  		}
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1616
1617
  	} else
  		ttrace->entry_pending = true;
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1618
1619
1620
1621
1622
  
  	return 0;
  }
  
  static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
0c82adcf1   Stanislav Fomichev   perf trace: Add p...
1623
  			   union perf_event *event __maybe_unused,
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1624
1625
  			   struct perf_sample *sample)
  {
2c82c3ad5   Chang Hyun Park   perf trace: Fix m...
1626
  	long ret;
60c907abc   Arnaldo Carvalho de Melo   perf trace: Add a...
1627
  	u64 duration = 0;
2ae3a312c   Arnaldo Carvalho de Melo   perf trace: Allow...
1628
  	struct thread *thread;
77170988f   Arnaldo Carvalho de Melo   perf trace: Don't...
1629
  	int id = perf_evsel__sc_tp_uint(evsel, id, sample);
bf2575c12   David Ahern   perf trace: Add s...
1630
  	struct syscall *sc = trace__syscall_info(trace, evsel, id);
2ae3a312c   Arnaldo Carvalho de Melo   perf trace: Allow...
1631
1632
1633
1634
  	struct thread_trace *ttrace;
  
  	if (sc == NULL)
  		return -1;
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1635

2ae3a312c   Arnaldo Carvalho de Melo   perf trace: Allow...
1636
1637
  	if (sc->filtered)
  		return 0;
8fb598e5a   David Ahern   perf trace: Fix c...
1638
  	thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1639
  	ttrace = thread__trace(thread, trace->output);
2ae3a312c   Arnaldo Carvalho de Melo   perf trace: Allow...
1640
  	if (ttrace == NULL)
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1641
  		return -1;
bf2575c12   David Ahern   perf trace: Add s...
1642
1643
  	if (trace->summary)
  		thread__update_stats(ttrace, id, sample);
77170988f   Arnaldo Carvalho de Melo   perf trace: Don't...
1644
  	ret = perf_evsel__sc_tp_uint(evsel, ret, sample);
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1645

c522739d7   Arnaldo Carvalho de Melo   perf trace: Use v...
1646
1647
1648
1649
1650
  	if (id == trace->audit.open_id && ret >= 0 && trace->last_vfs_getname) {
  		trace__set_fd_pathname(thread, ret, trace->last_vfs_getname);
  		trace->last_vfs_getname = NULL;
  		++trace->stats.vfs_getname;
  	}
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1651
  	ttrace->exit_time = sample->time;
ae9ed0357   Arnaldo Carvalho de Melo   perf trace: Add d...
1652
  	if (ttrace->entry_time) {
60c907abc   Arnaldo Carvalho de Melo   perf trace: Add a...
1653
  		duration = sample->time - ttrace->entry_time;
ae9ed0357   Arnaldo Carvalho de Melo   perf trace: Add d...
1654
1655
1656
1657
  		if (trace__filter_duration(trace, duration))
  			goto out;
  	} else if (trace->duration_filter)
  		goto out;
60c907abc   Arnaldo Carvalho de Melo   perf trace: Add a...
1658

fd2eabaf1   David Ahern   perf trace: Add s...
1659
1660
  	if (trace->summary_only)
  		goto out;
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1661
  	trace__fprintf_entry_head(trace, thread, duration, sample->time, trace->output);
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1662
1663
  
  	if (ttrace->entry_pending) {
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1664
  		fprintf(trace->output, "%-70s", ttrace->entry_str);
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1665
  	} else {
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1666
1667
1668
  		fprintf(trace->output, " ... [");
  		color_fprintf(trace->output, PERF_COLOR_YELLOW, "continued");
  		fprintf(trace->output, "]: %s()", sc->name);
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1669
  	}
da3c9a448   Arnaldo Carvalho de Melo   perf trace: Simpl...
1670
1671
  	if (sc->fmt == NULL) {
  signed_print:
2c82c3ad5   Chang Hyun Park   perf trace: Fix m...
1672
  		fprintf(trace->output, ") = %ld", ret);
da3c9a448   Arnaldo Carvalho de Melo   perf trace: Simpl...
1673
  	} else if (ret < 0 && sc->fmt->errmsg) {
942a91ed3   Masami Hiramatsu   perf trace: Use s...
1674
  		char bf[STRERR_BUFSIZE];
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1675
1676
  		const char *emsg = strerror_r(-ret, bf, sizeof(bf)),
  			   *e = audit_errno_to_name(-ret);
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1677
  		fprintf(trace->output, ") = -1 %s %s", e, emsg);
da3c9a448   Arnaldo Carvalho de Melo   perf trace: Simpl...
1678
  	} else if (ret == 0 && sc->fmt->timeout)
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1679
  		fprintf(trace->output, ") = 0 Timeout");
04b34729e   Arnaldo Carvalho de Melo   perf trace: Allow...
1680
  	else if (sc->fmt->hexret)
2c82c3ad5   Chang Hyun Park   perf trace: Fix m...
1681
  		fprintf(trace->output, ") = %#lx", ret);
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1682
  	else
da3c9a448   Arnaldo Carvalho de Melo   perf trace: Simpl...
1683
  		goto signed_print;
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1684

c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1685
1686
  	fputc('
  ', trace->output);
ae9ed0357   Arnaldo Carvalho de Melo   perf trace: Add d...
1687
  out:
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1688
  	ttrace->entry_pending = false;
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1689
1690
  	return 0;
  }
c522739d7   Arnaldo Carvalho de Melo   perf trace: Use v...
1691
  static int trace__vfs_getname(struct trace *trace, struct perf_evsel *evsel,
0c82adcf1   Stanislav Fomichev   perf trace: Add p...
1692
  			      union perf_event *event __maybe_unused,
c522739d7   Arnaldo Carvalho de Melo   perf trace: Use v...
1693
1694
1695
1696
1697
  			      struct perf_sample *sample)
  {
  	trace->last_vfs_getname = perf_evsel__rawptr(evsel, sample, "pathname");
  	return 0;
  }
1302d88e6   Arnaldo Carvalho de Melo   perf trace: Use s...
1698
  static int trace__sched_stat_runtime(struct trace *trace, struct perf_evsel *evsel,
0c82adcf1   Stanislav Fomichev   perf trace: Add p...
1699
  				     union perf_event *event __maybe_unused,
1302d88e6   Arnaldo Carvalho de Melo   perf trace: Use s...
1700
1701
1702
1703
  				     struct perf_sample *sample)
  {
          u64 runtime = perf_evsel__intval(evsel, sample, "runtime");
  	double runtime_ms = (double)runtime / NSEC_PER_MSEC;
8fb598e5a   David Ahern   perf trace: Fix c...
1704
  	struct thread *thread = machine__findnew_thread(trace->host,
314add6b1   Adrian Hunter   perf tools: chang...
1705
1706
  							sample->pid,
  							sample->tid);
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1707
  	struct thread_trace *ttrace = thread__trace(thread, trace->output);
1302d88e6   Arnaldo Carvalho de Melo   perf trace: Use s...
1708
1709
1710
1711
1712
1713
1714
1715
1716
  
  	if (ttrace == NULL)
  		goto out_dump;
  
  	ttrace->runtime_ms += runtime_ms;
  	trace->runtime_ms += runtime_ms;
  	return 0;
  
  out_dump:
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1717
1718
  	fprintf(trace->output, "%s: comm=%s,pid=%u,runtime=%" PRIu64 ",vruntime=%" PRIu64 ")
  ",
1302d88e6   Arnaldo Carvalho de Melo   perf trace: Use s...
1719
1720
1721
1722
1723
1724
1725
  	       evsel->name,
  	       perf_evsel__strval(evsel, sample, "comm"),
  	       (pid_t)perf_evsel__intval(evsel, sample, "pid"),
  	       runtime,
  	       perf_evsel__intval(evsel, sample, "vruntime"));
  	return 0;
  }
598d02c5a   Stanislav Fomichev   perf trace: Add s...
1726
1727
1728
1729
1730
1731
1732
1733
1734
  static void print_location(FILE *f, struct perf_sample *sample,
  			   struct addr_location *al,
  			   bool print_dso, bool print_sym)
  {
  
  	if ((verbose || print_dso) && al->map)
  		fprintf(f, "%s@", al->map->dso->long_name);
  
  	if ((verbose || print_sym) && al->sym)
4414a3c51   Arnaldo Carvalho de Melo   perf trace: Fix b...
1735
  		fprintf(f, "%s+0x%" PRIx64, al->sym->name,
598d02c5a   Stanislav Fomichev   perf trace: Add s...
1736
1737
  			al->addr - al->sym->start);
  	else if (al->map)
4414a3c51   Arnaldo Carvalho de Melo   perf trace: Fix b...
1738
  		fprintf(f, "0x%" PRIx64, al->addr);
598d02c5a   Stanislav Fomichev   perf trace: Add s...
1739
  	else
4414a3c51   Arnaldo Carvalho de Melo   perf trace: Fix b...
1740
  		fprintf(f, "0x%" PRIx64, sample->addr);
598d02c5a   Stanislav Fomichev   perf trace: Add s...
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
  }
  
  static int trace__pgfault(struct trace *trace,
  			  struct perf_evsel *evsel,
  			  union perf_event *event,
  			  struct perf_sample *sample)
  {
  	struct thread *thread;
  	u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
  	struct addr_location al;
  	char map_type = 'd';
a2ea67d7b   Stanislav Fomichev   perf trace: Add p...
1752
  	struct thread_trace *ttrace;
598d02c5a   Stanislav Fomichev   perf trace: Add s...
1753
1754
  
  	thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
a2ea67d7b   Stanislav Fomichev   perf trace: Add p...
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
  	ttrace = thread__trace(thread, trace->output);
  	if (ttrace == NULL)
  		return -1;
  
  	if (evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ)
  		ttrace->pfmaj++;
  	else
  		ttrace->pfmin++;
  
  	if (trace->summary_only)
  		return 0;
598d02c5a   Stanislav Fomichev   perf trace: Add s...
1766

bb871a9c8   Arnaldo Carvalho de Melo   perf tools: A thr...
1767
  	thread__find_addr_location(thread, cpumode, MAP__FUNCTION,
598d02c5a   Stanislav Fomichev   perf trace: Add s...
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
  			      sample->ip, &al);
  
  	trace__fprintf_entry_head(trace, thread, 0, sample->time, trace->output);
  
  	fprintf(trace->output, "%sfault [",
  		evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ?
  		"maj" : "min");
  
  	print_location(trace->output, sample, &al, false, true);
  
  	fprintf(trace->output, "] => ");
bb871a9c8   Arnaldo Carvalho de Melo   perf tools: A thr...
1779
  	thread__find_addr_location(thread, cpumode, MAP__VARIABLE,
598d02c5a   Stanislav Fomichev   perf trace: Add s...
1780
1781
1782
  				   sample->addr, &al);
  
  	if (!al.map) {
bb871a9c8   Arnaldo Carvalho de Melo   perf tools: A thr...
1783
  		thread__find_addr_location(thread, cpumode,
598d02c5a   Stanislav Fomichev   perf trace: Add s...
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
  					   MAP__FUNCTION, sample->addr, &al);
  
  		if (al.map)
  			map_type = 'x';
  		else
  			map_type = '?';
  	}
  
  	print_location(trace->output, sample, &al, true, false);
  
  	fprintf(trace->output, " (%c%c)
  ", map_type, al.level);
  
  	return 0;
  }
bdc896617   David Ahern   perf trace: Honor...
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
  static bool skip_sample(struct trace *trace, struct perf_sample *sample)
  {
  	if ((trace->pid_list && intlist__find(trace->pid_list, sample->pid)) ||
  	    (trace->tid_list && intlist__find(trace->tid_list, sample->tid)))
  		return false;
  
  	if (trace->pid_list || trace->tid_list)
  		return true;
  
  	return false;
  }
6810fc915   David Ahern   perf trace: Add o...
1810
  static int trace__process_sample(struct perf_tool *tool,
0c82adcf1   Stanislav Fomichev   perf trace: Add p...
1811
  				 union perf_event *event,
6810fc915   David Ahern   perf trace: Add o...
1812
1813
1814
1815
1816
1817
  				 struct perf_sample *sample,
  				 struct perf_evsel *evsel,
  				 struct machine *machine __maybe_unused)
  {
  	struct trace *trace = container_of(tool, struct trace, tool);
  	int err = 0;
744a97194   Arnaldo Carvalho de Melo   perf evsel: Ditch...
1818
  	tracepoint_handler handler = evsel->handler;
6810fc915   David Ahern   perf trace: Add o...
1819

bdc896617   David Ahern   perf trace: Honor...
1820
1821
  	if (skip_sample(trace, sample))
  		return 0;
4bb09192d   David Ahern   perf trace: Add o...
1822
  	if (!trace->full_time && trace->base_time == 0)
6810fc915   David Ahern   perf trace: Add o...
1823
  		trace->base_time = sample->time;
3160565f0   David Ahern   perf trace: Fix s...
1824
1825
  	if (handler) {
  		++trace->nr_events;
0c82adcf1   Stanislav Fomichev   perf trace: Add p...
1826
  		handler(trace, evsel, event, sample);
3160565f0   David Ahern   perf trace: Fix s...
1827
  	}
6810fc915   David Ahern   perf trace: Add o...
1828
1829
1830
  
  	return err;
  }
bdc896617   David Ahern   perf trace: Honor...
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
  static int parse_target_str(struct trace *trace)
  {
  	if (trace->opts.target.pid) {
  		trace->pid_list = intlist__new(trace->opts.target.pid);
  		if (trace->pid_list == NULL) {
  			pr_err("Error parsing process id string
  ");
  			return -EINVAL;
  		}
  	}
  
  	if (trace->opts.target.tid) {
  		trace->tid_list = intlist__new(trace->opts.target.tid);
  		if (trace->tid_list == NULL) {
  			pr_err("Error parsing thread id string
  ");
  			return -EINVAL;
  		}
  	}
  
  	return 0;
  }
1e28fe0a4   Stanislav Fomichev   perf trace: Add p...
1853
  static int trace__record(struct trace *trace, int argc, const char **argv)
5e2485b1a   David Ahern   perf trace: Add r...
1854
1855
1856
1857
1858
1859
1860
1861
  {
  	unsigned int rec_argc, i, j;
  	const char **rec_argv;
  	const char * const record_args[] = {
  		"record",
  		"-R",
  		"-m", "1024",
  		"-c", "1",
5e2485b1a   David Ahern   perf trace: Add r...
1862
  	};
1e28fe0a4   Stanislav Fomichev   perf trace: Add p...
1863
1864
1865
1866
1867
1868
  	const char * const sc_args[] = { "-e", };
  	unsigned int sc_args_nr = ARRAY_SIZE(sc_args);
  	const char * const majpf_args[] = { "-e", "major-faults" };
  	unsigned int majpf_args_nr = ARRAY_SIZE(majpf_args);
  	const char * const minpf_args[] = { "-e", "minor-faults" };
  	unsigned int minpf_args_nr = ARRAY_SIZE(minpf_args);
9aca7f179   David Ahern   perf trace: Add s...
1869
  	/* +1 is for the event string below */
1e28fe0a4   Stanislav Fomichev   perf trace: Add p...
1870
1871
  	rec_argc = ARRAY_SIZE(record_args) + sc_args_nr + 1 +
  		majpf_args_nr + minpf_args_nr + argc;
5e2485b1a   David Ahern   perf trace: Add r...
1872
1873
1874
1875
  	rec_argv = calloc(rec_argc + 1, sizeof(char *));
  
  	if (rec_argv == NULL)
  		return -ENOMEM;
1e28fe0a4   Stanislav Fomichev   perf trace: Add p...
1876
  	j = 0;
5e2485b1a   David Ahern   perf trace: Add r...
1877
  	for (i = 0; i < ARRAY_SIZE(record_args); i++)
1e28fe0a4   Stanislav Fomichev   perf trace: Add p...
1878
  		rec_argv[j++] = record_args[i];
e281a9606   Stanislav Fomichev   perf trace: Add p...
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
  	if (trace->trace_syscalls) {
  		for (i = 0; i < sc_args_nr; i++)
  			rec_argv[j++] = sc_args[i];
  
  		/* event string may be different for older kernels - e.g., RHEL6 */
  		if (is_valid_tracepoint("raw_syscalls:sys_enter"))
  			rec_argv[j++] = "raw_syscalls:sys_enter,raw_syscalls:sys_exit";
  		else if (is_valid_tracepoint("syscalls:sys_enter"))
  			rec_argv[j++] = "syscalls:sys_enter,syscalls:sys_exit";
  		else {
  			pr_err("Neither raw_syscalls nor syscalls events exist.
  ");
  			return -1;
  		}
9aca7f179   David Ahern   perf trace: Add s...
1893
  	}
9aca7f179   David Ahern   perf trace: Add s...
1894

1e28fe0a4   Stanislav Fomichev   perf trace: Add p...
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
  	if (trace->trace_pgfaults & TRACE_PFMAJ)
  		for (i = 0; i < majpf_args_nr; i++)
  			rec_argv[j++] = majpf_args[i];
  
  	if (trace->trace_pgfaults & TRACE_PFMIN)
  		for (i = 0; i < minpf_args_nr; i++)
  			rec_argv[j++] = minpf_args[i];
  
  	for (i = 0; i < (unsigned int)argc; i++)
  		rec_argv[j++] = argv[i];
5e2485b1a   David Ahern   perf trace: Add r...
1905

1e28fe0a4   Stanislav Fomichev   perf trace: Add p...
1906
  	return cmd_record(j, rec_argv, NULL);
5e2485b1a   David Ahern   perf trace: Add r...
1907
  }
bf2575c12   David Ahern   perf trace: Add s...
1908
  static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp);
c522739d7   Arnaldo Carvalho de Melo   perf trace: Use v...
1909
1910
  static void perf_evlist__add_vfs_getname(struct perf_evlist *evlist)
  {
ef503831d   Arnaldo Carvalho de Melo   perf evsel: Remov...
1911
  	struct perf_evsel *evsel = perf_evsel__newtp("probe", "vfs_getname");
c522739d7   Arnaldo Carvalho de Melo   perf trace: Use v...
1912
1913
1914
1915
1916
1917
1918
  	if (evsel == NULL)
  		return;
  
  	if (perf_evsel__field(evsel, "pathname") == NULL) {
  		perf_evsel__delete(evsel);
  		return;
  	}
744a97194   Arnaldo Carvalho de Melo   perf evsel: Ditch...
1919
  	evsel->handler = trace__vfs_getname;
c522739d7   Arnaldo Carvalho de Melo   perf trace: Use v...
1920
1921
  	perf_evlist__add(evlist, evsel);
  }
598d02c5a   Stanislav Fomichev   perf trace: Add s...
1922
1923
1924
1925
1926
1927
1928
  static int perf_evlist__add_pgfault(struct perf_evlist *evlist,
  				    u64 config)
  {
  	struct perf_evsel *evsel;
  	struct perf_event_attr attr = {
  		.type = PERF_TYPE_SOFTWARE,
  		.mmap_data = 1,
598d02c5a   Stanislav Fomichev   perf trace: Add s...
1929
1930
1931
  	};
  
  	attr.config = config;
0524798cc   Arnaldo Carvalho de Melo   perf tools: Fix b...
1932
  	attr.sample_period = 1;
598d02c5a   Stanislav Fomichev   perf trace: Add s...
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
  
  	event_attr_init(&attr);
  
  	evsel = perf_evsel__new(&attr);
  	if (!evsel)
  		return -ENOMEM;
  
  	evsel->handler = trace__pgfault;
  	perf_evlist__add(evlist, evsel);
  
  	return 0;
  }
f15eb531d   Namhyung Kim   perf trace: Add s...
1945
  static int trace__run(struct trace *trace, int argc, const char **argv)
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1946
  {
334fe7a3c   Namhyung Kim   perf evlist: Remo...
1947
  	struct perf_evlist *evlist = perf_evlist__new();
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1948
  	struct perf_evsel *evsel;
efd5745e4   Arnaldo Carvalho de Melo   perf trace: Count...
1949
1950
  	int err = -1, i;
  	unsigned long before;
f15eb531d   Namhyung Kim   perf trace: Add s...
1951
  	const bool forks = argc > 0;
46fb3c21d   Arnaldo Carvalho de Melo   perf trace: Filte...
1952
  	bool draining = false;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1953

75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
1954
  	trace->live = true;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1955
  	if (evlist == NULL) {
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1956
1957
  		fprintf(trace->output, "Not enough memory to run!
  ");
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1958
1959
  		goto out;
  	}
e281a9606   Stanislav Fomichev   perf trace: Add p...
1960
1961
1962
  	if (trace->trace_syscalls &&
  	    perf_evlist__add_syscall_newtp(evlist, trace__sys_enter,
  					   trace__sys_exit))
87f918685   Ramkumar Ramachandra   perf trace: Impro...
1963
  		goto out_error_tp;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1964

e281a9606   Stanislav Fomichev   perf trace: Add p...
1965
1966
  	if (trace->trace_syscalls)
  		perf_evlist__add_vfs_getname(evlist);
c522739d7   Arnaldo Carvalho de Melo   perf trace: Use v...
1967

598d02c5a   Stanislav Fomichev   perf trace: Add s...
1968
1969
1970
1971
1972
1973
1974
  	if ((trace->trace_pgfaults & TRACE_PFMAJ) &&
  	    perf_evlist__add_pgfault(evlist, PERF_COUNT_SW_PAGE_FAULTS_MAJ))
  		goto out_error_tp;
  
  	if ((trace->trace_pgfaults & TRACE_PFMIN) &&
  	    perf_evlist__add_pgfault(evlist, PERF_COUNT_SW_PAGE_FAULTS_MIN))
  		goto out_error_tp;
1302d88e6   Arnaldo Carvalho de Melo   perf trace: Use s...
1975
  	if (trace->sched &&
87f918685   Ramkumar Ramachandra   perf trace: Impro...
1976
1977
1978
  		perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime",
  				trace__sched_stat_runtime))
  		goto out_error_tp;
1302d88e6   Arnaldo Carvalho de Melo   perf trace: Use s...
1979

514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1980
1981
  	err = perf_evlist__create_maps(evlist, &trace->opts.target);
  	if (err < 0) {
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1982
1983
  		fprintf(trace->output, "Problems parsing the target to trace, check your options!
  ");
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1984
1985
  		goto out_delete_evlist;
  	}
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1986
1987
  	err = trace__symbols_init(trace, evlist);
  	if (err < 0) {
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1988
1989
  		fprintf(trace->output, "Problems initializing symbol libraries!
  ");
03ad9747c   Arnaldo Carvalho de Melo   perf evlist: Move...
1990
  		goto out_delete_evlist;
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1991
  	}
f77a95182   Arnaldo Carvalho de Melo   perf evlist: Set ...
1992
  	perf_evlist__config(evlist, &trace->opts);
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1993

f15eb531d   Namhyung Kim   perf trace: Add s...
1994
1995
1996
1997
  	signal(SIGCHLD, sig_handler);
  	signal(SIGINT, sig_handler);
  
  	if (forks) {
6ef73ec44   Namhyung Kim   perf evlist: Pass...
1998
  		err = perf_evlist__prepare_workload(evlist, &trace->opts.target,
735f7e0bb   Arnaldo Carvalho de Melo   perf evlist: Move...
1999
  						    argv, false, NULL);
f15eb531d   Namhyung Kim   perf trace: Add s...
2000
  		if (err < 0) {
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
2001
2002
  			fprintf(trace->output, "Couldn't run the workload!
  ");
03ad9747c   Arnaldo Carvalho de Melo   perf evlist: Move...
2003
  			goto out_delete_evlist;
f15eb531d   Namhyung Kim   perf trace: Add s...
2004
2005
  		}
  	}
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2006
  	err = perf_evlist__open(evlist);
a8f23d8f8   Arnaldo Carvalho de Melo   perf trace: Impro...
2007
2008
  	if (err < 0)
  		goto out_error_open;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2009

f885037ef   Jiri Olsa   perf trace: Honou...
2010
  	err = perf_evlist__mmap(evlist, trace->opts.mmap_pages, false);
e09b18d49   Arnaldo Carvalho de Melo   perf trace: Provi...
2011
2012
  	if (err < 0)
  		goto out_error_mmap;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2013
2014
  
  	perf_evlist__enable(evlist);
f15eb531d   Namhyung Kim   perf trace: Add s...
2015
2016
2017
  
  	if (forks)
  		perf_evlist__start_workload(evlist);
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
2018
  	trace->multiple_threads = evlist->threads->map[0] == -1 || evlist->threads->nr > 1;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2019
  again:
efd5745e4   Arnaldo Carvalho de Melo   perf trace: Count...
2020
  	before = trace->nr_events;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2021
2022
2023
2024
2025
2026
  
  	for (i = 0; i < evlist->nr_mmaps; i++) {
  		union perf_event *event;
  
  		while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
  			const u32 type = event->header.type;
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
2027
  			tracepoint_handler handler;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2028
  			struct perf_sample sample;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2029

efd5745e4   Arnaldo Carvalho de Melo   perf trace: Count...
2030
  			++trace->nr_events;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2031

514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2032
2033
  			err = perf_evlist__parse_sample(evlist, event, &sample);
  			if (err) {
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
2034
2035
  				fprintf(trace->output, "Can't parse sample, err = %d, skipping...
  ", err);
8e50d384c   Zhouyi Zhou   perf tools: Fixup...
2036
  				goto next_event;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2037
  			}
4bb09192d   David Ahern   perf trace: Add o...
2038
  			if (!trace->full_time && trace->base_time == 0)
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
2039
2040
2041
  				trace->base_time = sample.time;
  
  			if (type != PERF_RECORD_SAMPLE) {
162f0befd   Frederic Weisbecker   perf tools: Add t...
2042
  				trace__process_event(trace, trace->host, event, &sample);
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
2043
2044
  				continue;
  			}
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2045
2046
  			evsel = perf_evlist__id2evsel(evlist, sample.id);
  			if (evsel == NULL) {
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
2047
2048
  				fprintf(trace->output, "Unknown tp ID %" PRIu64 ", skipping...
  ", sample.id);
8e50d384c   Zhouyi Zhou   perf tools: Fixup...
2049
  				goto next_event;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2050
  			}
598d02c5a   Stanislav Fomichev   perf trace: Add s...
2051
2052
  			if (evsel->attr.type == PERF_TYPE_TRACEPOINT &&
  			    sample.raw_data == NULL) {
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
2053
2054
  				fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...
  ",
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
2055
2056
  				       perf_evsel__name(evsel), sample.tid,
  				       sample.cpu, sample.raw_size);
8e50d384c   Zhouyi Zhou   perf tools: Fixup...
2057
  				goto next_event;
fc551f8d4   Arnaldo Carvalho de Melo   perf trace: Check...
2058
  			}
744a97194   Arnaldo Carvalho de Melo   perf evsel: Ditch...
2059
  			handler = evsel->handler;
0c82adcf1   Stanislav Fomichev   perf trace: Add p...
2060
  			handler(trace, evsel, event, &sample);
8e50d384c   Zhouyi Zhou   perf tools: Fixup...
2061
2062
  next_event:
  			perf_evlist__mmap_consume(evlist, i);
20c5f10eb   Arnaldo Carvalho de Melo   perf trace: Check...
2063

ba209f856   Arnaldo Carvalho de Melo   perf trace: Impro...
2064
2065
  			if (interrupted)
  				goto out_disable;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2066
2067
  		}
  	}
efd5745e4   Arnaldo Carvalho de Melo   perf trace: Count...
2068
  	if (trace->nr_events == before) {
ba209f856   Arnaldo Carvalho de Melo   perf trace: Impro...
2069
  		int timeout = done ? 100 : -1;
f15eb531d   Namhyung Kim   perf trace: Add s...
2070

46fb3c21d   Arnaldo Carvalho de Melo   perf trace: Filte...
2071
2072
2073
  		if (!draining && perf_evlist__poll(evlist, timeout) > 0) {
  			if (perf_evlist__filter_pollfd(evlist, POLLERR | POLLHUP) == 0)
  				draining = true;
ba209f856   Arnaldo Carvalho de Melo   perf trace: Impro...
2074
  			goto again;
46fb3c21d   Arnaldo Carvalho de Melo   perf trace: Filte...
2075
  		}
ba209f856   Arnaldo Carvalho de Melo   perf trace: Impro...
2076
2077
  	} else {
  		goto again;
f15eb531d   Namhyung Kim   perf trace: Add s...
2078
  	}
ba209f856   Arnaldo Carvalho de Melo   perf trace: Impro...
2079
2080
  out_disable:
  	perf_evlist__disable(evlist);
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2081

c522739d7   Arnaldo Carvalho de Melo   perf trace: Use v...
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
  	if (!err) {
  		if (trace->summary)
  			trace__fprintf_thread_summary(trace, trace->output);
  
  		if (trace->show_tool_stats) {
  			fprintf(trace->output, "Stats:
   "
  					       " vfs_getname : %" PRIu64 "
  "
  					       " proc_getname: %" PRIu64 "
  ",
  				trace->stats.vfs_getname,
  				trace->stats.proc_getname);
  		}
  	}
bf2575c12   David Ahern   perf trace: Add s...
2097

514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2098
2099
2100
  out_delete_evlist:
  	perf_evlist__delete(evlist);
  out:
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
2101
  	trace->live = false;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2102
  	return err;
6ef068cb8   Arnaldo Carvalho de Melo   perf evlist: Intr...
2103
2104
  {
  	char errbuf[BUFSIZ];
a8f23d8f8   Arnaldo Carvalho de Melo   perf trace: Impro...
2105
2106
  
  out_error_tp:
6ef068cb8   Arnaldo Carvalho de Melo   perf evlist: Intr...
2107
  	perf_evlist__strerror_tp(evlist, errno, errbuf, sizeof(errbuf));
a8f23d8f8   Arnaldo Carvalho de Melo   perf trace: Impro...
2108
  	goto out_error;
e09b18d49   Arnaldo Carvalho de Melo   perf trace: Provi...
2109
2110
2111
  out_error_mmap:
  	perf_evlist__strerror_mmap(evlist, errno, errbuf, sizeof(errbuf));
  	goto out_error;
a8f23d8f8   Arnaldo Carvalho de Melo   perf trace: Impro...
2112
2113
2114
2115
  out_error_open:
  	perf_evlist__strerror_open(evlist, errno, errbuf, sizeof(errbuf));
  
  out_error:
6ef068cb8   Arnaldo Carvalho de Melo   perf evlist: Intr...
2116
2117
  	fprintf(trace->output, "%s
  ", errbuf);
87f918685   Ramkumar Ramachandra   perf trace: Impro...
2118
  	goto out_delete_evlist;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2119
  }
a8f23d8f8   Arnaldo Carvalho de Melo   perf trace: Impro...
2120
  }
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2121

6810fc915   David Ahern   perf trace: Add o...
2122
2123
2124
  static int trace__replay(struct trace *trace)
  {
  	const struct perf_evsel_str_handler handlers[] = {
c522739d7   Arnaldo Carvalho de Melo   perf trace: Use v...
2125
  		{ "probe:vfs_getname",	     trace__vfs_getname, },
6810fc915   David Ahern   perf trace: Add o...
2126
  	};
f5fc14124   Jiri Olsa   perf tools: Add d...
2127
2128
2129
2130
  	struct perf_data_file file = {
  		.path  = input_name,
  		.mode  = PERF_DATA_MODE_READ,
  	};
6810fc915   David Ahern   perf trace: Add o...
2131
  	struct perf_session *session;
003824e8c   Namhyung Kim   perf trace: Fix s...
2132
  	struct perf_evsel *evsel;
6810fc915   David Ahern   perf trace: Add o...
2133
2134
2135
2136
  	int err = -1;
  
  	trace->tool.sample	  = trace__process_sample;
  	trace->tool.mmap	  = perf_event__process_mmap;
384c671e3   David Ahern   perf trace: Add m...
2137
  	trace->tool.mmap2	  = perf_event__process_mmap2;
6810fc915   David Ahern   perf trace: Add o...
2138
2139
2140
2141
2142
2143
  	trace->tool.comm	  = perf_event__process_comm;
  	trace->tool.exit	  = perf_event__process_exit;
  	trace->tool.fork	  = perf_event__process_fork;
  	trace->tool.attr	  = perf_event__process_attr;
  	trace->tool.tracing_data = perf_event__process_tracing_data;
  	trace->tool.build_id	  = perf_event__process_build_id;
0a8cb85c2   Jiri Olsa   perf tools: Renam...
2144
  	trace->tool.ordered_events = true;
6810fc915   David Ahern   perf trace: Add o...
2145
2146
2147
2148
  	trace->tool.ordering_requires_timestamps = true;
  
  	/* add tid to output */
  	trace->multiple_threads = true;
f5fc14124   Jiri Olsa   perf tools: Add d...
2149
  	session = perf_session__new(&file, false, &trace->tool);
6810fc915   David Ahern   perf trace: Add o...
2150
  	if (session == NULL)
52e028349   Taeung Song   perf tools: Modif...
2151
  		return -1;
6810fc915   David Ahern   perf trace: Add o...
2152

0a7e6d1b6   Namhyung Kim   perf tools: Check...
2153
  	if (symbol__init(&session->header.env) < 0)
cb2ffae24   Namhyung Kim   perf trace: Move ...
2154
  		goto out;
8fb598e5a   David Ahern   perf trace: Fix c...
2155
  	trace->host = &session->machines.host;
6810fc915   David Ahern   perf trace: Add o...
2156
2157
2158
  	err = perf_session__set_tracepoints_handlers(session, handlers);
  	if (err)
  		goto out;
003824e8c   Namhyung Kim   perf trace: Fix s...
2159
2160
  	evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
  						     "raw_syscalls:sys_enter");
9aca7f179   David Ahern   perf trace: Add s...
2161
2162
2163
2164
  	/* older kernels have syscalls tp versus raw_syscalls */
  	if (evsel == NULL)
  		evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
  							     "syscalls:sys_enter");
003824e8c   Namhyung Kim   perf trace: Fix s...
2165

e281a9606   Stanislav Fomichev   perf trace: Add p...
2166
2167
2168
  	if (evsel &&
  	    (perf_evsel__init_syscall_tp(evsel, trace__sys_enter) < 0 ||
  	    perf_evsel__init_sc_tp_ptr_field(evsel, args))) {
003824e8c   Namhyung Kim   perf trace: Fix s...
2169
2170
2171
2172
2173
2174
2175
  		pr_err("Error during initialize raw_syscalls:sys_enter event
  ");
  		goto out;
  	}
  
  	evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
  						     "raw_syscalls:sys_exit");
9aca7f179   David Ahern   perf trace: Add s...
2176
2177
2178
  	if (evsel == NULL)
  		evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
  							     "syscalls:sys_exit");
e281a9606   Stanislav Fomichev   perf trace: Add p...
2179
2180
2181
  	if (evsel &&
  	    (perf_evsel__init_syscall_tp(evsel, trace__sys_exit) < 0 ||
  	    perf_evsel__init_sc_tp_uint_field(evsel, ret))) {
003824e8c   Namhyung Kim   perf trace: Fix s...
2182
2183
  		pr_err("Error during initialize raw_syscalls:sys_exit event
  ");
6810fc915   David Ahern   perf trace: Add o...
2184
2185
  		goto out;
  	}
1e28fe0a4   Stanislav Fomichev   perf trace: Add p...
2186
2187
2188
2189
2190
2191
2192
  	evlist__for_each(session->evlist, evsel) {
  		if (evsel->attr.type == PERF_TYPE_SOFTWARE &&
  		    (evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ||
  		     evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MIN ||
  		     evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS))
  			evsel->handler = trace__pgfault;
  	}
bdc896617   David Ahern   perf trace: Honor...
2193
2194
2195
  	err = parse_target_str(trace);
  	if (err != 0)
  		goto out;
6810fc915   David Ahern   perf trace: Add o...
2196
2197
2198
2199
2200
  	setup_pager();
  
  	err = perf_session__process_events(session, &trace->tool);
  	if (err)
  		pr_err("Failed to process events, error %d", err);
bf2575c12   David Ahern   perf trace: Add s...
2201
2202
  	else if (trace->summary)
  		trace__fprintf_thread_summary(trace, trace->output);
6810fc915   David Ahern   perf trace: Add o...
2203
2204
2205
2206
2207
  out:
  	perf_session__delete(session);
  
  	return err;
  }
1302d88e6   Arnaldo Carvalho de Melo   perf trace: Use s...
2208
2209
2210
  static size_t trace__fprintf_threads_header(FILE *fp)
  {
  	size_t printed;
99ff71505   Pekka Enberg   perf trace: Simpl...
2211
2212
2213
2214
  	printed  = fprintf(fp, "
   Summary of events:
  
  ");
bf2575c12   David Ahern   perf trace: Add s...
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
  
  	return printed;
  }
  
  static size_t thread__dump_stats(struct thread_trace *ttrace,
  				 struct trace *trace, FILE *fp)
  {
  	struct stats *stats;
  	size_t printed = 0;
  	struct syscall *sc;
  	struct int_node *inode = intlist__first(ttrace->syscall_stats);
  
  	if (inode == NULL)
  		return 0;
  
  	printed += fprintf(fp, "
  ");
27a778b51   Pekka Enberg   perf trace: Tweak...
2232
2233
2234
2235
2236
2237
  	printed += fprintf(fp, "   syscall            calls      min       avg       max      stddev
  ");
  	printed += fprintf(fp, "                               (msec)    (msec)    (msec)        (%%)
  ");
  	printed += fprintf(fp, "   --------------- -------- --------- --------- ---------     ------
  ");
99ff71505   Pekka Enberg   perf trace: Simpl...
2238

bf2575c12   David Ahern   perf trace: Add s...
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
  	/* each int_node is a syscall */
  	while (inode) {
  		stats = inode->priv;
  		if (stats) {
  			double min = (double)(stats->min) / NSEC_PER_MSEC;
  			double max = (double)(stats->max) / NSEC_PER_MSEC;
  			double avg = avg_stats(stats);
  			double pct;
  			u64 n = (u64) stats->n;
  
  			pct = avg ? 100.0 * stddev_stats(stats)/avg : 0.0;
  			avg /= NSEC_PER_MSEC;
  
  			sc = &trace->syscalls.table[inode->i];
99ff71505   Pekka Enberg   perf trace: Simpl...
2253
  			printed += fprintf(fp, "   %-15s", sc->name);
27a778b51   Pekka Enberg   perf trace: Tweak...
2254
  			printed += fprintf(fp, " %8" PRIu64 " %9.3f %9.3f",
7f7a4138c   Pekka Enberg   perf trace: Chang...
2255
  					   n, min, avg);
27a778b51   Pekka Enberg   perf trace: Tweak...
2256
2257
  			printed += fprintf(fp, " %9.3f %9.2f%%
  ", max, pct);
bf2575c12   David Ahern   perf trace: Add s...
2258
2259
2260
2261
2262
2263
2264
2265
  		}
  
  		inode = intlist__next(inode);
  	}
  
  	printed += fprintf(fp, "
  
  ");
1302d88e6   Arnaldo Carvalho de Melo   perf trace: Use s...
2266
2267
2268
  
  	return printed;
  }
896cbb56b   David Ahern   perf trace: Use n...
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
  /* struct used to pass data to per-thread function */
  struct summary_data {
  	FILE *fp;
  	struct trace *trace;
  	size_t printed;
  };
  
  static int trace__fprintf_one_thread(struct thread *thread, void *priv)
  {
  	struct summary_data *data = priv;
  	FILE *fp = data->fp;
  	size_t printed = data->printed;
  	struct trace *trace = data->trace;
89dceb22c   Namhyung Kim   perf trace: Use t...
2282
  	struct thread_trace *ttrace = thread__priv(thread);
896cbb56b   David Ahern   perf trace: Use n...
2283
2284
2285
2286
2287
2288
  	double ratio;
  
  	if (ttrace == NULL)
  		return 0;
  
  	ratio = (double)ttrace->nr_events / trace->nr_events * 100.0;
15e65c693   Pekka Enberg   perf trace: Remov...
2289
  	printed += fprintf(fp, " %s (%d), ", thread__comm_str(thread), thread->tid);
99ff71505   Pekka Enberg   perf trace: Simpl...
2290
  	printed += fprintf(fp, "%lu events, ", ttrace->nr_events);
15e65c693   Pekka Enberg   perf trace: Remov...
2291
  	printed += fprintf(fp, "%.1f%%", ratio);
a2ea67d7b   Stanislav Fomichev   perf trace: Add p...
2292
2293
2294
2295
  	if (ttrace->pfmaj)
  		printed += fprintf(fp, ", %lu majfaults", ttrace->pfmaj);
  	if (ttrace->pfmin)
  		printed += fprintf(fp, ", %lu minfaults", ttrace->pfmin);
99ff71505   Pekka Enberg   perf trace: Simpl...
2296
2297
  	printed += fprintf(fp, ", %.3f msec
  ", ttrace->runtime_ms);
bf2575c12   David Ahern   perf trace: Add s...
2298
  	printed += thread__dump_stats(ttrace, trace, fp);
896cbb56b   David Ahern   perf trace: Use n...
2299
2300
2301
2302
2303
  
  	data->printed += printed;
  
  	return 0;
  }
1302d88e6   Arnaldo Carvalho de Melo   perf trace: Use s...
2304
2305
  static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp)
  {
896cbb56b   David Ahern   perf trace: Use n...
2306
2307
2308
2309
2310
  	struct summary_data data = {
  		.fp = fp,
  		.trace = trace
  	};
  	data.printed = trace__fprintf_threads_header(fp);
1302d88e6   Arnaldo Carvalho de Melo   perf trace: Use s...
2311

896cbb56b   David Ahern   perf trace: Use n...
2312
2313
2314
  	machine__for_each_thread(trace->host, trace__fprintf_one_thread, &data);
  
  	return data.printed;
1302d88e6   Arnaldo Carvalho de Melo   perf trace: Use s...
2315
  }
ae9ed0357   Arnaldo Carvalho de Melo   perf trace: Add d...
2316
2317
2318
2319
2320
2321
2322
2323
  static int trace__set_duration(const struct option *opt, const char *str,
  			       int unset __maybe_unused)
  {
  	struct trace *trace = opt->value;
  
  	trace->duration_filter = atof(str);
  	return 0;
  }
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
  static int trace__open_output(struct trace *trace, const char *filename)
  {
  	struct stat st;
  
  	if (!stat(filename, &st) && st.st_size) {
  		char oldname[PATH_MAX];
  
  		scnprintf(oldname, sizeof(oldname), "%s.old", filename);
  		unlink(oldname);
  		rename(filename, oldname);
  	}
  
  	trace->output = fopen(filename, "w");
  
  	return trace->output == NULL ? -errno : 0;
  }
598d02c5a   Stanislav Fomichev   perf trace: Add s...
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
  static int parse_pagefaults(const struct option *opt, const char *str,
  			    int unset __maybe_unused)
  {
  	int *trace_pgfaults = opt->value;
  
  	if (strcmp(str, "all") == 0)
  		*trace_pgfaults |= TRACE_PFMAJ | TRACE_PFMIN;
  	else if (strcmp(str, "maj") == 0)
  		*trace_pgfaults |= TRACE_PFMAJ;
  	else if (strcmp(str, "min") == 0)
  		*trace_pgfaults |= TRACE_PFMIN;
  	else
  		return -1;
  
  	return 0;
  }
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2356
2357
2358
  int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
  {
  	const char * const trace_usage[] = {
f15eb531d   Namhyung Kim   perf trace: Add s...
2359
2360
  		"perf trace [<options>] [<command>]",
  		"perf trace [<options>] -- <command> [<options>]",
5e2485b1a   David Ahern   perf trace: Add r...
2361
2362
  		"perf trace record [<options>] [<command>]",
  		"perf trace record [<options>] -- <command> [<options>]",
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2363
2364
2365
  		NULL
  	};
  	struct trace trace = {
c522739d7   Arnaldo Carvalho de Melo   perf trace: Use v...
2366
2367
2368
2369
  		.audit = {
  			.machine = audit_detect_machine(),
  			.open_id = audit_name_to_syscall("open", trace.audit.machine),
  		},
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
  		.syscalls = {
  			. max = -1,
  		},
  		.opts = {
  			.target = {
  				.uid	   = UINT_MAX,
  				.uses_mmap = true,
  			},
  			.user_freq     = UINT_MAX,
  			.user_interval = ULLONG_MAX,
509051ea8   Arnaldo Carvalho de Melo   perf record: Rena...
2380
  			.no_buffering  = true,
38d5447d6   Arnaldo Carvalho de Melo   perf trace: Let t...
2381
  			.mmap_pages    = UINT_MAX,
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2382
  		},
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
2383
  		.output = stdout,
50c95cbd7   Arnaldo Carvalho de Melo   perf trace: Add o...
2384
  		.show_comm = true,
e281a9606   Stanislav Fomichev   perf trace: Add p...
2385
  		.trace_syscalls = true,
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2386
  	};
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
2387
  	const char *output_name = NULL;
2ae3a312c   Arnaldo Carvalho de Melo   perf trace: Allow...
2388
  	const char *ev_qualifier_str = NULL;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2389
  	const struct option trace_options[] = {
50c95cbd7   Arnaldo Carvalho de Melo   perf trace: Add o...
2390
2391
  	OPT_BOOLEAN(0, "comm", &trace.show_comm,
  		    "show the thread COMM next to its id"),
c522739d7   Arnaldo Carvalho de Melo   perf trace: Use v...
2392
  	OPT_BOOLEAN(0, "tool_stats", &trace.show_tool_stats, "show tool stats"),
2ae3a312c   Arnaldo Carvalho de Melo   perf trace: Allow...
2393
2394
  	OPT_STRING('e', "expr", &ev_qualifier_str, "expr",
  		    "list of events to trace"),
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
2395
  	OPT_STRING('o', "output", &output_name, "file", "output file name"),
6810fc915   David Ahern   perf trace: Add o...
2396
  	OPT_STRING('i', "input", &input_name, "file", "Analyze events in file"),
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2397
2398
  	OPT_STRING('p', "pid", &trace.opts.target.pid, "pid",
  		    "trace events on existing process id"),
ac9be8ee4   David Ahern   perf trace: Make ...
2399
  	OPT_STRING('t', "tid", &trace.opts.target.tid, "tid",
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2400
  		    "trace events on existing thread id"),
ac9be8ee4   David Ahern   perf trace: Make ...
2401
  	OPT_BOOLEAN('a', "all-cpus", &trace.opts.target.system_wide,
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2402
  		    "system-wide collection from all CPUs"),
ac9be8ee4   David Ahern   perf trace: Make ...
2403
  	OPT_STRING('C', "cpu", &trace.opts.target.cpu_list, "cpu",
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2404
  		    "list of cpus to monitor"),
6810fc915   David Ahern   perf trace: Add o...
2405
  	OPT_BOOLEAN(0, "no-inherit", &trace.opts.no_inherit,
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2406
  		    "child tasks do not inherit counters"),
994a1f78b   Jiri Olsa   perf tools: Check...
2407
2408
2409
  	OPT_CALLBACK('m', "mmap-pages", &trace.opts.mmap_pages, "pages",
  		     "number of mmap data pages",
  		     perf_evlist__parse_mmap_pages),
ac9be8ee4   David Ahern   perf trace: Make ...
2410
  	OPT_STRING('u', "uid", &trace.opts.target.uid_str, "user",
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2411
  		   "user to profile"),
ae9ed0357   Arnaldo Carvalho de Melo   perf trace: Add d...
2412
2413
2414
  	OPT_CALLBACK(0, "duration", &trace, "float",
  		     "show only events with duration > N.M ms",
  		     trace__set_duration),
1302d88e6   Arnaldo Carvalho de Melo   perf trace: Use s...
2415
  	OPT_BOOLEAN(0, "sched", &trace.sched, "show blocking scheduler events"),
7c304ee0f   Arnaldo Carvalho de Melo   perf trace: Add -...
2416
  	OPT_INCR('v', "verbose", &verbose, "be more verbose"),
4bb09192d   David Ahern   perf trace: Add o...
2417
2418
  	OPT_BOOLEAN('T', "time", &trace.full_time,
  		    "Show full timestamp, not time relative to first start"),
fd2eabaf1   David Ahern   perf trace: Add s...
2419
2420
2421
2422
  	OPT_BOOLEAN('s', "summary", &trace.summary_only,
  		    "Show only syscall summary with statistics"),
  	OPT_BOOLEAN('S', "with-summary", &trace.summary,
  		    "Show all syscalls and summary with statistics"),
598d02c5a   Stanislav Fomichev   perf trace: Add s...
2423
2424
  	OPT_CALLBACK_DEFAULT('F', "pf", &trace.trace_pgfaults, "all|maj|min",
  		     "Trace pagefaults", parse_pagefaults, "maj"),
e281a9606   Stanislav Fomichev   perf trace: Add p...
2425
  	OPT_BOOLEAN(0, "syscalls", &trace.trace_syscalls, "Trace syscalls"),
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2426
2427
2428
  	OPT_END()
  	};
  	int err;
32caf0d1f   Namhyung Kim   perf trace: Valid...
2429
  	char bf[BUFSIZ];
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2430

1e28fe0a4   Stanislav Fomichev   perf trace: Add p...
2431
2432
  	argc = parse_options(argc, argv, trace_options, trace_usage,
  			     PARSE_OPT_STOP_AT_NON_OPTION);
fd2eabaf1   David Ahern   perf trace: Add s...
2433

598d02c5a   Stanislav Fomichev   perf trace: Add s...
2434
2435
2436
2437
  	if (trace.trace_pgfaults) {
  		trace.opts.sample_address = true;
  		trace.opts.sample_time = true;
  	}
1e28fe0a4   Stanislav Fomichev   perf trace: Add p...
2438
2439
2440
2441
2442
2443
  	if ((argc >= 1) && (strcmp(argv[0], "record") == 0))
  		return trace__record(&trace, argc-1, &argv[1]);
  
  	/* summary_only implies summary option, but don't overwrite summary if set */
  	if (trace.summary_only)
  		trace.summary = trace.summary_only;
e281a9606   Stanislav Fomichev   perf trace: Add p...
2444
2445
2446
2447
2448
  	if (!trace.trace_syscalls && !trace.trace_pgfaults) {
  		pr_err("Please specify something to trace.
  ");
  		return -1;
  	}
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
2449
2450
2451
2452
2453
2454
2455
  	if (output_name != NULL) {
  		err = trace__open_output(&trace, output_name);
  		if (err < 0) {
  			perror("failed to create output file");
  			goto out;
  		}
  	}
2ae3a312c   Arnaldo Carvalho de Melo   perf trace: Allow...
2456
  	if (ev_qualifier_str != NULL) {
b059efdf5   Arnaldo Carvalho de Melo   perf trace: Suppo...
2457
2458
2459
2460
2461
2462
  		const char *s = ev_qualifier_str;
  
  		trace.not_ev_qualifier = *s == '!';
  		if (trace.not_ev_qualifier)
  			++s;
  		trace.ev_qualifier = strlist__new(true, s);
2ae3a312c   Arnaldo Carvalho de Melo   perf trace: Allow...
2463
  		if (trace.ev_qualifier == NULL) {
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
2464
2465
2466
2467
  			fputs("Not enough memory to parse event qualifier",
  			      trace.output);
  			err = -ENOMEM;
  			goto out_close;
2ae3a312c   Arnaldo Carvalho de Melo   perf trace: Allow...
2468
2469
  		}
  	}
602ad878d   Arnaldo Carvalho de Melo   perf target: Shor...
2470
  	err = target__validate(&trace.opts.target);
32caf0d1f   Namhyung Kim   perf trace: Valid...
2471
  	if (err) {
602ad878d   Arnaldo Carvalho de Melo   perf target: Shor...
2472
  		target__strerror(&trace.opts.target, err, bf, sizeof(bf));
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
2473
2474
  		fprintf(trace.output, "%s", bf);
  		goto out_close;
32caf0d1f   Namhyung Kim   perf trace: Valid...
2475
  	}
602ad878d   Arnaldo Carvalho de Melo   perf target: Shor...
2476
  	err = target__parse_uid(&trace.opts.target);
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2477
  	if (err) {
602ad878d   Arnaldo Carvalho de Melo   perf target: Shor...
2478
  		target__strerror(&trace.opts.target, err, bf, sizeof(bf));
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
2479
2480
  		fprintf(trace.output, "%s", bf);
  		goto out_close;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2481
  	}
602ad878d   Arnaldo Carvalho de Melo   perf target: Shor...
2482
  	if (!argc && target__none(&trace.opts.target))
ee76120e2   Namhyung Kim   perf trace: Expli...
2483
  		trace.opts.target.system_wide = true;
6810fc915   David Ahern   perf trace: Add o...
2484
2485
2486
2487
  	if (input_name)
  		err = trace__replay(&trace);
  	else
  		err = trace__run(&trace, argc, argv);
1302d88e6   Arnaldo Carvalho de Melo   perf trace: Use s...
2488

c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
2489
2490
2491
2492
  out_close:
  	if (output_name != NULL)
  		fclose(trace.output);
  out:
1302d88e6   Arnaldo Carvalho de Melo   perf trace: Use s...
2493
  	return err;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2494
  }