Blame view

tools/perf/builtin-trace.c 63.6 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
6e7eeb511   Arnaldo Carvalho de Melo   perf trace: Allow...
385
  static size_t syscall_arg__scnprintf_madvise_behavior(char *bf, size_t size,
01533e972   Arnaldo Carvalho de Melo   perf trace: Put s...
386
  						      struct syscall_arg *arg)
9e9716d1b   Arnaldo Carvalho de Melo   perf trace: Add b...
387
  {
01533e972   Arnaldo Carvalho de Melo   perf trace: Put s...
388
  	int behavior = arg->val;
9e9716d1b   Arnaldo Carvalho de Melo   perf trace: Add b...
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
  
  	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...
406
  #ifdef MADV_HUGEPAGE
9e9716d1b   Arnaldo Carvalho de Melo   perf trace: Add b...
407
  	P_MADV_BHV(HUGEPAGE);
f2935f3e5   David Ahern   perf trace: Handl...
408
409
  #endif
  #ifdef MADV_NOHUGEPAGE
9e9716d1b   Arnaldo Carvalho de Melo   perf trace: Add b...
410
  	P_MADV_BHV(NOHUGEPAGE);
f2935f3e5   David Ahern   perf trace: Handl...
411
  #endif
9e9716d1b   Arnaldo Carvalho de Melo   perf trace: Add b...
412
413
414
415
416
417
418
419
420
421
422
423
424
425
  #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...
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
  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...
456
  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...
457
458
459
460
461
462
463
464
465
  {
  	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...
466
  	int op = arg->val;
f9da0b0c7   Arnaldo Carvalho de Melo   perf trace: Add b...
467
468
469
470
471
  	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...
472
473
474
475
476
477
  	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...
478
  	P_FUTEX_OP(WAKE_OP);							  break;
01533e972   Arnaldo Carvalho de Melo   perf trace: Put s...
479
480
481
482
483
  	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...
484
485
486
487
488
489
490
491
492
493
494
495
  	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...
496
  #define SCA_FUTEX_OP  syscall_arg__scnprintf_futex_op
03e3adc9f   Arnaldo Carvalho de Melo   perf trace: Allow...
497
498
  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...
499

1f115cb72   Arnaldo Carvalho de Melo   perf trace: Allow...
500
501
  static const char *itimers[] = { "REAL", "VIRTUAL", "PROF", };
  static DEFINE_STRARRAY(itimers);
efe6b882c   Arnaldo Carvalho de Melo   perf trace: Use s...
502
503
504
505
506
507
508
509
510
  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...
511

80f587d5f   Arnaldo Carvalho de Melo   perf trace: Beaut...
512
513
514
515
516
517
518
  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...
519
520
521
522
523
524
  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...
525
526
  static const char *sighow[] = { "BLOCK", "UNBLOCK", "SETMASK", };
  static DEFINE_STRARRAY(sighow);
4f8c1b74c   David Ahern   perf trace: Add b...
527
528
529
530
531
  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...
532
533
534
535
536
537
538
539
540
  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...
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
  #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...
587
588
589
  #ifndef MSG_PROBE
  #define MSG_PROBE	     0x10
  #endif
b6e8f8f46   David Ahern   perf trace: Handl...
590
591
592
  #ifndef MSG_WAITFORONE
  #define MSG_WAITFORONE	0x10000
  #endif
b2cc99fda   Arnaldo Carvalho de Melo   perf trace: Beaut...
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
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
  #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...
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
  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...
669
  static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
01533e972   Arnaldo Carvalho de Melo   perf trace: Put s...
670
  					       struct syscall_arg *arg)
be65a89a0   Arnaldo Carvalho de Melo   perf trace: Add b...
671
  {
01533e972   Arnaldo Carvalho de Melo   perf trace: Put s...
672
  	int printed = 0, flags = arg->val;
be65a89a0   Arnaldo Carvalho de Melo   perf trace: Add b...
673
674
  
  	if (!(flags & O_CREAT))
01533e972   Arnaldo Carvalho de Melo   perf trace: Put s...
675
  		arg->mask |= 1 << (arg->idx + 1); /* Mask the mode parm */
be65a89a0   Arnaldo Carvalho de Melo   perf trace: Add b...
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
  
  	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...
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
  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...
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
  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...
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
  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...
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
  	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...
807
808
809
810
811
812
813
814
815
  #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...
816
817
818
819
820
821
822
  	default: break;
  	}
  
  	return scnprintf(bf, size, "%#x", sig);
  }
  
  #define SCA_SIGNUM syscall_arg__scnprintf_signum
844ae5b46   Arnaldo Carvalho de Melo   perf trace: Fix i...
823
824
825
826
  #if defined(__i386__) || defined(__x86_64__)
  /*
   * FIXME: Make this available to all arches.
   */
78645cf3e   Arnaldo Carvalho de Melo   perf trace: Initi...
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
  #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...
848
  #endif /* defined(__i386__) || defined(__x86_64__) */
78645cf3e   Arnaldo Carvalho de Melo   perf trace: Initi...
849

453350dd0   Arnaldo Carvalho de Melo   perf trace: Add h...
850
851
852
  #define STRARRAY(arg, name, array) \
  	  .arg_scnprintf = { [arg] = SCA_STRARRAY, }, \
  	  .arg_parm	 = { [arg] = &strarray__##array, }
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
853
854
  static struct syscall_fmt {
  	const char *name;
aec1930b0   Arnaldo Carvalho de Melo   perf trace: Add a...
855
  	const char *alias;
01533e972   Arnaldo Carvalho de Melo   perf trace: Put s...
856
  	size_t	   (*arg_scnprintf[6])(char *bf, size_t size, struct syscall_arg *arg);
1f115cb72   Arnaldo Carvalho de Melo   perf trace: Allow...
857
  	void	   *arg_parm[6];
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
858
859
  	bool	   errmsg;
  	bool	   timeout;
04b34729e   Arnaldo Carvalho de Melo   perf trace: Allow...
860
  	bool	   hexret;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
861
  } syscall_fmts[] = {
511089994   Arnaldo Carvalho de Melo   perf trace: Beaut...
862
863
  	{ .name	    = "access",	    .errmsg = true,
  	  .arg_scnprintf = { [1] = SCA_ACCMODE, /* mode */ }, },
aec1930b0   Arnaldo Carvalho de Melo   perf trace: Add a...
864
  	{ .name	    = "arch_prctl", .errmsg = true, .alias = "prctl", },
beccb2b54   Arnaldo Carvalho de Melo   perf trace: Allow...
865
866
  	{ .name	    = "brk",	    .hexret = true,
  	  .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, },
4f8c1b74c   David Ahern   perf trace: Add b...
867
  	{ .name     = "clock_gettime",  .errmsg = true, STRARRAY(0, clk_id, clockid), },
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
868
869
  	{ .name	    = "close",	    .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_CLOSE_FD, /* fd */ }, }, 
a14bb860a   Arnaldo Carvalho de Melo   perf trace: Beaut...
870
  	{ .name	    = "connect",    .errmsg = true, },
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
871
872
873
874
875
876
  	{ .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...
877
  	{ .name	    = "epoll_ctl",  .errmsg = true, STRARRAY(1, op, epoll_ctl_ops), },
49af9e93a   Arnaldo Carvalho de Melo   perf trace: Beaut...
878
879
  	{ .name	    = "eventfd2",   .errmsg = true,
  	  .arg_scnprintf = { [1] = SCA_EFD_FLAGS, /* flags */ }, },
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
  	{ .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...
902
  	{ .name	    = "flock",	    .errmsg = true,
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
903
904
905
906
907
908
909
910
911
912
913
914
915
916
  	  .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...
917
918
  	{ .name	    = "futex",	    .errmsg = true,
  	  .arg_scnprintf = { [1] = SCA_FUTEX_OP, /* op */ }, },
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
919
920
921
922
923
924
  	{ .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...
925
926
  	{ .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...
927
  	{ .name	    = "ioctl",	    .errmsg = true,
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
928
  	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ 
844ae5b46   Arnaldo Carvalho de Melo   perf trace: Fix i...
929
930
931
932
  #if defined(__i386__) || defined(__x86_64__)
  /*
   * FIXME: Make this available to all arches.
   */
78645cf3e   Arnaldo Carvalho de Melo   perf trace: Initi...
933
934
935
  			     [1] = SCA_STRHEXARRAY, /* cmd */
  			     [2] = SCA_HEX, /* arg */ },
  	  .arg_parm	 = { [1] = &strarray__tioctls, /* cmd */ }, },
844ae5b46   Arnaldo Carvalho de Melo   perf trace: Fix i...
936
937
938
  #else
  			     [2] = SCA_HEX, /* arg */ }, },
  #endif
8bad5b0ab   Arnaldo Carvalho de Melo   perf trace: Beaut...
939
940
  	{ .name	    = "kill",	    .errmsg = true,
  	  .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
941
942
943
944
945
946
  	{ .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...
947
  	{ .name	    = "lstat",	    .errmsg = true, .alias = "newlstat", },
9e9716d1b   Arnaldo Carvalho de Melo   perf trace: Add b...
948
949
950
  	{ .name     = "madvise",    .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_HEX,	 /* start */
  			     [2] = SCA_MADV_BHV, /* behavior */ }, },
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
951
952
953
954
  	{ .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...
955
956
957
958
  	{ .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...
959
  	{ .name	    = "mmap",	    .hexret = true,
ae685380b   Arnaldo Carvalho de Melo   perf trace: Add b...
960
  	  .arg_scnprintf = { [0] = SCA_HEX,	  /* addr */
941557e0e   Arnaldo Carvalho de Melo   perf trace: Add b...
961
  			     [2] = SCA_MMAP_PROT, /* prot */
73faab3a4   Namhyung Kim   perf trace: Beaut...
962
963
  			     [3] = SCA_MMAP_FLAGS, /* flags */
  			     [4] = SCA_FD, 	  /* fd */ }, },
beccb2b54   Arnaldo Carvalho de Melo   perf trace: Allow...
964
  	{ .name	    = "mprotect",   .errmsg = true,
ae685380b   Arnaldo Carvalho de Melo   perf trace: Add b...
965
966
967
968
969
  	  .arg_scnprintf = { [0] = SCA_HEX, /* start */
  			     [2] = SCA_MMAP_PROT, /* prot */ }, },
  	{ .name	    = "mremap",	    .hexret = true,
  	  .arg_scnprintf = { [0] = SCA_HEX, /* addr */
  			     [4] = SCA_HEX, /* new_addr */ }, },
3d903aa74   Arnaldo Carvalho de Melo   perf trace: Beaut...
970
971
  	{ .name	    = "munlock",    .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
beccb2b54   Arnaldo Carvalho de Melo   perf trace: Allow...
972
973
  	{ .name	    = "munmap",	    .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
974
975
976
977
  	{ .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...
978
979
  	{ .name	    = "open",	    .errmsg = true,
  	  .arg_scnprintf = { [1] = SCA_OPEN_FLAGS, /* flags */ }, },
31cd3855c   Arnaldo Carvalho de Melo   perf trace: Tell ...
980
  	{ .name	    = "open_by_handle_at", .errmsg = true,
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
981
982
  	  .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
  			     [2] = SCA_OPEN_FLAGS, /* flags */ }, },
31cd3855c   Arnaldo Carvalho de Melo   perf trace: Tell ...
983
  	{ .name	    = "openat",	    .errmsg = true,
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
984
985
  	  .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
  			     [2] = SCA_OPEN_FLAGS, /* flags */ }, },
46cce19ba   Arnaldo Carvalho de Melo   perf trace: Beaut...
986
987
  	{ .name	    = "pipe2",	    .errmsg = true,
  	  .arg_scnprintf = { [1] = SCA_PIPE_FLAGS, /* flags */ }, },
aec1930b0   Arnaldo Carvalho de Melo   perf trace: Add a...
988
989
  	{ .name	    = "poll",	    .errmsg = true, .timeout = true, },
  	{ .name	    = "ppoll",	    .errmsg = true, .timeout = true, },
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
990
991
992
993
  	{ .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...
994
  	{ .name	    = "prlimit64",  .errmsg = true, STRARRAY(1, resource, rlimit_resources), },
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
995
996
997
998
999
1000
1001
1002
1003
1004
  	{ .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...
1005
1006
1007
1008
1009
1010
  	{ .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 ...
1011
1012
  	{ .name	    = "renameat",   .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, 
8bad5b0ab   Arnaldo Carvalho de Melo   perf trace: Beaut...
1013
1014
  	{ .name	    = "rt_sigaction", .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_SIGNUM, /* sig */ }, },
453350dd0   Arnaldo Carvalho de Melo   perf trace: Add h...
1015
  	{ .name	    = "rt_sigprocmask",  .errmsg = true, STRARRAY(0, how, sighow), },
8bad5b0ab   Arnaldo Carvalho de Melo   perf trace: Beaut...
1016
1017
1018
1019
  	{ .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...
1020
  	{ .name	    = "select",	    .errmsg = true, .timeout = true, },
b2cc99fda   Arnaldo Carvalho de Melo   perf trace: Beaut...
1021
1022
1023
1024
1025
1026
  	{ .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...
1027
1028
  	{ .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 ...
1029
1030
  	{ .name	    = "shutdown",   .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
e10bce815   Arnaldo Carvalho de Melo   perf trace: Beaut...
1031
  	{ .name	    = "socket",	    .errmsg = true,
a28b24b27   Arnaldo Carvalho de Melo   perf trace: Beaut...
1032
1033
  	  .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
  			     [1] = SCA_SK_TYPE, /* type */ },
07120aa5d   Arnaldo Carvalho de Melo   perf trace: Use s...
1034
1035
1036
1037
  	  .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...
1038
  	  .arg_parm	 = { [0] = &strarray__socket_families, /* family */ }, },
aec1930b0   Arnaldo Carvalho de Melo   perf trace: Add a...
1039
  	{ .name	    = "stat",	    .errmsg = true, .alias = "newstat", },
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
1040
1041
  	{ .name	    = "symlinkat",  .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, 
8bad5b0ab   Arnaldo Carvalho de Melo   perf trace: Beaut...
1042
1043
1044
1045
  	{ .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...
1046
  	{ .name	    = "uname",	    .errmsg = true, .alias = "newuname", },
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
1047
1048
1049
1050
1051
1052
1053
1054
  	{ .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
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
  };
  
  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...
1072
  	bool		    filtered;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1073
  	struct syscall_fmt  *fmt;
01533e972   Arnaldo Carvalho de Melo   perf trace: Put s...
1074
  	size_t		    (**arg_scnprintf)(char *bf, size_t size, struct syscall_arg *arg);
1f115cb72   Arnaldo Carvalho de Melo   perf trace: Allow...
1075
  	void		    **arg_parm;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1076
  };
60c907abc   Arnaldo Carvalho de Melo   perf trace: Add a...
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
  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...
1088
  	return printed + fprintf(fp, "): ");
60c907abc   Arnaldo Carvalho de Melo   perf trace: Add a...
1089
  }
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1090
1091
1092
1093
  struct thread_trace {
  	u64		  entry_time;
  	u64		  exit_time;
  	bool		  entry_pending;
efd5745e4   Arnaldo Carvalho de Melo   perf trace: Count...
1094
  	unsigned long	  nr_events;
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1095
  	char		  *entry_str;
1302d88e6   Arnaldo Carvalho de Melo   perf trace: Use s...
1096
  	double		  runtime_ms;
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
1097
1098
1099
1100
  	struct {
  		int	  max;
  		char	  **table;
  	} paths;
bf2575c12   David Ahern   perf trace: Add s...
1101
1102
  
  	struct intlist *syscall_stats;
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1103
1104
1105
1106
  };
  
  static struct thread_trace *thread_trace__new(void)
  {
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
1107
1108
1109
1110
  	struct thread_trace *ttrace =  zalloc(sizeof(struct thread_trace));
  
  	if (ttrace)
  		ttrace->paths.max = -1;
bf2575c12   David Ahern   perf trace: Add s...
1111
  	ttrace->syscall_stats = intlist__new(NULL);
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
1112
  	return ttrace;
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1113
  }
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1114
  static struct thread_trace *thread__trace(struct thread *thread, FILE *fp)
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1115
  {
efd5745e4   Arnaldo Carvalho de Melo   perf trace: Count...
1116
  	struct thread_trace *ttrace;
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1117
1118
1119
1120
1121
  	if (thread == NULL)
  		goto fail;
  
  	if (thread->priv == NULL)
  		thread->priv = thread_trace__new();
efd5745e4   Arnaldo Carvalho de Melo   perf trace: Count...
1122
  		
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1123
1124
  	if (thread->priv == NULL)
  		goto fail;
efd5745e4   Arnaldo Carvalho de Melo   perf trace: Count...
1125
1126
1127
1128
  	ttrace = thread->priv;
  	++ttrace->nr_events;
  
  	return ttrace;
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1129
  fail:
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1130
  	color_fprintf(fp, PERF_COLOR_RED,
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1131
1132
1133
1134
  		      "WARNING: not enough memory, dropping samples!
  ");
  	return NULL;
  }
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1135
  struct trace {
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1136
  	struct perf_tool	tool;
c522739d7   Arnaldo Carvalho de Melo   perf trace: Use v...
1137
1138
1139
1140
  	struct {
  		int		machine;
  		int		open_id;
  	}			audit;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1141
1142
1143
1144
  	struct {
  		int		max;
  		struct syscall  *table;
  	} syscalls;
b40067964   Arnaldo Carvalho de Melo   perf tools: Renam...
1145
  	struct record_opts	opts;
8fb598e5a   David Ahern   perf trace: Fix c...
1146
  	struct machine		*host;
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1147
  	u64			base_time;
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1148
  	FILE			*output;
efd5745e4   Arnaldo Carvalho de Melo   perf trace: Count...
1149
  	unsigned long		nr_events;
b059efdf5   Arnaldo Carvalho de Melo   perf trace: Suppo...
1150
  	struct strlist		*ev_qualifier;
c522739d7   Arnaldo Carvalho de Melo   perf trace: Use v...
1151
  	const char 		*last_vfs_getname;
bdc896617   David Ahern   perf trace: Honor...
1152
1153
  	struct intlist		*tid_list;
  	struct intlist		*pid_list;
98eafce6b   Arnaldo Carvalho de Melo   perf trace: Pack ...
1154
1155
1156
1157
1158
1159
1160
1161
1162
  	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...
1163
  	bool			sched;
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1164
  	bool			multiple_threads;
bf2575c12   David Ahern   perf trace: Add s...
1165
  	bool			summary;
fd2eabaf1   David Ahern   perf trace: Add s...
1166
  	bool			summary_only;
50c95cbd7   Arnaldo Carvalho de Melo   perf trace: Add o...
1167
  	bool			show_comm;
c522739d7   Arnaldo Carvalho de Melo   perf trace: Use v...
1168
  	bool			show_tool_stats;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1169
  };
97119f37b   Arnaldo Carvalho de Melo   perf trace: Split...
1170
  static int trace__set_fd_pathname(struct thread *thread, int fd, const char *pathname)
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
1171
1172
  {
  	struct thread_trace *ttrace = thread->priv;
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
  
  	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...
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
  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...
1220
1221
  static const char *thread__fd_path(struct thread *thread, int fd,
  				   struct trace *trace)
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
1222
1223
1224
1225
1226
1227
1228
1229
  {
  	struct thread_trace *ttrace = thread->priv;
  
  	if (ttrace == NULL)
  		return NULL;
  
  	if (fd < 0)
  		return NULL;
c522739d7   Arnaldo Carvalho de Melo   perf trace: Use v...
1230
1231
1232
1233
1234
1235
1236
  	if ((fd > ttrace->paths.max || ttrace->paths.table[fd] == NULL))
  		if (!trace->live)
  			return NULL;
  		++trace->stats.proc_getname;
  		if (thread__read_fd_path(thread, fd)) {
  			return NULL;
  	}
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
1237
1238
1239
1240
1241
1242
1243
1244
1245
  
  	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...
1246
  	const char *path = thread__fd_path(arg->thread, fd, arg->trace);
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
  
  	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);
  	struct thread_trace *ttrace = arg->thread->priv;
046625231   Arnaldo Carvalho de Melo   perf tools: Intro...
1260
1261
  	if (ttrace && fd >= 0 && fd <= ttrace->paths.max)
  		zfree(&ttrace->paths.table[fd]);
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
1262
1263
1264
  
  	return printed;
  }
ae9ed0357   Arnaldo Carvalho de Melo   perf trace: Add d...
1265
1266
1267
1268
  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...
1269
1270
1271
  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...
1272
  	return fprintf(fp, "%10.3f ", ts);
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1273
  }
f15eb531d   Namhyung Kim   perf trace: Add s...
1274
  static bool done = false;
ba209f856   Arnaldo Carvalho de Melo   perf trace: Impro...
1275
  static bool interrupted = false;
f15eb531d   Namhyung Kim   perf trace: Add s...
1276

ba209f856   Arnaldo Carvalho de Melo   perf trace: Impro...
1277
  static void sig_handler(int sig)
f15eb531d   Namhyung Kim   perf trace: Add s...
1278
1279
  {
  	done = true;
ba209f856   Arnaldo Carvalho de Melo   perf trace: Impro...
1280
  	interrupted = sig == SIGINT;
f15eb531d   Namhyung Kim   perf trace: Add s...
1281
  }
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1282
  static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thread,
60c907abc   Arnaldo Carvalho de Melo   perf trace: Add a...
1283
  					u64 duration, u64 tstamp, FILE *fp)
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1284
1285
  {
  	size_t printed = trace__fprintf_tstamp(trace, tstamp, fp);
60c907abc   Arnaldo Carvalho de Melo   perf trace: Add a...
1286
  	printed += fprintf_duration(duration, fp);
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1287

50c95cbd7   Arnaldo Carvalho de Melo   perf trace: Add o...
1288
1289
  	if (trace->multiple_threads) {
  		if (trace->show_comm)
1902efe7f   Frederic Weisbecker   perf tools: Add n...
1290
  			printed += fprintf(fp, "%.14s/", thread__comm_str(thread));
380512345   Adrian Hunter   perf tools: struc...
1291
  		printed += fprintf(fp, "%d ", thread->tid);
50c95cbd7   Arnaldo Carvalho de Melo   perf trace: Add o...
1292
  	}
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1293
1294
1295
  
  	return printed;
  }
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1296
  static int trace__process_event(struct trace *trace, struct machine *machine,
162f0befd   Frederic Weisbecker   perf tools: Add t...
1297
  				union perf_event *event, struct perf_sample *sample)
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1298
1299
1300
1301
1302
  {
  	int ret = 0;
  
  	switch (event->header.type) {
  	case PERF_RECORD_LOST:
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1303
  		color_fprintf(trace->output, PERF_COLOR_RED,
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1304
1305
  			      "LOST %" PRIu64 " events!
  ", event->lost.lost);
162f0befd   Frederic Weisbecker   perf tools: Add t...
1306
  		ret = machine__process_lost_event(machine, event, sample);
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1307
  	default:
162f0befd   Frederic Weisbecker   perf tools: Add t...
1308
  		ret = machine__process_event(machine, event, sample);
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1309
1310
1311
1312
1313
  		break;
  	}
  
  	return ret;
  }
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1314
  static int trace__tool_process(struct perf_tool *tool,
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1315
  			       union perf_event *event,
162f0befd   Frederic Weisbecker   perf tools: Add t...
1316
  			       struct perf_sample *sample,
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1317
1318
  			       struct machine *machine)
  {
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1319
  	struct trace *trace = container_of(tool, struct trace, tool);
162f0befd   Frederic Weisbecker   perf tools: Add t...
1320
  	return trace__process_event(trace, machine, event, sample);
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1321
1322
1323
1324
1325
1326
1327
1328
  }
  
  static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
  {
  	int err = symbol__init();
  
  	if (err)
  		return err;
8fb598e5a   David Ahern   perf trace: Fix c...
1329
1330
1331
  	trace->host = machine__new_host();
  	if (trace->host == NULL)
  		return -ENOMEM;
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1332

a33fbd56e   Arnaldo Carvalho de Melo   perf machine: Sim...
1333
1334
  	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...
1335
1336
1337
1338
1339
  	if (err)
  		symbol__exit();
  
  	return err;
  }
13d4ff3eb   Arnaldo Carvalho de Melo   perf trace: Intro...
1340
1341
1342
1343
1344
1345
1346
1347
  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...
1348
1349
  	if (sc->fmt)
  		sc->arg_parm = sc->fmt->arg_parm;
13d4ff3eb   Arnaldo Carvalho de Melo   perf trace: Intro...
1350
  	for (field = sc->tp_format->format.fields->next; field; field = field->next) {
beccb2b54   Arnaldo Carvalho de Melo   perf trace: Allow...
1351
1352
1353
  		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...
1354
1355
1356
1357
1358
1359
  			sc->arg_scnprintf[idx] = syscall_arg__scnprintf_hex;
  		++idx;
  	}
  
  	return 0;
  }
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1360
1361
1362
1363
  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...
1364
  	const char *name = audit_syscall_to_name(id, trace->audit.machine);
3a531260a   Arnaldo Carvalho de Melo   perf trace: Valid...
1365
1366
1367
  
  	if (name == NULL)
  		return -1;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
  
  	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...
1387
  	sc->name = name;
2ae3a312c   Arnaldo Carvalho de Melo   perf trace: Allow...
1388

b059efdf5   Arnaldo Carvalho de Melo   perf trace: Suppo...
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
  	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...
1400
  	}
3a531260a   Arnaldo Carvalho de Melo   perf trace: Valid...
1401
  	sc->fmt  = syscall_fmt__find(sc->name);
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1402

aec1930b0   Arnaldo Carvalho de Melo   perf trace: Add a...
1403
  	snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name);
97978b3e3   Jiri Olsa   perf tools: Add t...
1404
  	sc->tp_format = trace_event__tp_format("syscalls", tp_name);
aec1930b0   Arnaldo Carvalho de Melo   perf trace: Add a...
1405
1406
1407
  
  	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...
1408
  		sc->tp_format = trace_event__tp_format("syscalls", tp_name);
aec1930b0   Arnaldo Carvalho de Melo   perf trace: Add a...
1409
  	}
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1410

13d4ff3eb   Arnaldo Carvalho de Melo   perf trace: Intro...
1411
1412
1413
1414
  	if (sc->tp_format == NULL)
  		return -1;
  
  	return syscall__set_arg_fmts(sc);
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1415
  }
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1416
  static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
1417
1418
  				      unsigned long *args, struct trace *trace,
  				      struct thread *thread)
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1419
  {
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1420
1421
1422
1423
  	size_t printed = 0;
  
  	if (sc->tp_format != NULL) {
  		struct format_field *field;
01533e972   Arnaldo Carvalho de Melo   perf trace: Put s...
1424
1425
  		u8 bit = 1;
  		struct syscall_arg arg = {
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
1426
1427
1428
1429
  			.idx	= 0,
  			.mask	= 0,
  			.trace  = trace,
  			.thread = thread,
01533e972   Arnaldo Carvalho de Melo   perf trace: Put s...
1430
  		};
6e7eeb511   Arnaldo Carvalho de Melo   perf trace: Allow...
1431
1432
  
  		for (field = sc->tp_format->format.fields->next; field;
01533e972   Arnaldo Carvalho de Melo   perf trace: Put s...
1433
1434
  		     field = field->next, ++arg.idx, bit <<= 1) {
  			if (arg.mask & bit)
6e7eeb511   Arnaldo Carvalho de Melo   perf trace: Allow...
1435
  				continue;
4aa582322   Arnaldo Carvalho de Melo   perf trace: Don't...
1436
1437
1438
1439
1440
1441
1442
1443
1444
  			/*
   			 * 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...
1445
  				continue;
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1446
  			printed += scnprintf(bf + printed, size - printed,
13d4ff3eb   Arnaldo Carvalho de Melo   perf trace: Intro...
1447
  					     "%s%s: ", printed ? ", " : "", field->name);
01533e972   Arnaldo Carvalho de Melo   perf trace: Put s...
1448
1449
  			if (sc->arg_scnprintf && sc->arg_scnprintf[arg.idx]) {
  				arg.val = args[arg.idx];
1f115cb72   Arnaldo Carvalho de Melo   perf trace: Allow...
1450
1451
  				if (sc->arg_parm)
  					arg.parm = sc->arg_parm[arg.idx];
01533e972   Arnaldo Carvalho de Melo   perf trace: Put s...
1452
1453
  				printed += sc->arg_scnprintf[arg.idx](bf + printed,
  								      size - printed, &arg);
6e7eeb511   Arnaldo Carvalho de Melo   perf trace: Allow...
1454
  			} else {
13d4ff3eb   Arnaldo Carvalho de Melo   perf trace: Intro...
1455
  				printed += scnprintf(bf + printed, size - printed,
01533e972   Arnaldo Carvalho de Melo   perf trace: Put s...
1456
  						     "%ld", args[arg.idx]);
6e7eeb511   Arnaldo Carvalho de Melo   perf trace: Allow...
1457
  			}
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1458
1459
  		}
  	} else {
01533e972   Arnaldo Carvalho de Melo   perf trace: Put s...
1460
  		int i = 0;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1461
  		while (i < 6) {
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1462
1463
1464
  			printed += scnprintf(bf + printed, size - printed,
  					     "%sarg%d: %ld",
  					     printed ? ", " : "", i, args[i]);
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1465
1466
1467
1468
1469
1470
  			++i;
  		}
  	}
  
  	return printed;
  }
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1471
1472
1473
1474
  typedef int (*tracepoint_handler)(struct trace *trace, struct perf_evsel *evsel,
  				  struct perf_sample *sample);
  
  static struct syscall *trace__syscall_info(struct trace *trace,
bf2575c12   David Ahern   perf trace: Add s...
1475
  					   struct perf_evsel *evsel, int id)
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1476
  {
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1477
1478
  
  	if (id < 0) {
adaa18bf5   Arnaldo Carvalho de Melo   perf trace: Hide ...
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
  
  		/*
  		 * 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...
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
  		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 -...
1509
1510
1511
1512
1513
1514
1515
  	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...
1516
1517
  	return NULL;
  }
bf2575c12   David Ahern   perf trace: Add s...
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
  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...
1543
1544
1545
  static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
  			    struct perf_sample *sample)
  {
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1546
  	char *msg;
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1547
  	void *args;
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1548
  	size_t printed = 0;
2ae3a312c   Arnaldo Carvalho de Melo   perf trace: Allow...
1549
  	struct thread *thread;
77170988f   Arnaldo Carvalho de Melo   perf trace: Don't...
1550
  	int id = perf_evsel__sc_tp_uint(evsel, id, sample);
bf2575c12   David Ahern   perf trace: Add s...
1551
  	struct syscall *sc = trace__syscall_info(trace, evsel, id);
2ae3a312c   Arnaldo Carvalho de Melo   perf trace: Allow...
1552
1553
1554
1555
  	struct thread_trace *ttrace;
  
  	if (sc == NULL)
  		return -1;
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1556

2ae3a312c   Arnaldo Carvalho de Melo   perf trace: Allow...
1557
1558
  	if (sc->filtered)
  		return 0;
8fb598e5a   David Ahern   perf trace: Fix c...
1559
  	thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1560
  	ttrace = thread__trace(thread, trace->output);
2ae3a312c   Arnaldo Carvalho de Melo   perf trace: Allow...
1561
  	if (ttrace == NULL)
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1562
  		return -1;
77170988f   Arnaldo Carvalho de Melo   perf trace: Don't...
1563
  	args = perf_evsel__sc_tp_ptr(evsel, args, sample);
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
  	ttrace = thread->priv;
  
  	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 ...
1575
1576
  	printed += syscall__scnprintf_args(sc, msg + printed, 1024 - printed,
  					   args, trace, thread);
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1577
1578
  
  	if (!strcmp(sc->name, "exit_group") || !strcmp(sc->name, "exit")) {
fd2eabaf1   David Ahern   perf trace: Add s...
1579
  		if (!trace->duration_filter && !trace->summary_only) {
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1580
1581
1582
  			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...
1583
  		}
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1584
1585
  	} else
  		ttrace->entry_pending = true;
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1586
1587
1588
1589
1590
1591
1592
1593
  
  	return 0;
  }
  
  static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
  			   struct perf_sample *sample)
  {
  	int ret;
60c907abc   Arnaldo Carvalho de Melo   perf trace: Add a...
1594
  	u64 duration = 0;
2ae3a312c   Arnaldo Carvalho de Melo   perf trace: Allow...
1595
  	struct thread *thread;
77170988f   Arnaldo Carvalho de Melo   perf trace: Don't...
1596
  	int id = perf_evsel__sc_tp_uint(evsel, id, sample);
bf2575c12   David Ahern   perf trace: Add s...
1597
  	struct syscall *sc = trace__syscall_info(trace, evsel, id);
2ae3a312c   Arnaldo Carvalho de Melo   perf trace: Allow...
1598
1599
1600
1601
  	struct thread_trace *ttrace;
  
  	if (sc == NULL)
  		return -1;
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1602

2ae3a312c   Arnaldo Carvalho de Melo   perf trace: Allow...
1603
1604
  	if (sc->filtered)
  		return 0;
8fb598e5a   David Ahern   perf trace: Fix c...
1605
  	thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1606
  	ttrace = thread__trace(thread, trace->output);
2ae3a312c   Arnaldo Carvalho de Melo   perf trace: Allow...
1607
  	if (ttrace == NULL)
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1608
  		return -1;
bf2575c12   David Ahern   perf trace: Add s...
1609
1610
  	if (trace->summary)
  		thread__update_stats(ttrace, id, sample);
77170988f   Arnaldo Carvalho de Melo   perf trace: Don't...
1611
  	ret = perf_evsel__sc_tp_uint(evsel, ret, sample);
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1612

c522739d7   Arnaldo Carvalho de Melo   perf trace: Use v...
1613
1614
1615
1616
1617
  	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...
1618
1619
1620
  	ttrace = thread->priv;
  
  	ttrace->exit_time = sample->time;
ae9ed0357   Arnaldo Carvalho de Melo   perf trace: Add d...
1621
  	if (ttrace->entry_time) {
60c907abc   Arnaldo Carvalho de Melo   perf trace: Add a...
1622
  		duration = sample->time - ttrace->entry_time;
ae9ed0357   Arnaldo Carvalho de Melo   perf trace: Add d...
1623
1624
1625
1626
  		if (trace__filter_duration(trace, duration))
  			goto out;
  	} else if (trace->duration_filter)
  		goto out;
60c907abc   Arnaldo Carvalho de Melo   perf trace: Add a...
1627

fd2eabaf1   David Ahern   perf trace: Add s...
1628
1629
  	if (trace->summary_only)
  		goto out;
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1630
  	trace__fprintf_entry_head(trace, thread, duration, sample->time, trace->output);
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1631
1632
  
  	if (ttrace->entry_pending) {
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1633
  		fprintf(trace->output, "%-70s", ttrace->entry_str);
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1634
  	} else {
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1635
1636
1637
  		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...
1638
  	}
da3c9a448   Arnaldo Carvalho de Melo   perf trace: Simpl...
1639
1640
1641
1642
  	if (sc->fmt == NULL) {
  signed_print:
  		fprintf(trace->output, ") = %d", ret);
  	} else if (ret < 0 && sc->fmt->errmsg) {
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1643
1644
1645
  		char bf[256];
  		const char *emsg = strerror_r(-ret, bf, sizeof(bf)),
  			   *e = audit_errno_to_name(-ret);
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1646
  		fprintf(trace->output, ") = -1 %s %s", e, emsg);
da3c9a448   Arnaldo Carvalho de Melo   perf trace: Simpl...
1647
  	} else if (ret == 0 && sc->fmt->timeout)
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1648
  		fprintf(trace->output, ") = 0 Timeout");
04b34729e   Arnaldo Carvalho de Melo   perf trace: Allow...
1649
1650
  	else if (sc->fmt->hexret)
  		fprintf(trace->output, ") = %#x", ret);
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1651
  	else
da3c9a448   Arnaldo Carvalho de Melo   perf trace: Simpl...
1652
  		goto signed_print;
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1653

c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1654
1655
  	fputc('
  ', trace->output);
ae9ed0357   Arnaldo Carvalho de Melo   perf trace: Add d...
1656
  out:
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1657
  	ttrace->entry_pending = false;
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1658
1659
  	return 0;
  }
c522739d7   Arnaldo Carvalho de Melo   perf trace: Use v...
1660
1661
1662
1663
1664
1665
  static int trace__vfs_getname(struct trace *trace, struct perf_evsel *evsel,
  			      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...
1666
1667
1668
1669
1670
  static int trace__sched_stat_runtime(struct trace *trace, struct perf_evsel *evsel,
  				     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...
1671
  	struct thread *thread = machine__findnew_thread(trace->host,
314add6b1   Adrian Hunter   perf tools: chang...
1672
1673
  							sample->pid,
  							sample->tid);
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1674
  	struct thread_trace *ttrace = thread__trace(thread, trace->output);
1302d88e6   Arnaldo Carvalho de Melo   perf trace: Use s...
1675
1676
1677
1678
1679
1680
1681
1682
1683
  
  	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...
1684
1685
  	fprintf(trace->output, "%s: comm=%s,pid=%u,runtime=%" PRIu64 ",vruntime=%" PRIu64 ")
  ",
1302d88e6   Arnaldo Carvalho de Melo   perf trace: Use s...
1686
1687
1688
1689
1690
1691
1692
  	       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;
  }
bdc896617   David Ahern   perf trace: Honor...
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
  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...
1704
1705
1706
1707
1708
1709
1710
1711
  static int trace__process_sample(struct perf_tool *tool,
  				 union perf_event *event __maybe_unused,
  				 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...
1712
  	tracepoint_handler handler = evsel->handler;
6810fc915   David Ahern   perf trace: Add o...
1713

bdc896617   David Ahern   perf trace: Honor...
1714
1715
  	if (skip_sample(trace, sample))
  		return 0;
4bb09192d   David Ahern   perf trace: Add o...
1716
  	if (!trace->full_time && trace->base_time == 0)
6810fc915   David Ahern   perf trace: Add o...
1717
  		trace->base_time = sample->time;
3160565f0   David Ahern   perf trace: Fix s...
1718
1719
  	if (handler) {
  		++trace->nr_events;
6810fc915   David Ahern   perf trace: Add o...
1720
  		handler(trace, evsel, sample);
3160565f0   David Ahern   perf trace: Fix s...
1721
  	}
6810fc915   David Ahern   perf trace: Add o...
1722
1723
1724
  
  	return err;
  }
bdc896617   David Ahern   perf trace: Honor...
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
  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;
  }
5e2485b1a   David Ahern   perf trace: Add r...
1747
1748
1749
1750
1751
1752
1753
1754
1755
  static int trace__record(int argc, const char **argv)
  {
  	unsigned int rec_argc, i, j;
  	const char **rec_argv;
  	const char * const record_args[] = {
  		"record",
  		"-R",
  		"-m", "1024",
  		"-c", "1",
9aca7f179   David Ahern   perf trace: Add s...
1756
  		"-e",
5e2485b1a   David Ahern   perf trace: Add r...
1757
  	};
9aca7f179   David Ahern   perf trace: Add s...
1758
1759
  	/* +1 is for the event string below */
  	rec_argc = ARRAY_SIZE(record_args) + 1 + argc;
5e2485b1a   David Ahern   perf trace: Add r...
1760
1761
1762
1763
1764
1765
1766
  	rec_argv = calloc(rec_argc + 1, sizeof(char *));
  
  	if (rec_argv == NULL)
  		return -ENOMEM;
  
  	for (i = 0; i < ARRAY_SIZE(record_args); i++)
  		rec_argv[i] = record_args[i];
9aca7f179   David Ahern   perf trace: Add s...
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
  	/* event string may be different for older kernels - e.g., RHEL6 */
  	if (is_valid_tracepoint("raw_syscalls:sys_enter"))
  		rec_argv[i] = "raw_syscalls:sys_enter,raw_syscalls:sys_exit";
  	else if (is_valid_tracepoint("syscalls:sys_enter"))
  		rec_argv[i] = "syscalls:sys_enter,syscalls:sys_exit";
  	else {
  		pr_err("Neither raw_syscalls nor syscalls events exist.
  ");
  		return -1;
  	}
  	i++;
5e2485b1a   David Ahern   perf trace: Add r...
1778
1779
1780
1781
1782
  	for (j = 0; j < (unsigned int)argc; j++, i++)
  		rec_argv[i] = argv[j];
  
  	return cmd_record(i, rec_argv, NULL);
  }
bf2575c12   David Ahern   perf trace: Add s...
1783
  static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp);
c522739d7   Arnaldo Carvalho de Melo   perf trace: Use v...
1784
1785
  static void perf_evlist__add_vfs_getname(struct perf_evlist *evlist)
  {
ef503831d   Arnaldo Carvalho de Melo   perf evsel: Remov...
1786
  	struct perf_evsel *evsel = perf_evsel__newtp("probe", "vfs_getname");
c522739d7   Arnaldo Carvalho de Melo   perf trace: Use v...
1787
1788
1789
1790
1791
1792
1793
  	if (evsel == NULL)
  		return;
  
  	if (perf_evsel__field(evsel, "pathname") == NULL) {
  		perf_evsel__delete(evsel);
  		return;
  	}
744a97194   Arnaldo Carvalho de Melo   perf evsel: Ditch...
1794
  	evsel->handler = trace__vfs_getname;
c522739d7   Arnaldo Carvalho de Melo   perf trace: Use v...
1795
1796
  	perf_evlist__add(evlist, evsel);
  }
f15eb531d   Namhyung Kim   perf trace: Add s...
1797
  static int trace__run(struct trace *trace, int argc, const char **argv)
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1798
  {
334fe7a3c   Namhyung Kim   perf evlist: Remo...
1799
  	struct perf_evlist *evlist = perf_evlist__new();
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1800
  	struct perf_evsel *evsel;
efd5745e4   Arnaldo Carvalho de Melo   perf trace: Count...
1801
1802
  	int err = -1, i;
  	unsigned long before;
f15eb531d   Namhyung Kim   perf trace: Add s...
1803
  	const bool forks = argc > 0;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1804

75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
1805
  	trace->live = true;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1806
  	if (evlist == NULL) {
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1807
1808
  		fprintf(trace->output, "Not enough memory to run!
  ");
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1809
1810
  		goto out;
  	}
77170988f   Arnaldo Carvalho de Melo   perf trace: Don't...
1811
  	if (perf_evlist__add_syscall_newtp(evlist, trace__sys_enter, trace__sys_exit))
87f918685   Ramkumar Ramachandra   perf trace: Impro...
1812
  		goto out_error_tp;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1813

c522739d7   Arnaldo Carvalho de Melo   perf trace: Use v...
1814
  	perf_evlist__add_vfs_getname(evlist);
1302d88e6   Arnaldo Carvalho de Melo   perf trace: Use s...
1815
  	if (trace->sched &&
87f918685   Ramkumar Ramachandra   perf trace: Impro...
1816
1817
1818
  		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...
1819

514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1820
1821
  	err = perf_evlist__create_maps(evlist, &trace->opts.target);
  	if (err < 0) {
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1822
1823
  		fprintf(trace->output, "Problems parsing the target to trace, check your options!
  ");
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1824
1825
  		goto out_delete_evlist;
  	}
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1826
1827
  	err = trace__symbols_init(trace, evlist);
  	if (err < 0) {
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1828
1829
  		fprintf(trace->output, "Problems initializing symbol libraries!
  ");
03ad9747c   Arnaldo Carvalho de Melo   perf evlist: Move...
1830
  		goto out_delete_evlist;
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1831
  	}
f77a95182   Arnaldo Carvalho de Melo   perf evlist: Set ...
1832
  	perf_evlist__config(evlist, &trace->opts);
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1833

f15eb531d   Namhyung Kim   perf trace: Add s...
1834
1835
1836
1837
  	signal(SIGCHLD, sig_handler);
  	signal(SIGINT, sig_handler);
  
  	if (forks) {
6ef73ec44   Namhyung Kim   perf evlist: Pass...
1838
  		err = perf_evlist__prepare_workload(evlist, &trace->opts.target,
735f7e0bb   Arnaldo Carvalho de Melo   perf evlist: Move...
1839
  						    argv, false, NULL);
f15eb531d   Namhyung Kim   perf trace: Add s...
1840
  		if (err < 0) {
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1841
1842
  			fprintf(trace->output, "Couldn't run the workload!
  ");
03ad9747c   Arnaldo Carvalho de Melo   perf evlist: Move...
1843
  			goto out_delete_evlist;
f15eb531d   Namhyung Kim   perf trace: Add s...
1844
1845
  		}
  	}
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1846
  	err = perf_evlist__open(evlist);
a8f23d8f8   Arnaldo Carvalho de Melo   perf trace: Impro...
1847
1848
  	if (err < 0)
  		goto out_error_open;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1849

f885037ef   Jiri Olsa   perf trace: Honou...
1850
  	err = perf_evlist__mmap(evlist, trace->opts.mmap_pages, false);
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1851
  	if (err < 0) {
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1852
1853
  		fprintf(trace->output, "Couldn't mmap the events: %s
  ", strerror(errno));
f26e1c7cb   Arnaldo Carvalho de Melo   perf evlist: Clos...
1854
  		goto out_delete_evlist;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1855
1856
1857
  	}
  
  	perf_evlist__enable(evlist);
f15eb531d   Namhyung Kim   perf trace: Add s...
1858
1859
1860
  
  	if (forks)
  		perf_evlist__start_workload(evlist);
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1861
  	trace->multiple_threads = evlist->threads->map[0] == -1 || evlist->threads->nr > 1;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1862
  again:
efd5745e4   Arnaldo Carvalho de Melo   perf trace: Count...
1863
  	before = trace->nr_events;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1864
1865
1866
1867
1868
1869
  
  	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...
1870
  			tracepoint_handler handler;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1871
  			struct perf_sample sample;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1872

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

514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1875
1876
  			err = perf_evlist__parse_sample(evlist, event, &sample);
  			if (err) {
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1877
1878
  				fprintf(trace->output, "Can't parse sample, err = %d, skipping...
  ", err);
8e50d384c   Zhouyi Zhou   perf tools: Fixup...
1879
  				goto next_event;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1880
  			}
4bb09192d   David Ahern   perf trace: Add o...
1881
  			if (!trace->full_time && trace->base_time == 0)
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1882
1883
1884
  				trace->base_time = sample.time;
  
  			if (type != PERF_RECORD_SAMPLE) {
162f0befd   Frederic Weisbecker   perf tools: Add t...
1885
  				trace__process_event(trace, trace->host, event, &sample);
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1886
1887
  				continue;
  			}
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1888
1889
  			evsel = perf_evlist__id2evsel(evlist, sample.id);
  			if (evsel == NULL) {
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1890
1891
  				fprintf(trace->output, "Unknown tp ID %" PRIu64 ", skipping...
  ", sample.id);
8e50d384c   Zhouyi Zhou   perf tools: Fixup...
1892
  				goto next_event;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1893
  			}
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1894
  			if (sample.raw_data == NULL) {
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1895
1896
  				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...
1897
1898
  				       perf_evsel__name(evsel), sample.tid,
  				       sample.cpu, sample.raw_size);
8e50d384c   Zhouyi Zhou   perf tools: Fixup...
1899
  				goto next_event;
fc551f8d4   Arnaldo Carvalho de Melo   perf trace: Check...
1900
  			}
744a97194   Arnaldo Carvalho de Melo   perf evsel: Ditch...
1901
  			handler = evsel->handler;
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1902
  			handler(trace, evsel, &sample);
8e50d384c   Zhouyi Zhou   perf tools: Fixup...
1903
1904
  next_event:
  			perf_evlist__mmap_consume(evlist, i);
20c5f10eb   Arnaldo Carvalho de Melo   perf trace: Check...
1905

ba209f856   Arnaldo Carvalho de Melo   perf trace: Impro...
1906
1907
  			if (interrupted)
  				goto out_disable;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1908
1909
  		}
  	}
efd5745e4   Arnaldo Carvalho de Melo   perf trace: Count...
1910
  	if (trace->nr_events == before) {
ba209f856   Arnaldo Carvalho de Melo   perf trace: Impro...
1911
  		int timeout = done ? 100 : -1;
f15eb531d   Namhyung Kim   perf trace: Add s...
1912

ba209f856   Arnaldo Carvalho de Melo   perf trace: Impro...
1913
1914
1915
1916
  		if (poll(evlist->pollfd, evlist->nr_fds, timeout) > 0)
  			goto again;
  	} else {
  		goto again;
f15eb531d   Namhyung Kim   perf trace: Add s...
1917
  	}
ba209f856   Arnaldo Carvalho de Melo   perf trace: Impro...
1918
1919
  out_disable:
  	perf_evlist__disable(evlist);
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1920

c522739d7   Arnaldo Carvalho de Melo   perf trace: Use v...
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
  	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...
1936

514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1937
1938
1939
  out_delete_evlist:
  	perf_evlist__delete(evlist);
  out:
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
1940
  	trace->live = false;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1941
  	return err;
6ef068cb8   Arnaldo Carvalho de Melo   perf evlist: Intr...
1942
1943
  {
  	char errbuf[BUFSIZ];
a8f23d8f8   Arnaldo Carvalho de Melo   perf trace: Impro...
1944
1945
  
  out_error_tp:
6ef068cb8   Arnaldo Carvalho de Melo   perf evlist: Intr...
1946
  	perf_evlist__strerror_tp(evlist, errno, errbuf, sizeof(errbuf));
a8f23d8f8   Arnaldo Carvalho de Melo   perf trace: Impro...
1947
1948
1949
1950
1951
1952
  	goto out_error;
  
  out_error_open:
  	perf_evlist__strerror_open(evlist, errno, errbuf, sizeof(errbuf));
  
  out_error:
6ef068cb8   Arnaldo Carvalho de Melo   perf evlist: Intr...
1953
1954
  	fprintf(trace->output, "%s
  ", errbuf);
87f918685   Ramkumar Ramachandra   perf trace: Impro...
1955
  	goto out_delete_evlist;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1956
  }
a8f23d8f8   Arnaldo Carvalho de Melo   perf trace: Impro...
1957
  }
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1958

6810fc915   David Ahern   perf trace: Add o...
1959
1960
1961
  static int trace__replay(struct trace *trace)
  {
  	const struct perf_evsel_str_handler handlers[] = {
c522739d7   Arnaldo Carvalho de Melo   perf trace: Use v...
1962
  		{ "probe:vfs_getname",	     trace__vfs_getname, },
6810fc915   David Ahern   perf trace: Add o...
1963
  	};
f5fc14124   Jiri Olsa   perf tools: Add d...
1964
1965
1966
1967
  	struct perf_data_file file = {
  		.path  = input_name,
  		.mode  = PERF_DATA_MODE_READ,
  	};
6810fc915   David Ahern   perf trace: Add o...
1968
  	struct perf_session *session;
003824e8c   Namhyung Kim   perf trace: Fix s...
1969
  	struct perf_evsel *evsel;
6810fc915   David Ahern   perf trace: Add o...
1970
1971
1972
1973
  	int err = -1;
  
  	trace->tool.sample	  = trace__process_sample;
  	trace->tool.mmap	  = perf_event__process_mmap;
384c671e3   David Ahern   perf trace: Add m...
1974
  	trace->tool.mmap2	  = perf_event__process_mmap2;
6810fc915   David Ahern   perf trace: Add o...
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
  	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;
  
  	trace->tool.ordered_samples = true;
  	trace->tool.ordering_requires_timestamps = true;
  
  	/* add tid to output */
  	trace->multiple_threads = true;
  
  	if (symbol__init() < 0)
  		return -1;
f5fc14124   Jiri Olsa   perf tools: Add d...
1990
  	session = perf_session__new(&file, false, &trace->tool);
6810fc915   David Ahern   perf trace: Add o...
1991
1992
  	if (session == NULL)
  		return -ENOMEM;
8fb598e5a   David Ahern   perf trace: Fix c...
1993
  	trace->host = &session->machines.host;
6810fc915   David Ahern   perf trace: Add o...
1994
1995
1996
  	err = perf_session__set_tracepoints_handlers(session, handlers);
  	if (err)
  		goto out;
003824e8c   Namhyung Kim   perf trace: Fix s...
1997
1998
  	evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
  						     "raw_syscalls:sys_enter");
9aca7f179   David Ahern   perf trace: Add s...
1999
2000
2001
2002
  	/* 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...
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
  	if (evsel == NULL) {
  		pr_err("Data file does not have raw_syscalls:sys_enter event
  ");
  		goto out;
  	}
  
  	if (perf_evsel__init_syscall_tp(evsel, trace__sys_enter) < 0 ||
  	    perf_evsel__init_sc_tp_ptr_field(evsel, args)) {
  		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...
2018
2019
2020
  	if (evsel == NULL)
  		evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
  							     "syscalls:sys_exit");
003824e8c   Namhyung Kim   perf trace: Fix s...
2021
2022
2023
  	if (evsel == NULL) {
  		pr_err("Data file does not have raw_syscalls:sys_exit event
  ");
6810fc915   David Ahern   perf trace: Add o...
2024
2025
  		goto out;
  	}
003824e8c   Namhyung Kim   perf trace: Fix s...
2026
2027
2028
2029
  	if (perf_evsel__init_syscall_tp(evsel, trace__sys_exit) < 0 ||
  	    perf_evsel__init_sc_tp_uint_field(evsel, ret)) {
  		pr_err("Error during initialize raw_syscalls:sys_exit event
  ");
6810fc915   David Ahern   perf trace: Add o...
2030
2031
  		goto out;
  	}
bdc896617   David Ahern   perf trace: Honor...
2032
2033
2034
  	err = parse_target_str(trace);
  	if (err != 0)
  		goto out;
6810fc915   David Ahern   perf trace: Add o...
2035
2036
2037
2038
2039
  	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...
2040
2041
  	else if (trace->summary)
  		trace__fprintf_thread_summary(trace, trace->output);
6810fc915   David Ahern   perf trace: Add o...
2042
2043
2044
2045
2046
  out:
  	perf_session__delete(session);
  
  	return err;
  }
1302d88e6   Arnaldo Carvalho de Melo   perf trace: Use s...
2047
2048
2049
  static size_t trace__fprintf_threads_header(FILE *fp)
  {
  	size_t printed;
99ff71505   Pekka Enberg   perf trace: Simpl...
2050
2051
2052
2053
  	printed  = fprintf(fp, "
   Summary of events:
  
  ");
bf2575c12   David Ahern   perf trace: Add s...
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
  
  	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...
2071
2072
2073
2074
2075
2076
  	printed += fprintf(fp, "   syscall            calls      min       avg       max      stddev
  ");
  	printed += fprintf(fp, "                               (msec)    (msec)    (msec)        (%%)
  ");
  	printed += fprintf(fp, "   --------------- -------- --------- --------- ---------     ------
  ");
99ff71505   Pekka Enberg   perf trace: Simpl...
2077

bf2575c12   David Ahern   perf trace: Add s...
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
  	/* 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...
2092
  			printed += fprintf(fp, "   %-15s", sc->name);
27a778b51   Pekka Enberg   perf trace: Tweak...
2093
  			printed += fprintf(fp, " %8" PRIu64 " %9.3f %9.3f",
7f7a4138c   Pekka Enberg   perf trace: Chang...
2094
  					   n, min, avg);
27a778b51   Pekka Enberg   perf trace: Tweak...
2095
2096
  			printed += fprintf(fp, " %9.3f %9.2f%%
  ", max, pct);
bf2575c12   David Ahern   perf trace: Add s...
2097
2098
2099
2100
2101
2102
2103
2104
  		}
  
  		inode = intlist__next(inode);
  	}
  
  	printed += fprintf(fp, "
  
  ");
1302d88e6   Arnaldo Carvalho de Melo   perf trace: Use s...
2105
2106
2107
  
  	return printed;
  }
896cbb56b   David Ahern   perf trace: Use n...
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
  /* 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;
  	struct thread_trace *ttrace = thread->priv;
896cbb56b   David Ahern   perf trace: Use n...
2122
2123
2124
2125
2126
2127
  	double ratio;
  
  	if (ttrace == NULL)
  		return 0;
  
  	ratio = (double)ttrace->nr_events / trace->nr_events * 100.0;
15e65c693   Pekka Enberg   perf trace: Remov...
2128
  	printed += fprintf(fp, " %s (%d), ", thread__comm_str(thread), thread->tid);
99ff71505   Pekka Enberg   perf trace: Simpl...
2129
  	printed += fprintf(fp, "%lu events, ", ttrace->nr_events);
15e65c693   Pekka Enberg   perf trace: Remov...
2130
  	printed += fprintf(fp, "%.1f%%", ratio);
99ff71505   Pekka Enberg   perf trace: Simpl...
2131
2132
  	printed += fprintf(fp, ", %.3f msec
  ", ttrace->runtime_ms);
bf2575c12   David Ahern   perf trace: Add s...
2133
  	printed += thread__dump_stats(ttrace, trace, fp);
896cbb56b   David Ahern   perf trace: Use n...
2134
2135
2136
2137
2138
  
  	data->printed += printed;
  
  	return 0;
  }
1302d88e6   Arnaldo Carvalho de Melo   perf trace: Use s...
2139
2140
  static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp)
  {
896cbb56b   David Ahern   perf trace: Use n...
2141
2142
2143
2144
2145
  	struct summary_data data = {
  		.fp = fp,
  		.trace = trace
  	};
  	data.printed = trace__fprintf_threads_header(fp);
1302d88e6   Arnaldo Carvalho de Melo   perf trace: Use s...
2146

896cbb56b   David Ahern   perf trace: Use n...
2147
2148
2149
  	machine__for_each_thread(trace->host, trace__fprintf_one_thread, &data);
  
  	return data.printed;
1302d88e6   Arnaldo Carvalho de Melo   perf trace: Use s...
2150
  }
ae9ed0357   Arnaldo Carvalho de Melo   perf trace: Add d...
2151
2152
2153
2154
2155
2156
2157
2158
  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...
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
  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;
  }
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2175
2176
2177
  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...
2178
2179
  		"perf trace [<options>] [<command>]",
  		"perf trace [<options>] -- <command> [<options>]",
5e2485b1a   David Ahern   perf trace: Add r...
2180
2181
  		"perf trace record [<options>] [<command>]",
  		"perf trace record [<options>] -- <command> [<options>]",
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2182
2183
2184
  		NULL
  	};
  	struct trace trace = {
c522739d7   Arnaldo Carvalho de Melo   perf trace: Use v...
2185
2186
2187
2188
  		.audit = {
  			.machine = audit_detect_machine(),
  			.open_id = audit_name_to_syscall("open", trace.audit.machine),
  		},
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
  		.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...
2199
  			.no_buffering  = true,
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2200
2201
  			.mmap_pages    = 1024,
  		},
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
2202
  		.output = stdout,
50c95cbd7   Arnaldo Carvalho de Melo   perf trace: Add o...
2203
  		.show_comm = true,
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2204
  	};
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
2205
  	const char *output_name = NULL;
2ae3a312c   Arnaldo Carvalho de Melo   perf trace: Allow...
2206
  	const char *ev_qualifier_str = NULL;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2207
  	const struct option trace_options[] = {
50c95cbd7   Arnaldo Carvalho de Melo   perf trace: Add o...
2208
2209
  	OPT_BOOLEAN(0, "comm", &trace.show_comm,
  		    "show the thread COMM next to its id"),
c522739d7   Arnaldo Carvalho de Melo   perf trace: Use v...
2210
  	OPT_BOOLEAN(0, "tool_stats", &trace.show_tool_stats, "show tool stats"),
2ae3a312c   Arnaldo Carvalho de Melo   perf trace: Allow...
2211
2212
  	OPT_STRING('e', "expr", &ev_qualifier_str, "expr",
  		    "list of events to trace"),
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
2213
  	OPT_STRING('o', "output", &output_name, "file", "output file name"),
6810fc915   David Ahern   perf trace: Add o...
2214
  	OPT_STRING('i', "input", &input_name, "file", "Analyze events in file"),
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2215
2216
  	OPT_STRING('p', "pid", &trace.opts.target.pid, "pid",
  		    "trace events on existing process id"),
ac9be8ee4   David Ahern   perf trace: Make ...
2217
  	OPT_STRING('t', "tid", &trace.opts.target.tid, "tid",
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2218
  		    "trace events on existing thread id"),
ac9be8ee4   David Ahern   perf trace: Make ...
2219
  	OPT_BOOLEAN('a', "all-cpus", &trace.opts.target.system_wide,
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2220
  		    "system-wide collection from all CPUs"),
ac9be8ee4   David Ahern   perf trace: Make ...
2221
  	OPT_STRING('C', "cpu", &trace.opts.target.cpu_list, "cpu",
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2222
  		    "list of cpus to monitor"),
6810fc915   David Ahern   perf trace: Add o...
2223
  	OPT_BOOLEAN(0, "no-inherit", &trace.opts.no_inherit,
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2224
  		    "child tasks do not inherit counters"),
994a1f78b   Jiri Olsa   perf tools: Check...
2225
2226
2227
  	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 ...
2228
  	OPT_STRING('u', "uid", &trace.opts.target.uid_str, "user",
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2229
  		   "user to profile"),
ae9ed0357   Arnaldo Carvalho de Melo   perf trace: Add d...
2230
2231
2232
  	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...
2233
  	OPT_BOOLEAN(0, "sched", &trace.sched, "show blocking scheduler events"),
7c304ee0f   Arnaldo Carvalho de Melo   perf trace: Add -...
2234
  	OPT_INCR('v', "verbose", &verbose, "be more verbose"),
4bb09192d   David Ahern   perf trace: Add o...
2235
2236
  	OPT_BOOLEAN('T', "time", &trace.full_time,
  		    "Show full timestamp, not time relative to first start"),
fd2eabaf1   David Ahern   perf trace: Add s...
2237
2238
2239
2240
  	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"),
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2241
2242
2243
  	OPT_END()
  	};
  	int err;
32caf0d1f   Namhyung Kim   perf trace: Valid...
2244
  	char bf[BUFSIZ];
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2245

5e2485b1a   David Ahern   perf trace: Add r...
2246
2247
  	if ((argc > 1) && (strcmp(argv[1], "record") == 0))
  		return trace__record(argc-2, &argv[2]);
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2248
  	argc = parse_options(argc, argv, trace_options, trace_usage, 0);
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2249

fd2eabaf1   David Ahern   perf trace: Add s...
2250
2251
2252
  	/* summary_only implies summary option, but don't overwrite summary if set */
  	if (trace.summary_only)
  		trace.summary = trace.summary_only;
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
2253
2254
2255
2256
2257
2258
2259
  	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...
2260
  	if (ev_qualifier_str != NULL) {
b059efdf5   Arnaldo Carvalho de Melo   perf trace: Suppo...
2261
2262
2263
2264
2265
2266
  		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...
2267
  		if (trace.ev_qualifier == NULL) {
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
2268
2269
2270
2271
  			fputs("Not enough memory to parse event qualifier",
  			      trace.output);
  			err = -ENOMEM;
  			goto out_close;
2ae3a312c   Arnaldo Carvalho de Melo   perf trace: Allow...
2272
2273
  		}
  	}
602ad878d   Arnaldo Carvalho de Melo   perf target: Shor...
2274
  	err = target__validate(&trace.opts.target);
32caf0d1f   Namhyung Kim   perf trace: Valid...
2275
  	if (err) {
602ad878d   Arnaldo Carvalho de Melo   perf target: Shor...
2276
  		target__strerror(&trace.opts.target, err, bf, sizeof(bf));
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
2277
2278
  		fprintf(trace.output, "%s", bf);
  		goto out_close;
32caf0d1f   Namhyung Kim   perf trace: Valid...
2279
  	}
602ad878d   Arnaldo Carvalho de Melo   perf target: Shor...
2280
  	err = target__parse_uid(&trace.opts.target);
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2281
  	if (err) {
602ad878d   Arnaldo Carvalho de Melo   perf target: Shor...
2282
  		target__strerror(&trace.opts.target, err, bf, sizeof(bf));
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
2283
2284
  		fprintf(trace.output, "%s", bf);
  		goto out_close;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2285
  	}
602ad878d   Arnaldo Carvalho de Melo   perf target: Shor...
2286
  	if (!argc && target__none(&trace.opts.target))
ee76120e2   Namhyung Kim   perf trace: Expli...
2287
  		trace.opts.target.system_wide = true;
6810fc915   David Ahern   perf trace: Add o...
2288
2289
2290
2291
  	if (input_name)
  		err = trace__replay(&trace);
  	else
  		err = trace__run(&trace, argc, argv);
1302d88e6   Arnaldo Carvalho de Melo   perf trace: Use s...
2292

c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
2293
2294
2295
2296
  out_close:
  	if (output_name != NULL)
  		fclose(trace.output);
  out:
1302d88e6   Arnaldo Carvalho de Melo   perf trace: Use s...
2297
  	return err;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2298
  }