Blame view

tools/perf/builtin-trace.c 83.2 KB
a598bb5e3   Arnaldo Carvalho de Melo   perf trace: Add h...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  /*
   * builtin-trace.c
   *
   * Builtin 'trace' command:
   *
   * Display a continuously updated trace of any workload, CPU, specific PID,
   * system wide, etc.  Default format is loosely strace like, but any other
   * event may be specified using --event.
   *
   * Copyright (C) 2012, 2013, 2014, 2015 Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
   *
   * Initially based on the 'trace' prototype by Thomas Gleixner:
   *
   * http://lwn.net/Articles/415728/ ("Announcing a new utility: 'trace'")
   *
   * Released under the GPL v2. (and only v2, not any later version)
   */
4e319027a   Robert Richter   perf tools: Use d...
18
  #include <traceevent/event-parse.h>
988bdb319   Jiri Olsa   tools lib api fs:...
19
  #include <api/fs/tracing_path.h>
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
20
  #include "builtin.h"
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
21
  #include "util/color.h"
7c304ee0f   Arnaldo Carvalho de Melo   perf trace: Add -...
22
  #include "util/debug.h"
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
23
  #include "util/evlist.h"
4b6ab94ea   Josh Poimboeuf   perf subcmd: Crea...
24
  #include <subcmd/exec-cmd.h>
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
25
  #include "util/machine.h"
6810fc915   David Ahern   perf trace: Add o...
26
  #include "util/session.h"
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
27
  #include "util/thread.h"
4b6ab94ea   Josh Poimboeuf   perf subcmd: Crea...
28
  #include <subcmd/parse-options.h>
2ae3a312c   Arnaldo Carvalho de Melo   perf trace: Allow...
29
  #include "util/strlist.h"
bdc896617   David Ahern   perf trace: Honor...
30
  #include "util/intlist.h"
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
31
  #include "util/thread_map.h"
bf2575c12   David Ahern   perf trace: Add s...
32
  #include "util/stat.h"
97978b3e3   Jiri Olsa   perf tools: Add t...
33
  #include "trace-event.h"
9aca7f179   David Ahern   perf trace: Add s...
34
  #include "util/parse-events.h"
ba5042353   Wang Nan   perf trace: Call ...
35
  #include "util/bpf-loader.h"
566a08859   Milian Wolff   perf trace: Add s...
36
  #include "callchain.h"
fd0db1026   Arnaldo Carvalho de Melo   perf trace: Move ...
37
  #include "syscalltbl.h"
96c144512   Arnaldo Carvalho de Melo   perf trace: Sort ...
38
  #include "rb_resort.h"
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
39

fd0db1026   Arnaldo Carvalho de Melo   perf trace: Move ...
40
  #include <libaudit.h> /* FIXME: Still needed for audit_errno_to_name */
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
41
  #include <stdlib.h>
8dd2a1317   Jiri Olsa   perf evsel: Propa...
42
  #include <linux/err.h>
997bba8cf   Arnaldo Carvalho de Melo   perf trace: Prett...
43
44
  #include <linux/filter.h>
  #include <linux/audit.h>
39878d492   Arnaldo Carvalho de Melo   perf trace: Prett...
45
  #include <linux/random.h>
c6d4a494a   Arnaldo Carvalho de Melo   perf trace: Add -...
46
  #include <linux/stringify.h>
bd48c63eb   Arnaldo Carvalho de Melo   tools: Introduce ...
47
  #include <linux/time64.h>
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
48

c188e7acd   Arnaldo Carvalho de Melo   perf trace: Fix t...
49
50
51
  #ifndef O_CLOEXEC
  # define O_CLOEXEC		02000000
  #endif
d1d438a3b   Arnaldo Carvalho de Melo   perf trace: Beaut...
52
53
  struct trace {
  	struct perf_tool	tool;
fd0db1026   Arnaldo Carvalho de Melo   perf trace: Move ...
54
  	struct syscalltbl	*sctbl;
d1d438a3b   Arnaldo Carvalho de Melo   perf trace: Beaut...
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
  	struct {
  		int		max;
  		struct syscall  *table;
  		struct {
  			struct perf_evsel *sys_enter,
  					  *sys_exit;
  		}		events;
  	} syscalls;
  	struct record_opts	opts;
  	struct perf_evlist	*evlist;
  	struct machine		*host;
  	struct thread		*current;
  	u64			base_time;
  	FILE			*output;
  	unsigned long		nr_events;
  	struct strlist		*ev_qualifier;
  	struct {
  		size_t		nr;
  		int		*entries;
  	}			ev_qualifier_ids;
  	struct intlist		*tid_list;
  	struct intlist		*pid_list;
  	struct {
  		size_t		nr;
  		pid_t		*entries;
  	}			filter_pids;
  	double			duration_filter;
  	double			runtime_ms;
  	struct {
  		u64		vfs_getname,
  				proc_getname;
  	} stats;
c6d4a494a   Arnaldo Carvalho de Melo   perf trace: Add -...
87
  	unsigned int		max_stack;
5cf9c84e2   Arnaldo Carvalho de Melo   perf trace: Intro...
88
  	unsigned int		min_stack;
d1d438a3b   Arnaldo Carvalho de Melo   perf trace: Beaut...
89
90
91
92
93
94
95
96
97
98
  	bool			not_ev_qualifier;
  	bool			live;
  	bool			full_time;
  	bool			sched;
  	bool			multiple_threads;
  	bool			summary;
  	bool			summary_only;
  	bool			show_comm;
  	bool			show_tool_stats;
  	bool			trace_syscalls;
44621819d   Arnaldo Carvalho de Melo   perf trace: Exclu...
99
  	bool			kernel_syscallchains;
d1d438a3b   Arnaldo Carvalho de Melo   perf trace: Beaut...
100
101
102
  	bool			force;
  	bool			vfs_getname;
  	int			trace_pgfaults;
fd0db1026   Arnaldo Carvalho de Melo   perf trace: Move ...
103
  	int			open_id;
d1d438a3b   Arnaldo Carvalho de Melo   perf trace: Beaut...
104
  };
a1c2552db   Arnaldo Carvalho de Melo   trace: Beautify p...
105

77170988f   Arnaldo Carvalho de Melo   perf trace: Don't...
106
107
108
109
110
111
112
113
114
115
116
  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) \
  { \
55d43bcaf   David Ahern   perf trace: Fix S...
117
118
119
  	u##bits value; \
  	memcpy(&value, sample->raw_data + field->offset, sizeof(value)); \
  	return value;  \
77170988f   Arnaldo Carvalho de Melo   perf trace: Don't...
120
121
122
123
124
125
126
127
128
129
  }
  
  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) \
  { \
55d43bcaf   David Ahern   perf trace: Fix S...
130
131
  	u##bits value; \
  	memcpy(&value, sample->raw_data + field->offset, sizeof(value)); \
77170988f   Arnaldo Carvalho de Melo   perf trace: Don't...
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
  	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...
218
  	zfree(&evsel->priv);
77170988f   Arnaldo Carvalho de Melo   perf trace: Don't...
219
220
  	perf_evsel__delete(evsel);
  }
96695d440   Namhyung Kim   perf trace: Separ...
221
222
223
224
225
226
227
228
229
230
231
232
233
234
  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...
235
  	zfree(&evsel->priv);
96695d440   Namhyung Kim   perf trace: Separ...
236
237
  	return -ENOENT;
  }
ef503831d   Arnaldo Carvalho de Melo   perf evsel: Remov...
238
  static struct perf_evsel *perf_evsel__syscall_newtp(const char *direction, void *handler)
77170988f   Arnaldo Carvalho de Melo   perf trace: Don't...
239
  {
ef503831d   Arnaldo Carvalho de Melo   perf evsel: Remov...
240
  	struct perf_evsel *evsel = perf_evsel__newtp("raw_syscalls", direction);
77170988f   Arnaldo Carvalho de Melo   perf trace: Don't...
241

9aca7f179   David Ahern   perf trace: Add s...
242
  	/* older kernel (e.g., RHEL6) use syscalls:{enter,exit} */
8dd2a1317   Jiri Olsa   perf evsel: Propa...
243
  	if (IS_ERR(evsel))
9aca7f179   David Ahern   perf trace: Add s...
244
  		evsel = perf_evsel__newtp("syscalls", direction);
8dd2a1317   Jiri Olsa   perf evsel: Propa...
245
246
247
248
249
  	if (IS_ERR(evsel))
  		return NULL;
  
  	if (perf_evsel__init_syscall_tp(evsel, handler))
  		goto out_delete;
77170988f   Arnaldo Carvalho de Melo   perf trace: Don't...
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
  
  	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); })
01533e972   Arnaldo Carvalho de Melo   perf trace: Put s...
265
266
  struct syscall_arg {
  	unsigned long val;
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
267
268
  	struct thread *thread;
  	struct trace  *trace;
1f115cb72   Arnaldo Carvalho de Melo   perf trace: Allow...
269
  	void	      *parm;
01533e972   Arnaldo Carvalho de Melo   perf trace: Put s...
270
271
272
  	u8	      idx;
  	u8	      mask;
  };
1f115cb72   Arnaldo Carvalho de Melo   perf trace: Allow...
273
  struct strarray {
03e3adc9f   Arnaldo Carvalho de Melo   perf trace: Allow...
274
  	int	    offset;
1f115cb72   Arnaldo Carvalho de Melo   perf trace: Allow...
275
276
277
278
279
280
281
282
  	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...
283
284
285
286
287
  #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...
288
289
290
  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...
291
  {
1f115cb72   Arnaldo Carvalho de Melo   perf trace: Allow...
292
  	struct strarray *sa = arg->parm;
03e3adc9f   Arnaldo Carvalho de Melo   perf trace: Allow...
293
  	int idx = arg->val - sa->offset;
1f115cb72   Arnaldo Carvalho de Melo   perf trace: Allow...
294
295
  
  	if (idx < 0 || idx >= sa->nr_entries)
975b7c2f4   Arnaldo Carvalho de Melo   perf trace: Prepa...
296
  		return scnprintf(bf, size, intfmt, arg->val);
1f115cb72   Arnaldo Carvalho de Melo   perf trace: Allow...
297
298
299
  
  	return scnprintf(bf, size, "%s", sa->entries[idx]);
  }
975b7c2f4   Arnaldo Carvalho de Melo   perf trace: Prepa...
300
301
302
303
304
  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...
305
  #define SCA_STRARRAY syscall_arg__scnprintf_strarray
844ae5b46   Arnaldo Carvalho de Melo   perf trace: Fix i...
306
307
308
309
310
  #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...
311
312
313
314
315
316
317
  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...
318
  #endif /* defined(__i386__) || defined(__x86_64__) */
78645cf3e   Arnaldo Carvalho de Melo   perf trace: Initi...
319

75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
320
321
322
323
  static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
  					struct syscall_arg *arg);
  
  #define SCA_FD syscall_arg__scnprintf_fd
48e1f91ad   Arnaldo Carvalho de Melo   perf trace: Add c...
324
325
326
  #ifndef AT_FDCWD
  #define AT_FDCWD	-100
  #endif
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
  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...
344
  static size_t syscall_arg__scnprintf_hex(char *bf, size_t size,
01533e972   Arnaldo Carvalho de Melo   perf trace: Put s...
345
  					 struct syscall_arg *arg)
13d4ff3eb   Arnaldo Carvalho de Melo   perf trace: Intro...
346
  {
01533e972   Arnaldo Carvalho de Melo   perf trace: Put s...
347
  	return scnprintf(bf, size, "%#lx", arg->val);
13d4ff3eb   Arnaldo Carvalho de Melo   perf trace: Intro...
348
  }
beccb2b54   Arnaldo Carvalho de Melo   perf trace: Allow...
349
  #define SCA_HEX syscall_arg__scnprintf_hex
a1c2552db   Arnaldo Carvalho de Melo   trace: Beautify p...
350
351
352
353
354
355
356
  static size_t syscall_arg__scnprintf_int(char *bf, size_t size,
  					 struct syscall_arg *arg)
  {
  	return scnprintf(bf, size, "%d", arg->val);
  }
  
  #define SCA_INT syscall_arg__scnprintf_int
729a78417   Arnaldo Carvalho de Melo   perf trace: Add c...
357
358
359
360
361
  static const char *bpf_cmd[] = {
  	"MAP_CREATE", "MAP_LOOKUP_ELEM", "MAP_UPDATE_ELEM", "MAP_DELETE_ELEM",
  	"MAP_GET_NEXT_KEY", "PROG_LOAD",
  };
  static DEFINE_STRARRAY(bpf_cmd);
03e3adc9f   Arnaldo Carvalho de Melo   perf trace: Allow...
362
363
  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...
364

1f115cb72   Arnaldo Carvalho de Melo   perf trace: Allow...
365
366
  static const char *itimers[] = { "REAL", "VIRTUAL", "PROF", };
  static DEFINE_STRARRAY(itimers);
b62bee1bd   Arnaldo Carvalho de Melo   perf trace: Beaut...
367
368
369
370
371
372
373
374
  static const char *keyctl_options[] = {
  	"GET_KEYRING_ID", "JOIN_SESSION_KEYRING", "UPDATE", "REVOKE", "CHOWN",
  	"SETPERM", "DESCRIBE", "CLEAR", "LINK", "UNLINK", "SEARCH", "READ",
  	"INSTANTIATE", "NEGATE", "SET_REQKEY_KEYRING", "SET_TIMEOUT",
  	"ASSUME_AUTHORITY", "GET_SECURITY", "SESSION_TO_PARENT", "REJECT",
  	"INSTANTIATE_IOV", "INVALIDATE", "GET_PERSISTENT",
  };
  static DEFINE_STRARRAY(keyctl_options);
efe6b882c   Arnaldo Carvalho de Melo   perf trace: Use s...
375
376
377
378
379
380
381
382
383
  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...
384

80f587d5f   Arnaldo Carvalho de Melo   perf trace: Beaut...
385
386
387
388
389
390
391
  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...
392
393
394
395
396
397
  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...
398
399
  static const char *sighow[] = { "BLOCK", "UNBLOCK", "SETMASK", };
  static DEFINE_STRARRAY(sighow);
4f8c1b74c   David Ahern   perf trace: Add b...
400
401
  static const char *clockid[] = {
  	"REALTIME", "MONOTONIC", "PROCESS_CPUTIME_ID", "THREAD_CPUTIME_ID",
28ebb87c7   Arnaldo Carvalho de Melo   perf trace: Add m...
402
403
  	"MONOTONIC_RAW", "REALTIME_COARSE", "MONOTONIC_COARSE", "BOOTTIME",
  	"REALTIME_ALARM", "BOOTTIME_ALARM", "SGI_CYCLE", "TAI"
4f8c1b74c   David Ahern   perf trace: Add b...
404
405
  };
  static DEFINE_STRARRAY(clockid);
e10bce815   Arnaldo Carvalho de Melo   perf trace: Beaut...
406
407
408
409
410
411
412
413
414
  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);
511089994   Arnaldo Carvalho de Melo   perf trace: Beaut...
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
  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
f994592d9   Arnaldo Carvalho de Melo   perf trace: Deref...
441
442
443
444
  static size_t syscall_arg__scnprintf_filename(char *bf, size_t size,
  					      struct syscall_arg *arg);
  
  #define SCA_FILENAME syscall_arg__scnprintf_filename
46cce19ba   Arnaldo Carvalho de Melo   perf trace: Beaut...
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
  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
844ae5b46   Arnaldo Carvalho de Melo   perf trace: Fix i...
467
468
469
470
  #if defined(__i386__) || defined(__x86_64__)
  /*
   * FIXME: Make this available to all arches.
   */
78645cf3e   Arnaldo Carvalho de Melo   perf trace: Initi...
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
  #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...
492
  #endif /* defined(__i386__) || defined(__x86_64__) */
78645cf3e   Arnaldo Carvalho de Melo   perf trace: Initi...
493

a355a61e4   Arnaldo Carvalho de Melo   perf trace: Add g...
494
495
496
497
498
499
  #ifndef GRND_NONBLOCK
  #define GRND_NONBLOCK	0x0001
  #endif
  #ifndef GRND_RANDOM
  #define GRND_RANDOM	0x0002
  #endif
39878d492   Arnaldo Carvalho de Melo   perf trace: Prett...
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
  static size_t syscall_arg__scnprintf_getrandom_flags(char *bf, size_t size,
  						   struct syscall_arg *arg)
  {
  	int printed = 0, flags = arg->val;
  
  #define	P_FLAG(n) \
  	if (flags & GRND_##n) { \
  		printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
  		flags &= ~GRND_##n; \
  	}
  
  	P_FLAG(RANDOM);
  	P_FLAG(NONBLOCK);
  #undef P_FLAG
  
  	if (flags)
  		printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
  
  	return printed;
  }
  
  #define SCA_GETRANDOM_FLAGS syscall_arg__scnprintf_getrandom_flags
453350dd0   Arnaldo Carvalho de Melo   perf trace: Add h...
522
523
524
  #define STRARRAY(arg, name, array) \
  	  .arg_scnprintf = { [arg] = SCA_STRARRAY, }, \
  	  .arg_parm	 = { [arg] = &strarray__##array, }
ea8dc3cef   Arnaldo Carvalho de Melo   perf trace: Move ...
525
  #include "trace/beauty/eventfd.c"
8bf382ce0   Arnaldo Carvalho de Melo   perf trace: Move ...
526
  #include "trace/beauty/flock.c"
d5d71e86d   Arnaldo Carvalho de Melo   perf trace: Move ...
527
  #include "trace/beauty/futex_op.c"
df4cb1678   Arnaldo Carvalho de Melo   perf trace: Move ...
528
  #include "trace/beauty/mmap.c"
ba2f22cf9   Arnaldo Carvalho de Melo   perf trace: Beaut...
529
  #include "trace/beauty/mode_t.c"
a30e6259b   Arnaldo Carvalho de Melo   perf trace: Move ...
530
  #include "trace/beauty/msg_flags.c"
8f48df69b   Arnaldo Carvalho de Melo   perf trace: Move ...
531
  #include "trace/beauty/open_flags.c"
62de344e4   Arnaldo Carvalho de Melo   perf trace: Move ...
532
  #include "trace/beauty/perf_event_open.c"
d5d71e86d   Arnaldo Carvalho de Melo   perf trace: Move ...
533
  #include "trace/beauty/pid.c"
a3bca91f2   Arnaldo Carvalho de Melo   perf trace: Beaut...
534
  #include "trace/beauty/sched_policy.c"
f5cd95ea6   Arnaldo Carvalho de Melo   perf trace: Move ...
535
  #include "trace/beauty/seccomp.c"
12199d8e2   Arnaldo Carvalho de Melo   perf trace: Move ...
536
  #include "trace/beauty/signum.c"
bbf86c43e   Arnaldo Carvalho de Melo   perf trace: Move ...
537
  #include "trace/beauty/socket_type.c"
7206b900e   Arnaldo Carvalho de Melo   perf trace: Beaut...
538
  #include "trace/beauty/waitid_options.c"
a3bca91f2   Arnaldo Carvalho de Melo   perf trace: Beaut...
539

514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
540
541
  static struct syscall_fmt {
  	const char *name;
aec1930b0   Arnaldo Carvalho de Melo   perf trace: Add a...
542
  	const char *alias;
01533e972   Arnaldo Carvalho de Melo   perf trace: Put s...
543
  	size_t	   (*arg_scnprintf[6])(char *bf, size_t size, struct syscall_arg *arg);
1f115cb72   Arnaldo Carvalho de Melo   perf trace: Allow...
544
  	void	   *arg_parm[6];
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
545
  	bool	   errmsg;
11c8e39f5   Arnaldo Carvalho de Melo   perf trace: Infra...
546
  	bool	   errpid;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
547
  	bool	   timeout;
04b34729e   Arnaldo Carvalho de Melo   perf trace: Allow...
548
  	bool	   hexret;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
549
  } syscall_fmts[] = {
511089994   Arnaldo Carvalho de Melo   perf trace: Beaut...
550
  	{ .name	    = "access",	    .errmsg = true,
12f3ca4fc   Arnaldo Carvalho de Melo   perf trace: Use t...
551
  	  .arg_scnprintf = { [1] = SCA_ACCMODE,  /* mode */ }, },
aec1930b0   Arnaldo Carvalho de Melo   perf trace: Add a...
552
  	{ .name	    = "arch_prctl", .errmsg = true, .alias = "prctl", },
729a78417   Arnaldo Carvalho de Melo   perf trace: Add c...
553
  	{ .name	    = "bpf",	    .errmsg = true, STRARRAY(0, cmd, bpf_cmd), },
beccb2b54   Arnaldo Carvalho de Melo   perf trace: Allow...
554
555
  	{ .name	    = "brk",	    .hexret = true,
  	  .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, },
12f3ca4fc   Arnaldo Carvalho de Melo   perf trace: Use t...
556
557
558
  	{ .name	    = "chdir",	    .errmsg = true, },
  	{ .name	    = "chmod",	    .errmsg = true, },
  	{ .name	    = "chroot",	    .errmsg = true, },
4f8c1b74c   David Ahern   perf trace: Add b...
559
  	{ .name     = "clock_gettime",  .errmsg = true, STRARRAY(0, clk_id, clockid), },
11c8e39f5   Arnaldo Carvalho de Melo   perf trace: Infra...
560
  	{ .name	    = "clone",	    .errpid = true, },
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
561
  	{ .name	    = "close",	    .errmsg = true,
48000a1ae   Arnaldo Carvalho de Melo   perf tools: Remov...
562
  	  .arg_scnprintf = { [0] = SCA_CLOSE_FD, /* fd */ }, },
a14bb860a   Arnaldo Carvalho de Melo   perf trace: Beaut...
563
  	{ .name	    = "connect",    .errmsg = true, },
12f3ca4fc   Arnaldo Carvalho de Melo   perf trace: Use t...
564
  	{ .name	    = "creat",	    .errmsg = true, },
b6565c908   Arnaldo Carvalho de Melo   perf trace: Use t...
565
566
567
  	{ .name	    = "dup",	    .errmsg = true, },
  	{ .name	    = "dup2",	    .errmsg = true, },
  	{ .name	    = "dup3",	    .errmsg = true, },
453350dd0   Arnaldo Carvalho de Melo   perf trace: Add h...
568
  	{ .name	    = "epoll_ctl",  .errmsg = true, STRARRAY(1, op, epoll_ctl_ops), },
49af9e93a   Arnaldo Carvalho de Melo   perf trace: Beaut...
569
570
  	{ .name	    = "eventfd2",   .errmsg = true,
  	  .arg_scnprintf = { [1] = SCA_EFD_FLAGS, /* flags */ }, },
12f3ca4fc   Arnaldo Carvalho de Melo   perf trace: Use t...
571
  	{ .name	    = "faccessat",  .errmsg = true, },
b6565c908   Arnaldo Carvalho de Melo   perf trace: Use t...
572
573
574
575
  	{ .name	    = "fadvise64",  .errmsg = true, },
  	{ .name	    = "fallocate",  .errmsg = true, },
  	{ .name	    = "fchdir",	    .errmsg = true, },
  	{ .name	    = "fchmod",	    .errmsg = true, },
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
576
  	{ .name	    = "fchmodat",   .errmsg = true,
12f3ca4fc   Arnaldo Carvalho de Melo   perf trace: Use t...
577
  	  .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
b6565c908   Arnaldo Carvalho de Melo   perf trace: Use t...
578
  	{ .name	    = "fchown",	    .errmsg = true, },
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
579
  	{ .name	    = "fchownat",   .errmsg = true,
12f3ca4fc   Arnaldo Carvalho de Melo   perf trace: Use t...
580
  	  .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
581
  	{ .name	    = "fcntl",	    .errmsg = true,
b6565c908   Arnaldo Carvalho de Melo   perf trace: Use t...
582
  	  .arg_scnprintf = { [1] = SCA_STRARRAY, /* cmd */ },
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
583
  	  .arg_parm	 = { [1] = &strarray__fcntl_cmds, /* cmd */ }, },
b6565c908   Arnaldo Carvalho de Melo   perf trace: Use t...
584
  	{ .name	    = "fdatasync",  .errmsg = true, },
5cea6ff26   Arnaldo Carvalho de Melo   perf trace: Beaut...
585
  	{ .name	    = "flock",	    .errmsg = true,
b6565c908   Arnaldo Carvalho de Melo   perf trace: Use t...
586
587
588
  	  .arg_scnprintf = { [1] = SCA_FLOCK, /* cmd */ }, },
  	{ .name	    = "fsetxattr",  .errmsg = true, },
  	{ .name	    = "fstat",	    .errmsg = true, .alias = "newfstat", },
12f3ca4fc   Arnaldo Carvalho de Melo   perf trace: Use t...
589
  	{ .name	    = "fstatat",    .errmsg = true, .alias = "newfstatat", },
b6565c908   Arnaldo Carvalho de Melo   perf trace: Use t...
590
591
592
  	{ .name	    = "fstatfs",    .errmsg = true, },
  	{ .name	    = "fsync",    .errmsg = true, },
  	{ .name	    = "ftruncate", .errmsg = true, },
f9da0b0c7   Arnaldo Carvalho de Melo   perf trace: Add b...
593
594
  	{ .name	    = "futex",	    .errmsg = true,
  	  .arg_scnprintf = { [1] = SCA_FUTEX_OP, /* op */ }, },
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
595
  	{ .name	    = "futimesat", .errmsg = true,
12f3ca4fc   Arnaldo Carvalho de Melo   perf trace: Use t...
596
  	  .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
b6565c908   Arnaldo Carvalho de Melo   perf trace: Use t...
597
598
  	{ .name	    = "getdents",   .errmsg = true, },
  	{ .name	    = "getdents64", .errmsg = true, },
453350dd0   Arnaldo Carvalho de Melo   perf trace: Add h...
599
  	{ .name	    = "getitimer",  .errmsg = true, STRARRAY(0, which, itimers), },
c65f10701   Arnaldo Carvalho de Melo   perf trace: Beaut...
600
  	{ .name	    = "getpid",	    .errpid = true, },
d1d438a3b   Arnaldo Carvalho de Melo   perf trace: Beaut...
601
  	{ .name	    = "getpgid",    .errpid = true, },
c65f10701   Arnaldo Carvalho de Melo   perf trace: Beaut...
602
  	{ .name	    = "getppid",    .errpid = true, },
39878d492   Arnaldo Carvalho de Melo   perf trace: Prett...
603
604
  	{ .name	    = "getrandom",  .errmsg = true,
  	  .arg_scnprintf = { [2] = SCA_GETRANDOM_FLAGS, /* flags */ }, },
453350dd0   Arnaldo Carvalho de Melo   perf trace: Add h...
605
  	{ .name	    = "getrlimit",  .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
12f3ca4fc   Arnaldo Carvalho de Melo   perf trace: Use t...
606
607
  	{ .name	    = "getxattr",   .errmsg = true, },
  	{ .name	    = "inotify_add_watch",	    .errmsg = true, },
beccb2b54   Arnaldo Carvalho de Melo   perf trace: Allow...
608
  	{ .name	    = "ioctl",	    .errmsg = true,
b6565c908   Arnaldo Carvalho de Melo   perf trace: Use t...
609
  	  .arg_scnprintf = {
844ae5b46   Arnaldo Carvalho de Melo   perf trace: Fix i...
610
611
612
613
  #if defined(__i386__) || defined(__x86_64__)
  /*
   * FIXME: Make this available to all arches.
   */
78645cf3e   Arnaldo Carvalho de Melo   perf trace: Initi...
614
615
616
  			     [1] = SCA_STRHEXARRAY, /* cmd */
  			     [2] = SCA_HEX, /* arg */ },
  	  .arg_parm	 = { [1] = &strarray__tioctls, /* cmd */ }, },
844ae5b46   Arnaldo Carvalho de Melo   perf trace: Fix i...
617
618
619
  #else
  			     [2] = SCA_HEX, /* arg */ }, },
  #endif
b62bee1bd   Arnaldo Carvalho de Melo   perf trace: Beaut...
620
  	{ .name	    = "keyctl",	    .errmsg = true, STRARRAY(0, option, keyctl_options), },
8bad5b0ab   Arnaldo Carvalho de Melo   perf trace: Beaut...
621
622
  	{ .name	    = "kill",	    .errmsg = true,
  	  .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
12f3ca4fc   Arnaldo Carvalho de Melo   perf trace: Use t...
623
624
  	{ .name	    = "lchown",    .errmsg = true, },
  	{ .name	    = "lgetxattr",  .errmsg = true, },
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
625
  	{ .name	    = "linkat",	    .errmsg = true,
48000a1ae   Arnaldo Carvalho de Melo   perf tools: Remov...
626
  	  .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
12f3ca4fc   Arnaldo Carvalho de Melo   perf trace: Use t...
627
628
629
  	{ .name	    = "listxattr",  .errmsg = true, },
  	{ .name	    = "llistxattr", .errmsg = true, },
  	{ .name	    = "lremovexattr",  .errmsg = true, },
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
630
  	{ .name	    = "lseek",	    .errmsg = true,
b6565c908   Arnaldo Carvalho de Melo   perf trace: Use t...
631
  	  .arg_scnprintf = { [2] = SCA_STRARRAY, /* whence */ },
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
632
  	  .arg_parm	 = { [2] = &strarray__whences, /* whence */ }, },
12f3ca4fc   Arnaldo Carvalho de Melo   perf trace: Use t...
633
634
635
  	{ .name	    = "lsetxattr",  .errmsg = true, },
  	{ .name	    = "lstat",	    .errmsg = true, .alias = "newlstat", },
  	{ .name	    = "lsxattr",    .errmsg = true, },
9e9716d1b   Arnaldo Carvalho de Melo   perf trace: Add b...
636
637
638
  	{ .name     = "madvise",    .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_HEX,	 /* start */
  			     [2] = SCA_MADV_BHV, /* behavior */ }, },
12f3ca4fc   Arnaldo Carvalho de Melo   perf trace: Use t...
639
  	{ .name	    = "mkdir",    .errmsg = true, },
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
640
  	{ .name	    = "mkdirat",    .errmsg = true,
12f3ca4fc   Arnaldo Carvalho de Melo   perf trace: Use t...
641
642
  	  .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
  	{ .name	    = "mknod",      .errmsg = true, },
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
643
  	{ .name	    = "mknodat",    .errmsg = true,
12f3ca4fc   Arnaldo Carvalho de Melo   perf trace: Use t...
644
  	  .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
3d903aa74   Arnaldo Carvalho de Melo   perf trace: Beaut...
645
646
647
648
  	{ .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...
649
  	{ .name	    = "mmap",	    .hexret = true,
ae685380b   Arnaldo Carvalho de Melo   perf trace: Add b...
650
  	  .arg_scnprintf = { [0] = SCA_HEX,	  /* addr */
941557e0e   Arnaldo Carvalho de Melo   perf trace: Add b...
651
  			     [2] = SCA_MMAP_PROT, /* prot */
b6565c908   Arnaldo Carvalho de Melo   perf trace: Use t...
652
  			     [3] = SCA_MMAP_FLAGS, /* flags */ }, },
beccb2b54   Arnaldo Carvalho de Melo   perf trace: Allow...
653
  	{ .name	    = "mprotect",   .errmsg = true,
ae685380b   Arnaldo Carvalho de Melo   perf trace: Add b...
654
655
  	  .arg_scnprintf = { [0] = SCA_HEX, /* start */
  			     [2] = SCA_MMAP_PROT, /* prot */ }, },
090389b6d   Arnaldo Carvalho de Melo   perf trace: Assoc...
656
657
  	{ .name	    = "mq_unlink", .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_FILENAME, /* u_name */ }, },
ae685380b   Arnaldo Carvalho de Melo   perf trace: Add b...
658
659
  	{ .name	    = "mremap",	    .hexret = true,
  	  .arg_scnprintf = { [0] = SCA_HEX, /* addr */
86998dda5   Alex Snast   perf trace: Add b...
660
  			     [3] = SCA_MREMAP_FLAGS, /* flags */
ae685380b   Arnaldo Carvalho de Melo   perf trace: Add b...
661
  			     [4] = SCA_HEX, /* new_addr */ }, },
3d903aa74   Arnaldo Carvalho de Melo   perf trace: Beaut...
662
663
  	{ .name	    = "munlock",    .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
beccb2b54   Arnaldo Carvalho de Melo   perf trace: Allow...
664
665
  	{ .name	    = "munmap",	    .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
666
  	{ .name	    = "name_to_handle_at", .errmsg = true,
48000a1ae   Arnaldo Carvalho de Melo   perf tools: Remov...
667
  	  .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
668
  	{ .name	    = "newfstatat", .errmsg = true,
12f3ca4fc   Arnaldo Carvalho de Melo   perf trace: Use t...
669
  	  .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
be65a89a0   Arnaldo Carvalho de Melo   perf trace: Add b...
670
  	{ .name	    = "open",	    .errmsg = true,
12f3ca4fc   Arnaldo Carvalho de Melo   perf trace: Use t...
671
  	  .arg_scnprintf = { [1] = SCA_OPEN_FLAGS, /* flags */ }, },
31cd3855c   Arnaldo Carvalho de Melo   perf trace: Tell ...
672
  	{ .name	    = "open_by_handle_at", .errmsg = true,
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
673
674
  	  .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
  			     [2] = SCA_OPEN_FLAGS, /* flags */ }, },
31cd3855c   Arnaldo Carvalho de Melo   perf trace: Tell ...
675
  	{ .name	    = "openat",	    .errmsg = true,
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
676
677
  	  .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
  			     [2] = SCA_OPEN_FLAGS, /* flags */ }, },
a1c2552db   Arnaldo Carvalho de Melo   trace: Beautify p...
678
  	{ .name	    = "perf_event_open", .errmsg = true,
ccd9b2a7f   Arnaldo Carvalho de Melo   perf trace: Do no...
679
  	  .arg_scnprintf = { [2] = SCA_INT, /* cpu */
a1c2552db   Arnaldo Carvalho de Melo   trace: Beautify p...
680
681
  			     [3] = SCA_FD,  /* group_fd */
  			     [4] = SCA_PERF_FLAGS,  /* flags */ }, },
46cce19ba   Arnaldo Carvalho de Melo   perf trace: Beaut...
682
683
  	{ .name	    = "pipe2",	    .errmsg = true,
  	  .arg_scnprintf = { [1] = SCA_PIPE_FLAGS, /* flags */ }, },
aec1930b0   Arnaldo Carvalho de Melo   perf trace: Add a...
684
685
  	{ .name	    = "poll",	    .errmsg = true, .timeout = true, },
  	{ .name	    = "ppoll",	    .errmsg = true, .timeout = true, },
b6565c908   Arnaldo Carvalho de Melo   perf trace: Use t...
686
687
  	{ .name	    = "pread",	    .errmsg = true, .alias = "pread64", },
  	{ .name	    = "preadv",	    .errmsg = true, .alias = "pread", },
453350dd0   Arnaldo Carvalho de Melo   perf trace: Add h...
688
  	{ .name	    = "prlimit64",  .errmsg = true, STRARRAY(1, resource, rlimit_resources), },
b6565c908   Arnaldo Carvalho de Melo   perf trace: Use t...
689
690
691
  	{ .name	    = "pwrite",	    .errmsg = true, .alias = "pwrite64", },
  	{ .name	    = "pwritev",    .errmsg = true, },
  	{ .name	    = "read",	    .errmsg = true, },
12f3ca4fc   Arnaldo Carvalho de Melo   perf trace: Use t...
692
  	{ .name	    = "readlink",   .errmsg = true, },
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
693
  	{ .name	    = "readlinkat", .errmsg = true,
12f3ca4fc   Arnaldo Carvalho de Melo   perf trace: Use t...
694
  	  .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
b6565c908   Arnaldo Carvalho de Melo   perf trace: Use t...
695
  	{ .name	    = "readv",	    .errmsg = true, },
b2cc99fda   Arnaldo Carvalho de Melo   perf trace: Beaut...
696
  	{ .name	    = "recvfrom",   .errmsg = true,
b6565c908   Arnaldo Carvalho de Melo   perf trace: Use t...
697
  	  .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
b2cc99fda   Arnaldo Carvalho de Melo   perf trace: Beaut...
698
  	{ .name	    = "recvmmsg",   .errmsg = true,
b6565c908   Arnaldo Carvalho de Melo   perf trace: Use t...
699
  	  .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
b2cc99fda   Arnaldo Carvalho de Melo   perf trace: Beaut...
700
  	{ .name	    = "recvmsg",    .errmsg = true,
b6565c908   Arnaldo Carvalho de Melo   perf trace: Use t...
701
  	  .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, },
12f3ca4fc   Arnaldo Carvalho de Melo   perf trace: Use t...
702
  	{ .name	    = "removexattr", .errmsg = true, },
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
703
  	{ .name	    = "renameat",   .errmsg = true,
48000a1ae   Arnaldo Carvalho de Melo   perf tools: Remov...
704
  	  .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
12f3ca4fc   Arnaldo Carvalho de Melo   perf trace: Use t...
705
  	{ .name	    = "rmdir",    .errmsg = true, },
8bad5b0ab   Arnaldo Carvalho de Melo   perf trace: Beaut...
706
707
  	{ .name	    = "rt_sigaction", .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_SIGNUM, /* sig */ }, },
453350dd0   Arnaldo Carvalho de Melo   perf trace: Add h...
708
  	{ .name	    = "rt_sigprocmask",  .errmsg = true, STRARRAY(0, how, sighow), },
8bad5b0ab   Arnaldo Carvalho de Melo   perf trace: Beaut...
709
710
711
712
  	{ .name	    = "rt_sigqueueinfo", .errmsg = true,
  	  .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
  	{ .name	    = "rt_tgsigqueueinfo", .errmsg = true,
  	  .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
f0bbd6022   Arnaldo Carvalho de Melo   perf trace: Beaut...
713
714
  	{ .name	    = "sched_getattr",	      .errmsg = true, },
  	{ .name	    = "sched_setattr",	      .errmsg = true, },
a3bca91f2   Arnaldo Carvalho de Melo   perf trace: Beaut...
715
716
  	{ .name	    = "sched_setscheduler",   .errmsg = true,
  	  .arg_scnprintf = { [1] = SCA_SCHED_POLICY, /* policy */ }, },
997bba8cf   Arnaldo Carvalho de Melo   perf trace: Prett...
717
718
719
  	{ .name	    = "seccomp", .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_SECCOMP_OP, /* op */
  			     [1] = SCA_SECCOMP_FLAGS, /* flags */ }, },
aec1930b0   Arnaldo Carvalho de Melo   perf trace: Add a...
720
  	{ .name	    = "select",	    .errmsg = true, .timeout = true, },
b2cc99fda   Arnaldo Carvalho de Melo   perf trace: Beaut...
721
  	{ .name	    = "sendmmsg",    .errmsg = true,
b6565c908   Arnaldo Carvalho de Melo   perf trace: Use t...
722
  	  .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
b2cc99fda   Arnaldo Carvalho de Melo   perf trace: Beaut...
723
  	{ .name	    = "sendmsg",    .errmsg = true,
b6565c908   Arnaldo Carvalho de Melo   perf trace: Use t...
724
  	  .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, },
b2cc99fda   Arnaldo Carvalho de Melo   perf trace: Beaut...
725
  	{ .name	    = "sendto",	    .errmsg = true,
b6565c908   Arnaldo Carvalho de Melo   perf trace: Use t...
726
  	  .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
c65f10701   Arnaldo Carvalho de Melo   perf trace: Beaut...
727
  	{ .name	    = "set_tid_address", .errpid = true, },
453350dd0   Arnaldo Carvalho de Melo   perf trace: Add h...
728
  	{ .name	    = "setitimer",  .errmsg = true, STRARRAY(0, which, itimers), },
d1d438a3b   Arnaldo Carvalho de Melo   perf trace: Beaut...
729
  	{ .name	    = "setpgid",    .errmsg = true, },
453350dd0   Arnaldo Carvalho de Melo   perf trace: Add h...
730
  	{ .name	    = "setrlimit",  .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
12f3ca4fc   Arnaldo Carvalho de Melo   perf trace: Use t...
731
  	{ .name	    = "setxattr",   .errmsg = true, },
b6565c908   Arnaldo Carvalho de Melo   perf trace: Use t...
732
  	{ .name	    = "shutdown",   .errmsg = true, },
e10bce815   Arnaldo Carvalho de Melo   perf trace: Beaut...
733
  	{ .name	    = "socket",	    .errmsg = true,
a28b24b27   Arnaldo Carvalho de Melo   perf trace: Beaut...
734
735
  	  .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
  			     [1] = SCA_SK_TYPE, /* type */ },
07120aa5d   Arnaldo Carvalho de Melo   perf trace: Use s...
736
737
738
739
  	  .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...
740
  	  .arg_parm	 = { [0] = &strarray__socket_families, /* family */ }, },
12f3ca4fc   Arnaldo Carvalho de Melo   perf trace: Use t...
741
742
  	{ .name	    = "stat",	    .errmsg = true, .alias = "newstat", },
  	{ .name	    = "statfs",	    .errmsg = true, },
34221118c   Arnaldo Carvalho de Melo   perf trace: Use v...
743
744
745
746
  	{ .name	    = "swapoff",    .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_FILENAME, /* specialfile */ }, },
  	{ .name	    = "swapon",	    .errmsg = true,
  	  .arg_scnprintf = { [0] = SCA_FILENAME, /* specialfile */ }, },
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
747
  	{ .name	    = "symlinkat",  .errmsg = true,
48000a1ae   Arnaldo Carvalho de Melo   perf tools: Remov...
748
  	  .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
8bad5b0ab   Arnaldo Carvalho de Melo   perf trace: Beaut...
749
750
751
752
  	{ .name	    = "tgkill",	    .errmsg = true,
  	  .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
  	{ .name	    = "tkill",	    .errmsg = true,
  	  .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
12f3ca4fc   Arnaldo Carvalho de Melo   perf trace: Use t...
753
  	{ .name	    = "truncate",   .errmsg = true, },
e5959683a   Arnaldo Carvalho de Melo   perf trace: Add a...
754
  	{ .name	    = "uname",	    .errmsg = true, .alias = "newuname", },
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
755
  	{ .name	    = "unlinkat",   .errmsg = true,
12f3ca4fc   Arnaldo Carvalho de Melo   perf trace: Use t...
756
757
  	  .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
  	{ .name	    = "utime",  .errmsg = true, },
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
758
  	{ .name	    = "utimensat",  .errmsg = true,
12f3ca4fc   Arnaldo Carvalho de Melo   perf trace: Use t...
759
760
  	  .arg_scnprintf = { [0] = SCA_FDAT, /* dirfd */ }, },
  	{ .name	    = "utimes",  .errmsg = true, },
b6565c908   Arnaldo Carvalho de Melo   perf trace: Use t...
761
  	{ .name	    = "vmsplice",  .errmsg = true, },
11c8e39f5   Arnaldo Carvalho de Melo   perf trace: Infra...
762
  	{ .name	    = "wait4",	    .errpid = true,
7206b900e   Arnaldo Carvalho de Melo   perf trace: Beaut...
763
  	  .arg_scnprintf = { [2] = SCA_WAITID_OPTIONS, /* options */ }, },
11c8e39f5   Arnaldo Carvalho de Melo   perf trace: Infra...
764
  	{ .name	    = "waitid",	    .errpid = true,
7206b900e   Arnaldo Carvalho de Melo   perf trace: Beaut...
765
  	  .arg_scnprintf = { [3] = SCA_WAITID_OPTIONS, /* options */ }, },
b6565c908   Arnaldo Carvalho de Melo   perf trace: Use t...
766
767
  	{ .name	    = "write",	    .errmsg = true, },
  	{ .name	    = "writev",	    .errmsg = true, },
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
  };
  
  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;
f208bd8df   Arnaldo Carvalho de Melo   perf trace: Handl...
784
785
  	int		    nr_args;
  	struct format_field *args;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
786
  	const char	    *name;
5089f20ee   Arnaldo Carvalho de Melo   perf trace: Cache...
787
  	bool		    is_exit;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
788
  	struct syscall_fmt  *fmt;
01533e972   Arnaldo Carvalho de Melo   perf trace: Put s...
789
  	size_t		    (**arg_scnprintf)(char *bf, size_t size, struct syscall_arg *arg);
1f115cb72   Arnaldo Carvalho de Melo   perf trace: Allow...
790
  	void		    **arg_parm;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
791
  };
60c907abc   Arnaldo Carvalho de Melo   perf trace: Add a...
792
793
794
795
796
797
798
799
800
801
802
  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...
803
  	return printed + fprintf(fp, "): ");
60c907abc   Arnaldo Carvalho de Melo   perf trace: Add a...
804
  }
f994592d9   Arnaldo Carvalho de Melo   perf trace: Deref...
805
806
807
808
809
  /**
   * filename.ptr: The filename char pointer that will be vfs_getname'd
   * filename.entry_str_pos: Where to insert the string translated from
   *                         filename.ptr by the vfs_getname tracepoint/kprobe.
   */
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
810
811
812
813
  struct thread_trace {
  	u64		  entry_time;
  	u64		  exit_time;
  	bool		  entry_pending;
efd5745e4   Arnaldo Carvalho de Melo   perf trace: Count...
814
  	unsigned long	  nr_events;
a2ea67d7b   Stanislav Fomichev   perf trace: Add p...
815
  	unsigned long	  pfmaj, pfmin;
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
816
  	char		  *entry_str;
1302d88e6   Arnaldo Carvalho de Melo   perf trace: Use s...
817
  	double		  runtime_ms;
f994592d9   Arnaldo Carvalho de Melo   perf trace: Deref...
818
819
          struct {
  		unsigned long ptr;
7f4f80013   Arnaldo Carvalho de Melo   perf trace: Move ...
820
821
822
823
  		short int     entry_str_pos;
  		bool	      pending_open;
  		unsigned int  namelen;
  		char	      *name;
f994592d9   Arnaldo Carvalho de Melo   perf trace: Deref...
824
  	} filename;
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
825
826
827
828
  	struct {
  		int	  max;
  		char	  **table;
  	} paths;
bf2575c12   David Ahern   perf trace: Add s...
829
830
  
  	struct intlist *syscall_stats;
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
831
832
833
834
  };
  
  static struct thread_trace *thread_trace__new(void)
  {
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
835
836
837
838
  	struct thread_trace *ttrace =  zalloc(sizeof(struct thread_trace));
  
  	if (ttrace)
  		ttrace->paths.max = -1;
bf2575c12   David Ahern   perf trace: Add s...
839
  	ttrace->syscall_stats = intlist__new(NULL);
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
840
  	return ttrace;
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
841
  }
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
842
  static struct thread_trace *thread__trace(struct thread *thread, FILE *fp)
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
843
  {
efd5745e4   Arnaldo Carvalho de Melo   perf trace: Count...
844
  	struct thread_trace *ttrace;
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
845
846
  	if (thread == NULL)
  		goto fail;
89dceb22c   Namhyung Kim   perf trace: Use t...
847
848
  	if (thread__priv(thread) == NULL)
  		thread__set_priv(thread, thread_trace__new());
48000a1ae   Arnaldo Carvalho de Melo   perf tools: Remov...
849

89dceb22c   Namhyung Kim   perf trace: Use t...
850
  	if (thread__priv(thread) == NULL)
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
851
  		goto fail;
89dceb22c   Namhyung Kim   perf trace: Use t...
852
  	ttrace = thread__priv(thread);
efd5745e4   Arnaldo Carvalho de Melo   perf trace: Count...
853
854
855
  	++ttrace->nr_events;
  
  	return ttrace;
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
856
  fail:
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
857
  	color_fprintf(fp, PERF_COLOR_RED,
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
858
859
860
861
  		      "WARNING: not enough memory, dropping samples!
  ");
  	return NULL;
  }
598d02c5a   Stanislav Fomichev   perf trace: Add s...
862
863
  #define TRACE_PFMAJ		(1 << 0)
  #define TRACE_PFMIN		(1 << 1)
e4d44e830   Arnaldo Carvalho de Melo   perf trace: Use a...
864
  static const size_t trace__entry_str_size = 2048;
97119f37b   Arnaldo Carvalho de Melo   perf trace: Split...
865
  static int trace__set_fd_pathname(struct thread *thread, int fd, const char *pathname)
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
866
  {
89dceb22c   Namhyung Kim   perf trace: Use t...
867
  	struct thread_trace *ttrace = thread__priv(thread);
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
  
  	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...
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
  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...
915
916
  static const char *thread__fd_path(struct thread *thread, int fd,
  				   struct trace *trace)
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
917
  {
89dceb22c   Namhyung Kim   perf trace: Use t...
918
  	struct thread_trace *ttrace = thread__priv(thread);
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
919
920
921
922
923
924
  
  	if (ttrace == NULL)
  		return NULL;
  
  	if (fd < 0)
  		return NULL;
cdcd1e6bd   Arnaldo Carvalho de Melo   perf trace: Fix u...
925
  	if ((fd > ttrace->paths.max || ttrace->paths.table[fd] == NULL)) {
c522739d7   Arnaldo Carvalho de Melo   perf trace: Use v...
926
927
928
  		if (!trace->live)
  			return NULL;
  		++trace->stats.proc_getname;
cdcd1e6bd   Arnaldo Carvalho de Melo   perf trace: Fix u...
929
  		if (thread__read_fd_path(thread, fd))
c522739d7   Arnaldo Carvalho de Melo   perf trace: Use v...
930
931
  			return NULL;
  	}
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
932
933
934
935
936
937
938
939
940
  
  	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...
941
  	const char *path = thread__fd_path(arg->thread, fd, arg->trace);
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
942
943
944
945
946
947
948
949
950
951
952
953
  
  	if (path)
  		printed += scnprintf(bf + printed, size - printed, "<%s>", path);
  
  	return printed;
  }
  
  static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
  					      struct syscall_arg *arg)
  {
  	int fd = arg->val;
  	size_t printed = syscall_arg__scnprintf_fd(bf, size, arg);
89dceb22c   Namhyung Kim   perf trace: Use t...
954
  	struct thread_trace *ttrace = thread__priv(arg->thread);
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
955

046625231   Arnaldo Carvalho de Melo   perf tools: Intro...
956
957
  	if (ttrace && fd >= 0 && fd <= ttrace->paths.max)
  		zfree(&ttrace->paths.table[fd]);
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
958
959
960
  
  	return printed;
  }
f994592d9   Arnaldo Carvalho de Melo   perf trace: Deref...
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
  static void thread__set_filename_pos(struct thread *thread, const char *bf,
  				     unsigned long ptr)
  {
  	struct thread_trace *ttrace = thread__priv(thread);
  
  	ttrace->filename.ptr = ptr;
  	ttrace->filename.entry_str_pos = bf - ttrace->entry_str;
  }
  
  static size_t syscall_arg__scnprintf_filename(char *bf, size_t size,
  					      struct syscall_arg *arg)
  {
  	unsigned long ptr = arg->val;
  
  	if (!arg->trace->vfs_getname)
  		return scnprintf(bf, size, "%#x", ptr);
  
  	thread__set_filename_pos(arg->thread, bf, ptr);
  	return 0;
  }
ae9ed0357   Arnaldo Carvalho de Melo   perf trace: Add d...
981
982
983
984
  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...
985
986
987
  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...
988
  	return fprintf(fp, "%10.3f ", ts);
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
989
  }
f15eb531d   Namhyung Kim   perf trace: Add s...
990
  static bool done = false;
ba209f856   Arnaldo Carvalho de Melo   perf trace: Impro...
991
  static bool interrupted = false;
f15eb531d   Namhyung Kim   perf trace: Add s...
992

ba209f856   Arnaldo Carvalho de Melo   perf trace: Impro...
993
  static void sig_handler(int sig)
f15eb531d   Namhyung Kim   perf trace: Add s...
994
995
  {
  	done = true;
ba209f856   Arnaldo Carvalho de Melo   perf trace: Impro...
996
  	interrupted = sig == SIGINT;
f15eb531d   Namhyung Kim   perf trace: Add s...
997
  }
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
998
  static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thread,
60c907abc   Arnaldo Carvalho de Melo   perf trace: Add a...
999
  					u64 duration, u64 tstamp, FILE *fp)
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1000
1001
  {
  	size_t printed = trace__fprintf_tstamp(trace, tstamp, fp);
60c907abc   Arnaldo Carvalho de Melo   perf trace: Add a...
1002
  	printed += fprintf_duration(duration, fp);
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1003

50c95cbd7   Arnaldo Carvalho de Melo   perf trace: Add o...
1004
1005
  	if (trace->multiple_threads) {
  		if (trace->show_comm)
1902efe7f   Frederic Weisbecker   perf tools: Add n...
1006
  			printed += fprintf(fp, "%.14s/", thread__comm_str(thread));
380512345   Adrian Hunter   perf tools: struc...
1007
  		printed += fprintf(fp, "%d ", thread->tid);
50c95cbd7   Arnaldo Carvalho de Melo   perf trace: Add o...
1008
  	}
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1009
1010
1011
  
  	return printed;
  }
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1012
  static int trace__process_event(struct trace *trace, struct machine *machine,
162f0befd   Frederic Weisbecker   perf tools: Add t...
1013
  				union perf_event *event, struct perf_sample *sample)
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1014
1015
1016
1017
1018
  {
  	int ret = 0;
  
  	switch (event->header.type) {
  	case PERF_RECORD_LOST:
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1019
  		color_fprintf(trace->output, PERF_COLOR_RED,
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1020
1021
  			      "LOST %" PRIu64 " events!
  ", event->lost.lost);
162f0befd   Frederic Weisbecker   perf tools: Add t...
1022
  		ret = machine__process_lost_event(machine, event, sample);
3ed5ca2ef   Arnaldo Carvalho de Melo   perf trace: Do no...
1023
  		break;
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1024
  	default:
162f0befd   Frederic Weisbecker   perf tools: Add t...
1025
  		ret = machine__process_event(machine, event, sample);
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1026
1027
1028
1029
1030
  		break;
  	}
  
  	return ret;
  }
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1031
  static int trace__tool_process(struct perf_tool *tool,
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1032
  			       union perf_event *event,
162f0befd   Frederic Weisbecker   perf tools: Add t...
1033
  			       struct perf_sample *sample,
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1034
1035
  			       struct machine *machine)
  {
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1036
  	struct trace *trace = container_of(tool, struct trace, tool);
162f0befd   Frederic Weisbecker   perf tools: Add t...
1037
  	return trace__process_event(trace, machine, event, sample);
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1038
  }
caf8a0d04   Arnaldo Carvalho de Melo   perf trace: Warn ...
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
  static char *trace__machine__resolve_kernel_addr(void *vmachine, unsigned long long *addrp, char **modp)
  {
  	struct machine *machine = vmachine;
  
  	if (machine->kptr_restrict_warned)
  		return NULL;
  
  	if (symbol_conf.kptr_restrict) {
  		pr_warning("Kernel address maps (/proc/{kallsyms,modules}) are restricted.
  
  "
  			   "Check /proc/sys/kernel/kptr_restrict.
  
  "
  			   "Kernel samples will not be resolved.
  ");
  		machine->kptr_restrict_warned = true;
  		return NULL;
  	}
  
  	return machine__resolve_kernel_addr(vmachine, addrp, modp);
  }
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1061
1062
  static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
  {
0a7e6d1b6   Namhyung Kim   perf tools: Check...
1063
  	int err = symbol__init(NULL);
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1064
1065
1066
  
  	if (err)
  		return err;
8fb598e5a   David Ahern   perf trace: Fix c...
1067
1068
1069
  	trace->host = machine__new_host();
  	if (trace->host == NULL)
  		return -ENOMEM;
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1070

caf8a0d04   Arnaldo Carvalho de Melo   perf trace: Warn ...
1071
  	if (trace_event__register_resolver(trace->host, trace__machine__resolve_kernel_addr) < 0)
706c3da40   Arnaldo Carvalho de Melo   perf trace: Provi...
1072
  		return -errno;
a33fbd56e   Arnaldo Carvalho de Melo   perf machine: Sim...
1073
  	err = __machine__synthesize_threads(trace->host, &trace->tool, &trace->opts.target,
9d9cad763   Kan Liang   perf tools: Confi...
1074
1075
  					    evlist->threads, trace__tool_process, false,
  					    trace->opts.proc_map_timeout);
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1076
1077
1078
1079
1080
  	if (err)
  		symbol__exit();
  
  	return err;
  }
13d4ff3eb   Arnaldo Carvalho de Melo   perf trace: Intro...
1081
1082
1083
  static int syscall__set_arg_fmts(struct syscall *sc)
  {
  	struct format_field *field;
b6565c908   Arnaldo Carvalho de Melo   perf trace: Use t...
1084
  	int idx = 0, len;
13d4ff3eb   Arnaldo Carvalho de Melo   perf trace: Intro...
1085

f208bd8df   Arnaldo Carvalho de Melo   perf trace: Handl...
1086
  	sc->arg_scnprintf = calloc(sc->nr_args, sizeof(void *));
13d4ff3eb   Arnaldo Carvalho de Melo   perf trace: Intro...
1087
1088
  	if (sc->arg_scnprintf == NULL)
  		return -1;
1f115cb72   Arnaldo Carvalho de Melo   perf trace: Allow...
1089
1090
  	if (sc->fmt)
  		sc->arg_parm = sc->fmt->arg_parm;
f208bd8df   Arnaldo Carvalho de Melo   perf trace: Handl...
1091
  	for (field = sc->args; field; field = field->next) {
beccb2b54   Arnaldo Carvalho de Melo   perf trace: Allow...
1092
1093
  		if (sc->fmt && sc->fmt->arg_scnprintf[idx])
  			sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx];
12f3ca4fc   Arnaldo Carvalho de Melo   perf trace: Use t...
1094
1095
1096
1097
1098
  		else if (strcmp(field->type, "const char *") == 0 &&
  			 (strcmp(field->name, "filename") == 0 ||
  			  strcmp(field->name, "path") == 0 ||
  			  strcmp(field->name, "pathname") == 0))
  			sc->arg_scnprintf[idx] = SCA_FILENAME;
beccb2b54   Arnaldo Carvalho de Melo   perf trace: Allow...
1099
  		else if (field->flags & FIELD_IS_POINTER)
13d4ff3eb   Arnaldo Carvalho de Melo   perf trace: Intro...
1100
  			sc->arg_scnprintf[idx] = syscall_arg__scnprintf_hex;
d1d438a3b   Arnaldo Carvalho de Melo   perf trace: Beaut...
1101
1102
  		else if (strcmp(field->type, "pid_t") == 0)
  			sc->arg_scnprintf[idx] = SCA_PID;
ba2f22cf9   Arnaldo Carvalho de Melo   perf trace: Beaut...
1103
1104
  		else if (strcmp(field->type, "umode_t") == 0)
  			sc->arg_scnprintf[idx] = SCA_MODE_T;
b6565c908   Arnaldo Carvalho de Melo   perf trace: Use t...
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
  		else if ((strcmp(field->type, "int") == 0 ||
  			  strcmp(field->type, "unsigned int") == 0 ||
  			  strcmp(field->type, "long") == 0) &&
  			 (len = strlen(field->name)) >= 2 &&
  			 strcmp(field->name + len - 2, "fd") == 0) {
  			/*
  			 * /sys/kernel/tracing/events/syscalls/sys_enter*
  			 * egrep 'field:.*fd;' .../format|sed -r 's/.*field:([a-z ]+) [a-z_]*fd.+/\1/g'|sort|uniq -c
  			 * 65 int
  			 * 23 unsigned int
  			 * 7 unsigned long
  			 */
  			sc->arg_scnprintf[idx] = SCA_FD;
  		}
13d4ff3eb   Arnaldo Carvalho de Melo   perf trace: Intro...
1119
1120
1121
1122
1123
  		++idx;
  	}
  
  	return 0;
  }
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1124
1125
1126
1127
  static int trace__read_syscall_info(struct trace *trace, int id)
  {
  	char tp_name[128];
  	struct syscall *sc;
fd0db1026   Arnaldo Carvalho de Melo   perf trace: Move ...
1128
  	const char *name = syscalltbl__name(trace->sctbl, id);
3a531260a   Arnaldo Carvalho de Melo   perf trace: Valid...
1129
1130
1131
  
  	if (name == NULL)
  		return -1;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
  
  	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...
1151
  	sc->name = name;
2ae3a312c   Arnaldo Carvalho de Melo   perf trace: Allow...
1152

3a531260a   Arnaldo Carvalho de Melo   perf trace: Valid...
1153
  	sc->fmt  = syscall_fmt__find(sc->name);
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1154

aec1930b0   Arnaldo Carvalho de Melo   perf trace: Add a...
1155
  	snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name);
97978b3e3   Jiri Olsa   perf tools: Add t...
1156
  	sc->tp_format = trace_event__tp_format("syscalls", tp_name);
aec1930b0   Arnaldo Carvalho de Melo   perf trace: Add a...
1157

8dd2a1317   Jiri Olsa   perf evsel: Propa...
1158
  	if (IS_ERR(sc->tp_format) && sc->fmt && sc->fmt->alias) {
aec1930b0   Arnaldo Carvalho de Melo   perf trace: Add a...
1159
  		snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->fmt->alias);
97978b3e3   Jiri Olsa   perf tools: Add t...
1160
  		sc->tp_format = trace_event__tp_format("syscalls", tp_name);
aec1930b0   Arnaldo Carvalho de Melo   perf trace: Add a...
1161
  	}
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1162

8dd2a1317   Jiri Olsa   perf evsel: Propa...
1163
  	if (IS_ERR(sc->tp_format))
13d4ff3eb   Arnaldo Carvalho de Melo   perf trace: Intro...
1164
  		return -1;
f208bd8df   Arnaldo Carvalho de Melo   perf trace: Handl...
1165
1166
  	sc->args = sc->tp_format->format.fields;
  	sc->nr_args = sc->tp_format->format.nr_fields;
c42de706d   Taeung Song   perf trace: Check...
1167
1168
1169
1170
1171
1172
  	/*
  	 * We need to check and discard the first variable '__syscall_nr'
  	 * or 'nr' that mean the syscall number. It is needless here.
  	 * So drop '__syscall_nr' or 'nr' field but does not exist on older kernels.
  	 */
  	if (sc->args && (!strcmp(sc->args->name, "__syscall_nr") || !strcmp(sc->args->name, "nr"))) {
f208bd8df   Arnaldo Carvalho de Melo   perf trace: Handl...
1173
1174
1175
  		sc->args = sc->args->next;
  		--sc->nr_args;
  	}
5089f20ee   Arnaldo Carvalho de Melo   perf trace: Cache...
1176
  	sc->is_exit = !strcmp(name, "exit_group") || !strcmp(name, "exit");
13d4ff3eb   Arnaldo Carvalho de Melo   perf trace: Intro...
1177
  	return syscall__set_arg_fmts(sc);
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1178
  }
d0cc439b3   Arnaldo Carvalho de Melo   perf trace: Valid...
1179
1180
  static int trace__validate_ev_qualifier(struct trace *trace)
  {
8b3ce7576   Arnaldo Carvalho de Melo   perf trace: Store...
1181
  	int err = 0, i;
d0cc439b3   Arnaldo Carvalho de Melo   perf trace: Valid...
1182
  	struct str_node *pos;
8b3ce7576   Arnaldo Carvalho de Melo   perf trace: Store...
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
  	trace->ev_qualifier_ids.nr = strlist__nr_entries(trace->ev_qualifier);
  	trace->ev_qualifier_ids.entries = malloc(trace->ev_qualifier_ids.nr *
  						 sizeof(trace->ev_qualifier_ids.entries[0]));
  
  	if (trace->ev_qualifier_ids.entries == NULL) {
  		fputs("Error:\tNot enough memory for allocating events qualifier ids
  ",
  		       trace->output);
  		err = -EINVAL;
  		goto out;
  	}
  
  	i = 0;
602a1f4da   Arnaldo Carvalho de Melo   perf tools: Renam...
1196
  	strlist__for_each_entry(pos, trace->ev_qualifier) {
d0cc439b3   Arnaldo Carvalho de Melo   perf trace: Valid...
1197
  		const char *sc = pos->s;
fd0db1026   Arnaldo Carvalho de Melo   perf trace: Move ...
1198
  		int id = syscalltbl__id(trace->sctbl, sc);
d0cc439b3   Arnaldo Carvalho de Melo   perf trace: Valid...
1199

8b3ce7576   Arnaldo Carvalho de Melo   perf trace: Store...
1200
  		if (id < 0) {
d0cc439b3   Arnaldo Carvalho de Melo   perf trace: Valid...
1201
1202
1203
1204
1205
1206
1207
1208
1209
  			if (err == 0) {
  				fputs("Error:\tInvalid syscall ", trace->output);
  				err = -EINVAL;
  			} else {
  				fputs(", ", trace->output);
  			}
  
  			fputs(sc, trace->output);
  		}
8b3ce7576   Arnaldo Carvalho de Melo   perf trace: Store...
1210
1211
  
  		trace->ev_qualifier_ids.entries[i++] = id;
d0cc439b3   Arnaldo Carvalho de Melo   perf trace: Valid...
1212
1213
1214
1215
1216
1217
1218
1219
  	}
  
  	if (err < 0) {
  		fputs("
  Hint:\ttry 'perf list syscalls:sys_enter_*'"
  		      "
  Hint:\tand: 'man syscalls'
  ", trace->output);
8b3ce7576   Arnaldo Carvalho de Melo   perf trace: Store...
1220
1221
  		zfree(&trace->ev_qualifier_ids.entries);
  		trace->ev_qualifier_ids.nr = 0;
d0cc439b3   Arnaldo Carvalho de Melo   perf trace: Valid...
1222
  	}
8b3ce7576   Arnaldo Carvalho de Melo   perf trace: Store...
1223
  out:
d0cc439b3   Arnaldo Carvalho de Melo   perf trace: Valid...
1224
1225
  	return err;
  }
55d43bcaf   David Ahern   perf trace: Fix S...
1226
1227
1228
1229
1230
1231
1232
1233
  /*
   * args is to be interpreted as a series of longs but we need to handle
   * 8-byte unaligned accesses. args points to raw_data within the event
   * and raw_data is guaranteed to be 8-byte unaligned because it is
   * preceded by raw_size which is a u32. So we need to copy args to a temp
   * variable to read it. Most notably this avoids extended load instructions
   * on unaligned addresses
   */
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1234
  static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
55d43bcaf   David Ahern   perf trace: Fix S...
1235
  				      unsigned char *args, struct trace *trace,
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
1236
  				      struct thread *thread)
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1237
  {
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1238
  	size_t printed = 0;
55d43bcaf   David Ahern   perf trace: Fix S...
1239
1240
  	unsigned char *p;
  	unsigned long val;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1241

f208bd8df   Arnaldo Carvalho de Melo   perf trace: Handl...
1242
  	if (sc->args != NULL) {
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1243
  		struct format_field *field;
01533e972   Arnaldo Carvalho de Melo   perf trace: Put s...
1244
1245
  		u8 bit = 1;
  		struct syscall_arg arg = {
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
1246
1247
1248
1249
  			.idx	= 0,
  			.mask	= 0,
  			.trace  = trace,
  			.thread = thread,
01533e972   Arnaldo Carvalho de Melo   perf trace: Put s...
1250
  		};
6e7eeb511   Arnaldo Carvalho de Melo   perf trace: Allow...
1251

f208bd8df   Arnaldo Carvalho de Melo   perf trace: Handl...
1252
  		for (field = sc->args; field;
01533e972   Arnaldo Carvalho de Melo   perf trace: Put s...
1253
1254
  		     field = field->next, ++arg.idx, bit <<= 1) {
  			if (arg.mask & bit)
6e7eeb511   Arnaldo Carvalho de Melo   perf trace: Allow...
1255
  				continue;
55d43bcaf   David Ahern   perf trace: Fix S...
1256
1257
1258
1259
  
  			/* special care for unaligned accesses */
  			p = args + sizeof(unsigned long) * arg.idx;
  			memcpy(&val, p, sizeof(val));
4aa582322   Arnaldo Carvalho de Melo   perf trace: Don't...
1260
1261
1262
1263
1264
  			/*
   			 * Suppress this argument if its value is zero and
   			 * and we don't have a string associated in an
   			 * strarray for it.
   			 */
55d43bcaf   David Ahern   perf trace: Fix S...
1265
  			if (val == 0 &&
4aa582322   Arnaldo Carvalho de Melo   perf trace: Don't...
1266
1267
1268
  			    !(sc->arg_scnprintf &&
  			      sc->arg_scnprintf[arg.idx] == SCA_STRARRAY &&
  			      sc->arg_parm[arg.idx]))
22ae5cf1c   Arnaldo Carvalho de Melo   perf trace: Don't...
1269
  				continue;
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1270
  			printed += scnprintf(bf + printed, size - printed,
13d4ff3eb   Arnaldo Carvalho de Melo   perf trace: Intro...
1271
  					     "%s%s: ", printed ? ", " : "", field->name);
01533e972   Arnaldo Carvalho de Melo   perf trace: Put s...
1272
  			if (sc->arg_scnprintf && sc->arg_scnprintf[arg.idx]) {
55d43bcaf   David Ahern   perf trace: Fix S...
1273
  				arg.val = val;
1f115cb72   Arnaldo Carvalho de Melo   perf trace: Allow...
1274
1275
  				if (sc->arg_parm)
  					arg.parm = sc->arg_parm[arg.idx];
01533e972   Arnaldo Carvalho de Melo   perf trace: Put s...
1276
1277
  				printed += sc->arg_scnprintf[arg.idx](bf + printed,
  								      size - printed, &arg);
6e7eeb511   Arnaldo Carvalho de Melo   perf trace: Allow...
1278
  			} else {
13d4ff3eb   Arnaldo Carvalho de Melo   perf trace: Intro...
1279
  				printed += scnprintf(bf + printed, size - printed,
55d43bcaf   David Ahern   perf trace: Fix S...
1280
  						     "%ld", val);
6e7eeb511   Arnaldo Carvalho de Melo   perf trace: Allow...
1281
  			}
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1282
  		}
4c4d6e519   Arnaldo Carvalho de Melo   perf trace: Do no...
1283
1284
1285
1286
1287
1288
  	} else if (IS_ERR(sc->tp_format)) {
  		/*
  		 * If we managed to read the tracepoint /format file, then we
  		 * may end up not having any args, like with gettid(), so only
  		 * print the raw args when we didn't manage to read it.
  		 */
01533e972   Arnaldo Carvalho de Melo   perf trace: Put s...
1289
  		int i = 0;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1290
  		while (i < 6) {
55d43bcaf   David Ahern   perf trace: Fix S...
1291
1292
1293
  			/* special care for unaligned accesses */
  			p = args + sizeof(unsigned long) * i;
  			memcpy(&val, p, sizeof(val));
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1294
1295
  			printed += scnprintf(bf + printed, size - printed,
  					     "%sarg%d: %ld",
55d43bcaf   David Ahern   perf trace: Fix S...
1296
  					     printed ? ", " : "", i, val);
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
1297
1298
1299
1300
1301
1302
  			++i;
  		}
  	}
  
  	return printed;
  }
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1303
  typedef int (*tracepoint_handler)(struct trace *trace, struct perf_evsel *evsel,
0c82adcf1   Stanislav Fomichev   perf trace: Add p...
1304
  				  union perf_event *event,
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1305
1306
1307
  				  struct perf_sample *sample);
  
  static struct syscall *trace__syscall_info(struct trace *trace,
bf2575c12   David Ahern   perf trace: Add s...
1308
  					   struct perf_evsel *evsel, int id)
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1309
  {
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1310
1311
  
  	if (id < 0) {
adaa18bf5   Arnaldo Carvalho de Melo   perf trace: Hide ...
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
  
  		/*
  		 * 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...
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
  		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 -...
1342
1343
1344
1345
1346
1347
1348
  	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...
1349
1350
  	return NULL;
  }
bf2575c12   David Ahern   perf trace: Add s...
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
  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);
  }
e596663eb   Arnaldo Carvalho de Melo   perf trace: Handl...
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
  static int trace__printf_interrupted_entry(struct trace *trace, struct perf_sample *sample)
  {
  	struct thread_trace *ttrace;
  	u64 duration;
  	size_t printed;
  
  	if (trace->current == NULL)
  		return 0;
  
  	ttrace = thread__priv(trace->current);
  
  	if (!ttrace->entry_pending)
  		return 0;
  
  	duration = sample->time - ttrace->entry_time;
567eea578   Arnaldo Carvalho de Melo   perf trace: Use t...
1391
  	printed  = trace__fprintf_entry_head(trace, trace->current, duration, ttrace->entry_time, trace->output);
e596663eb   Arnaldo Carvalho de Melo   perf trace: Handl...
1392
1393
1394
1395
1396
1397
  	printed += fprintf(trace->output, "%-70s) ...
  ", ttrace->entry_str);
  	ttrace->entry_pending = false;
  
  	return printed;
  }
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1398
  static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
0c82adcf1   Stanislav Fomichev   perf trace: Add p...
1399
  			    union perf_event *event __maybe_unused,
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1400
1401
  			    struct perf_sample *sample)
  {
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1402
  	char *msg;
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1403
  	void *args;
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1404
  	size_t printed = 0;
2ae3a312c   Arnaldo Carvalho de Melo   perf trace: Allow...
1405
  	struct thread *thread;
b91fc39f4   Arnaldo Carvalho de Melo   perf machine: Pro...
1406
  	int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
bf2575c12   David Ahern   perf trace: Add s...
1407
  	struct syscall *sc = trace__syscall_info(trace, evsel, id);
2ae3a312c   Arnaldo Carvalho de Melo   perf trace: Allow...
1408
1409
1410
1411
  	struct thread_trace *ttrace;
  
  	if (sc == NULL)
  		return -1;
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1412

8fb598e5a   David Ahern   perf trace: Fix c...
1413
  	thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1414
  	ttrace = thread__trace(thread, trace->output);
2ae3a312c   Arnaldo Carvalho de Melo   perf trace: Allow...
1415
  	if (ttrace == NULL)
b91fc39f4   Arnaldo Carvalho de Melo   perf machine: Pro...
1416
  		goto out_put;
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1417

77170988f   Arnaldo Carvalho de Melo   perf trace: Don't...
1418
  	args = perf_evsel__sc_tp_ptr(evsel, args, sample);
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1419
1420
  
  	if (ttrace->entry_str == NULL) {
e4d44e830   Arnaldo Carvalho de Melo   perf trace: Use a...
1421
  		ttrace->entry_str = malloc(trace__entry_str_size);
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1422
  		if (!ttrace->entry_str)
b91fc39f4   Arnaldo Carvalho de Melo   perf machine: Pro...
1423
  			goto out_put;
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1424
  	}
5cf9c84e2   Arnaldo Carvalho de Melo   perf trace: Intro...
1425
  	if (!(trace->duration_filter || trace->summary_only || trace->min_stack))
6ebad5c10   Arnaldo Carvalho de Melo   perf trace: Fix s...
1426
  		trace__printf_interrupted_entry(trace, sample);
e596663eb   Arnaldo Carvalho de Melo   perf trace: Handl...
1427

752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1428
1429
  	ttrace->entry_time = sample->time;
  	msg = ttrace->entry_str;
e4d44e830   Arnaldo Carvalho de Melo   perf trace: Use a...
1430
  	printed += scnprintf(msg + printed, trace__entry_str_size - printed, "%s(", sc->name);
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1431

e4d44e830   Arnaldo Carvalho de Melo   perf trace: Use a...
1432
  	printed += syscall__scnprintf_args(sc, msg + printed, trace__entry_str_size - printed,
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
1433
  					   args, trace, thread);
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1434

5089f20ee   Arnaldo Carvalho de Melo   perf trace: Cache...
1435
  	if (sc->is_exit) {
5cf9c84e2   Arnaldo Carvalho de Melo   perf trace: Intro...
1436
  		if (!(trace->duration_filter || trace->summary_only || trace->min_stack)) {
567eea578   Arnaldo Carvalho de Melo   perf trace: Use t...
1437
  			trace__fprintf_entry_head(trace, thread, 1, ttrace->entry_time, trace->output);
c008f78f9   Arnaldo Carvalho de Melo   perf trace: Fix e...
1438
1439
  			fprintf(trace->output, "%-70s)
  ", ttrace->entry_str);
ae9ed0357   Arnaldo Carvalho de Melo   perf trace: Add d...
1440
  		}
7f4f80013   Arnaldo Carvalho de Melo   perf trace: Move ...
1441
  	} else {
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1442
  		ttrace->entry_pending = true;
7f4f80013   Arnaldo Carvalho de Melo   perf trace: Move ...
1443
1444
1445
  		/* See trace__vfs_getname & trace__sys_exit */
  		ttrace->filename.pending_open = false;
  	}
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1446

f3b623b84   Arnaldo Carvalho de Melo   perf tools: Refer...
1447
1448
1449
1450
  	if (trace->current != thread) {
  		thread__put(trace->current);
  		trace->current = thread__get(thread);
  	}
b91fc39f4   Arnaldo Carvalho de Melo   perf machine: Pro...
1451
1452
1453
1454
  	err = 0;
  out_put:
  	thread__put(thread);
  	return err;
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1455
  }
5cf9c84e2   Arnaldo Carvalho de Melo   perf trace: Intro...
1456
1457
1458
  static int trace__resolve_callchain(struct trace *trace, struct perf_evsel *evsel,
  				    struct perf_sample *sample,
  				    struct callchain_cursor *cursor)
202ff9684   Arnaldo Carvalho de Melo   perf trace: Suppo...
1459
1460
  {
  	struct addr_location al;
5cf9c84e2   Arnaldo Carvalho de Melo   perf trace: Intro...
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
  
  	if (machine__resolve(trace->host, &al, sample) < 0 ||
  	    thread__resolve_callchain(al.thread, cursor, evsel, sample, NULL, NULL, trace->max_stack))
  		return -1;
  
  	return 0;
  }
  
  static int trace__fprintf_callchain(struct trace *trace, struct perf_sample *sample)
  {
202ff9684   Arnaldo Carvalho de Melo   perf trace: Suppo...
1471
  	/* TODO: user-configurable print_opts */
e20ab86e5   Arnaldo Carvalho de Melo   perf evsel: Move ...
1472
1473
1474
  	const unsigned int print_opts = EVSEL__PRINT_SYM |
  				        EVSEL__PRINT_DSO |
  				        EVSEL__PRINT_UNKNOWN_AS_ADDR;
202ff9684   Arnaldo Carvalho de Melo   perf trace: Suppo...
1475

d327e60cf   Arnaldo Carvalho de Melo   perf tools: Remov...
1476
  	return sample__fprintf_callchain(sample, 38, print_opts, &callchain_cursor, trace->output);
202ff9684   Arnaldo Carvalho de Melo   perf trace: Suppo...
1477
  }
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1478
  static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
0c82adcf1   Stanislav Fomichev   perf trace: Add p...
1479
  			   union perf_event *event __maybe_unused,
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1480
1481
  			   struct perf_sample *sample)
  {
2c82c3ad5   Chang Hyun Park   perf trace: Fix m...
1482
  	long ret;
60c907abc   Arnaldo Carvalho de Melo   perf trace: Add a...
1483
  	u64 duration = 0;
2ae3a312c   Arnaldo Carvalho de Melo   perf trace: Allow...
1484
  	struct thread *thread;
5cf9c84e2   Arnaldo Carvalho de Melo   perf trace: Intro...
1485
  	int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1, callchain_ret = 0;
bf2575c12   David Ahern   perf trace: Add s...
1486
  	struct syscall *sc = trace__syscall_info(trace, evsel, id);
2ae3a312c   Arnaldo Carvalho de Melo   perf trace: Allow...
1487
1488
1489
1490
  	struct thread_trace *ttrace;
  
  	if (sc == NULL)
  		return -1;
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1491

8fb598e5a   David Ahern   perf trace: Fix c...
1492
  	thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1493
  	ttrace = thread__trace(thread, trace->output);
2ae3a312c   Arnaldo Carvalho de Melo   perf trace: Allow...
1494
  	if (ttrace == NULL)
b91fc39f4   Arnaldo Carvalho de Melo   perf machine: Pro...
1495
  		goto out_put;
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1496

bf2575c12   David Ahern   perf trace: Add s...
1497
1498
  	if (trace->summary)
  		thread__update_stats(ttrace, id, sample);
77170988f   Arnaldo Carvalho de Melo   perf trace: Don't...
1499
  	ret = perf_evsel__sc_tp_uint(evsel, ret, sample);
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1500

fd0db1026   Arnaldo Carvalho de Melo   perf trace: Move ...
1501
  	if (id == trace->open_id && ret >= 0 && ttrace->filename.pending_open) {
7f4f80013   Arnaldo Carvalho de Melo   perf trace: Move ...
1502
1503
  		trace__set_fd_pathname(thread, ret, ttrace->filename.name);
  		ttrace->filename.pending_open = false;
c522739d7   Arnaldo Carvalho de Melo   perf trace: Use v...
1504
1505
  		++trace->stats.vfs_getname;
  	}
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1506
  	ttrace->exit_time = sample->time;
ae9ed0357   Arnaldo Carvalho de Melo   perf trace: Add d...
1507
  	if (ttrace->entry_time) {
60c907abc   Arnaldo Carvalho de Melo   perf trace: Add a...
1508
  		duration = sample->time - ttrace->entry_time;
ae9ed0357   Arnaldo Carvalho de Melo   perf trace: Add d...
1509
1510
1511
1512
  		if (trace__filter_duration(trace, duration))
  			goto out;
  	} else if (trace->duration_filter)
  		goto out;
60c907abc   Arnaldo Carvalho de Melo   perf trace: Add a...
1513

5cf9c84e2   Arnaldo Carvalho de Melo   perf trace: Intro...
1514
1515
1516
1517
1518
1519
1520
1521
  	if (sample->callchain) {
  		callchain_ret = trace__resolve_callchain(trace, evsel, sample, &callchain_cursor);
  		if (callchain_ret == 0) {
  			if (callchain_cursor.nr < trace->min_stack)
  				goto out;
  			callchain_ret = 1;
  		}
  	}
fd2eabaf1   David Ahern   perf trace: Add s...
1522
1523
  	if (trace->summary_only)
  		goto out;
567eea578   Arnaldo Carvalho de Melo   perf trace: Use t...
1524
  	trace__fprintf_entry_head(trace, thread, duration, ttrace->entry_time, trace->output);
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1525
1526
  
  	if (ttrace->entry_pending) {
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1527
  		fprintf(trace->output, "%-70s", ttrace->entry_str);
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1528
  	} else {
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1529
1530
1531
  		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...
1532
  	}
da3c9a448   Arnaldo Carvalho de Melo   perf trace: Simpl...
1533
1534
  	if (sc->fmt == NULL) {
  signed_print:
2c82c3ad5   Chang Hyun Park   perf trace: Fix m...
1535
  		fprintf(trace->output, ") = %ld", ret);
11c8e39f5   Arnaldo Carvalho de Melo   perf trace: Infra...
1536
  	} else if (ret < 0 && (sc->fmt->errmsg || sc->fmt->errpid)) {
942a91ed3   Masami Hiramatsu   perf trace: Use s...
1537
  		char bf[STRERR_BUFSIZE];
c8b5f2c96   Arnaldo Carvalho de Melo   tools: Introduce ...
1538
  		const char *emsg = str_error_r(-ret, bf, sizeof(bf)),
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1539
  			   *e = audit_errno_to_name(-ret);
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1540
  		fprintf(trace->output, ") = -1 %s %s", e, emsg);
da3c9a448   Arnaldo Carvalho de Melo   perf trace: Simpl...
1541
  	} else if (ret == 0 && sc->fmt->timeout)
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1542
  		fprintf(trace->output, ") = 0 Timeout");
04b34729e   Arnaldo Carvalho de Melo   perf trace: Allow...
1543
  	else if (sc->fmt->hexret)
2c82c3ad5   Chang Hyun Park   perf trace: Fix m...
1544
  		fprintf(trace->output, ") = %#lx", ret);
11c8e39f5   Arnaldo Carvalho de Melo   perf trace: Infra...
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
  	else if (sc->fmt->errpid) {
  		struct thread *child = machine__find_thread(trace->host, ret, ret);
  
  		if (child != NULL) {
  			fprintf(trace->output, ") = %ld", ret);
  			if (child->comm_set)
  				fprintf(trace->output, " (%s)", thread__comm_str(child));
  			thread__put(child);
  		}
  	} else
da3c9a448   Arnaldo Carvalho de Melo   perf trace: Simpl...
1555
  		goto signed_print;
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1556

c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1557
1558
  	fputc('
  ', trace->output);
566a08859   Milian Wolff   perf trace: Add s...
1559

5cf9c84e2   Arnaldo Carvalho de Melo   perf trace: Intro...
1560
1561
1562
1563
1564
  	if (callchain_ret > 0)
  		trace__fprintf_callchain(trace, sample);
  	else if (callchain_ret < 0)
  		pr_err("Problem processing %s callchain, skipping...
  ", perf_evsel__name(evsel));
ae9ed0357   Arnaldo Carvalho de Melo   perf trace: Add d...
1565
  out:
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
1566
  	ttrace->entry_pending = false;
b91fc39f4   Arnaldo Carvalho de Melo   perf machine: Pro...
1567
1568
1569
1570
  	err = 0;
  out_put:
  	thread__put(thread);
  	return err;
ba3d7deee   Arnaldo Carvalho de Melo   perf trace: Use e...
1571
  }
c522739d7   Arnaldo Carvalho de Melo   perf trace: Use v...
1572
  static int trace__vfs_getname(struct trace *trace, struct perf_evsel *evsel,
0c82adcf1   Stanislav Fomichev   perf trace: Add p...
1573
  			      union perf_event *event __maybe_unused,
c522739d7   Arnaldo Carvalho de Melo   perf trace: Use v...
1574
1575
  			      struct perf_sample *sample)
  {
f994592d9   Arnaldo Carvalho de Melo   perf trace: Deref...
1576
1577
1578
1579
1580
  	struct thread *thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
  	struct thread_trace *ttrace;
  	size_t filename_len, entry_str_len, to_move;
  	ssize_t remaining_space;
  	char *pos;
7f4f80013   Arnaldo Carvalho de Melo   perf trace: Move ...
1581
  	const char *filename = perf_evsel__rawptr(evsel, sample, "pathname");
f994592d9   Arnaldo Carvalho de Melo   perf trace: Deref...
1582
1583
1584
1585
1586
1587
1588
  
  	if (!thread)
  		goto out;
  
  	ttrace = thread__priv(thread);
  	if (!ttrace)
  		goto out;
7f4f80013   Arnaldo Carvalho de Melo   perf trace: Move ...
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
  	filename_len = strlen(filename);
  
  	if (ttrace->filename.namelen < filename_len) {
  		char *f = realloc(ttrace->filename.name, filename_len + 1);
  
  		if (f == NULL)
  				goto out;
  
  		ttrace->filename.namelen = filename_len;
  		ttrace->filename.name = f;
  	}
  
  	strcpy(ttrace->filename.name, filename);
  	ttrace->filename.pending_open = true;
f994592d9   Arnaldo Carvalho de Melo   perf trace: Deref...
1603
1604
1605
1606
1607
1608
1609
  	if (!ttrace->filename.ptr)
  		goto out;
  
  	entry_str_len = strlen(ttrace->entry_str);
  	remaining_space = trace__entry_str_size - entry_str_len - 1; /* \0 */
  	if (remaining_space <= 0)
  		goto out;
f994592d9   Arnaldo Carvalho de Melo   perf trace: Deref...
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
  	if (filename_len > (size_t)remaining_space) {
  		filename += filename_len - remaining_space;
  		filename_len = remaining_space;
  	}
  
  	to_move = entry_str_len - ttrace->filename.entry_str_pos + 1; /* \0 */
  	pos = ttrace->entry_str + ttrace->filename.entry_str_pos;
  	memmove(pos + filename_len, pos, to_move);
  	memcpy(pos, filename, filename_len);
  
  	ttrace->filename.ptr = 0;
  	ttrace->filename.entry_str_pos = 0;
  out:
c522739d7   Arnaldo Carvalho de Melo   perf trace: Use v...
1623
1624
  	return 0;
  }
1302d88e6   Arnaldo Carvalho de Melo   perf trace: Use s...
1625
  static int trace__sched_stat_runtime(struct trace *trace, struct perf_evsel *evsel,
0c82adcf1   Stanislav Fomichev   perf trace: Add p...
1626
  				     union perf_event *event __maybe_unused,
1302d88e6   Arnaldo Carvalho de Melo   perf trace: Use s...
1627
1628
1629
1630
  				     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...
1631
  	struct thread *thread = machine__findnew_thread(trace->host,
314add6b1   Adrian Hunter   perf tools: chang...
1632
1633
  							sample->pid,
  							sample->tid);
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1634
  	struct thread_trace *ttrace = thread__trace(thread, trace->output);
1302d88e6   Arnaldo Carvalho de Melo   perf trace: Use s...
1635
1636
1637
1638
1639
1640
  
  	if (ttrace == NULL)
  		goto out_dump;
  
  	ttrace->runtime_ms += runtime_ms;
  	trace->runtime_ms += runtime_ms;
b91fc39f4   Arnaldo Carvalho de Melo   perf machine: Pro...
1641
  	thread__put(thread);
1302d88e6   Arnaldo Carvalho de Melo   perf trace: Use s...
1642
1643
1644
  	return 0;
  
  out_dump:
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
1645
1646
  	fprintf(trace->output, "%s: comm=%s,pid=%u,runtime=%" PRIu64 ",vruntime=%" PRIu64 ")
  ",
1302d88e6   Arnaldo Carvalho de Melo   perf trace: Use s...
1647
1648
1649
1650
1651
  	       evsel->name,
  	       perf_evsel__strval(evsel, sample, "comm"),
  	       (pid_t)perf_evsel__intval(evsel, sample, "pid"),
  	       runtime,
  	       perf_evsel__intval(evsel, sample, "vruntime"));
b91fc39f4   Arnaldo Carvalho de Melo   perf machine: Pro...
1652
  	thread__put(thread);
1302d88e6   Arnaldo Carvalho de Melo   perf trace: Use s...
1653
1654
  	return 0;
  }
1d6c9407d   Wang Nan   perf trace: Print...
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
  static void bpf_output__printer(enum binary_printer_ops op,
  				unsigned int val, void *extra)
  {
  	FILE *output = extra;
  	unsigned char ch = (unsigned char)val;
  
  	switch (op) {
  	case BINARY_PRINT_CHAR_DATA:
  		fprintf(output, "%c", isprint(ch) ? ch : '.');
  		break;
  	case BINARY_PRINT_DATA_BEGIN:
  	case BINARY_PRINT_LINE_BEGIN:
  	case BINARY_PRINT_ADDR:
  	case BINARY_PRINT_NUM_DATA:
  	case BINARY_PRINT_NUM_PAD:
  	case BINARY_PRINT_SEP:
  	case BINARY_PRINT_CHAR_PAD:
  	case BINARY_PRINT_LINE_END:
  	case BINARY_PRINT_DATA_END:
  	default:
  		break;
  	}
  }
  
  static void bpf_output__fprintf(struct trace *trace,
  				struct perf_sample *sample)
  {
  	print_binary(sample->raw_data, sample->raw_size, 8,
  		     bpf_output__printer, trace->output);
  }
14a052df1   Arnaldo Carvalho de Melo   perf trace: Allow...
1685
1686
1687
1688
  static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
  				union perf_event *event __maybe_unused,
  				struct perf_sample *sample)
  {
7ad356159   Arnaldo Carvalho de Melo   perf trace: Make ...
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
  	int callchain_ret = 0;
  
  	if (sample->callchain) {
  		callchain_ret = trace__resolve_callchain(trace, evsel, sample, &callchain_cursor);
  		if (callchain_ret == 0) {
  			if (callchain_cursor.nr < trace->min_stack)
  				goto out;
  			callchain_ret = 1;
  		}
  	}
14a052df1   Arnaldo Carvalho de Melo   perf trace: Allow...
1699
1700
  	trace__printf_interrupted_entry(trace, sample);
  	trace__fprintf_tstamp(trace, sample->time, trace->output);
0808921a1   Arnaldo Carvalho de Melo   perf trace: Only ...
1701
1702
1703
1704
1705
  
  	if (trace->trace_syscalls)
  		fprintf(trace->output, "(         ): ");
  
  	fprintf(trace->output, "%s:", evsel->name);
14a052df1   Arnaldo Carvalho de Melo   perf trace: Allow...
1706

1d6c9407d   Wang Nan   perf trace: Print...
1707
1708
1709
  	if (perf_evsel__is_bpf_output(evsel)) {
  		bpf_output__fprintf(trace, sample);
  	} else if (evsel->tp_format) {
14a052df1   Arnaldo Carvalho de Melo   perf trace: Allow...
1710
1711
1712
1713
1714
1715
1716
  		event_format__fprintf(evsel->tp_format, sample->cpu,
  				      sample->raw_data, sample->raw_size,
  				      trace->output);
  	}
  
  	fprintf(trace->output, ")
  ");
202ff9684   Arnaldo Carvalho de Melo   perf trace: Suppo...
1717

7ad356159   Arnaldo Carvalho de Melo   perf trace: Make ...
1718
1719
1720
1721
1722
1723
  	if (callchain_ret > 0)
  		trace__fprintf_callchain(trace, sample);
  	else if (callchain_ret < 0)
  		pr_err("Problem processing %s callchain, skipping...
  ", perf_evsel__name(evsel));
  out:
14a052df1   Arnaldo Carvalho de Melo   perf trace: Allow...
1724
1725
  	return 0;
  }
598d02c5a   Stanislav Fomichev   perf trace: Add s...
1726
1727
1728
1729
1730
1731
1732
1733
1734
  static void print_location(FILE *f, struct perf_sample *sample,
  			   struct addr_location *al,
  			   bool print_dso, bool print_sym)
  {
  
  	if ((verbose || print_dso) && al->map)
  		fprintf(f, "%s@", al->map->dso->long_name);
  
  	if ((verbose || print_sym) && al->sym)
4414a3c51   Arnaldo Carvalho de Melo   perf trace: Fix b...
1735
  		fprintf(f, "%s+0x%" PRIx64, al->sym->name,
598d02c5a   Stanislav Fomichev   perf trace: Add s...
1736
1737
  			al->addr - al->sym->start);
  	else if (al->map)
4414a3c51   Arnaldo Carvalho de Melo   perf trace: Fix b...
1738
  		fprintf(f, "0x%" PRIx64, al->addr);
598d02c5a   Stanislav Fomichev   perf trace: Add s...
1739
  	else
4414a3c51   Arnaldo Carvalho de Melo   perf trace: Fix b...
1740
  		fprintf(f, "0x%" PRIx64, sample->addr);
598d02c5a   Stanislav Fomichev   perf trace: Add s...
1741
1742
1743
1744
  }
  
  static int trace__pgfault(struct trace *trace,
  			  struct perf_evsel *evsel,
473398a21   Arnaldo Carvalho de Melo   perf tools: Add c...
1745
  			  union perf_event *event __maybe_unused,
598d02c5a   Stanislav Fomichev   perf trace: Add s...
1746
1747
1748
  			  struct perf_sample *sample)
  {
  	struct thread *thread;
598d02c5a   Stanislav Fomichev   perf trace: Add s...
1749
1750
  	struct addr_location al;
  	char map_type = 'd';
a2ea67d7b   Stanislav Fomichev   perf trace: Add p...
1751
  	struct thread_trace *ttrace;
b91fc39f4   Arnaldo Carvalho de Melo   perf machine: Pro...
1752
  	int err = -1;
1df542904   Arnaldo Carvalho de Melo   perf trace: Make ...
1753
  	int callchain_ret = 0;
598d02c5a   Stanislav Fomichev   perf trace: Add s...
1754
1755
  
  	thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
1df542904   Arnaldo Carvalho de Melo   perf trace: Make ...
1756
1757
1758
1759
1760
1761
1762
1763
1764
  
  	if (sample->callchain) {
  		callchain_ret = trace__resolve_callchain(trace, evsel, sample, &callchain_cursor);
  		if (callchain_ret == 0) {
  			if (callchain_cursor.nr < trace->min_stack)
  				goto out_put;
  			callchain_ret = 1;
  		}
  	}
a2ea67d7b   Stanislav Fomichev   perf trace: Add p...
1765
1766
  	ttrace = thread__trace(thread, trace->output);
  	if (ttrace == NULL)
b91fc39f4   Arnaldo Carvalho de Melo   perf machine: Pro...
1767
  		goto out_put;
a2ea67d7b   Stanislav Fomichev   perf trace: Add p...
1768
1769
1770
1771
1772
1773
1774
  
  	if (evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ)
  		ttrace->pfmaj++;
  	else
  		ttrace->pfmin++;
  
  	if (trace->summary_only)
b91fc39f4   Arnaldo Carvalho de Melo   perf machine: Pro...
1775
  		goto out;
598d02c5a   Stanislav Fomichev   perf trace: Add s...
1776

473398a21   Arnaldo Carvalho de Melo   perf tools: Add c...
1777
  	thread__find_addr_location(thread, sample->cpumode, MAP__FUNCTION,
598d02c5a   Stanislav Fomichev   perf trace: Add s...
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
  			      sample->ip, &al);
  
  	trace__fprintf_entry_head(trace, thread, 0, sample->time, trace->output);
  
  	fprintf(trace->output, "%sfault [",
  		evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ?
  		"maj" : "min");
  
  	print_location(trace->output, sample, &al, false, true);
  
  	fprintf(trace->output, "] => ");
473398a21   Arnaldo Carvalho de Melo   perf tools: Add c...
1789
  	thread__find_addr_location(thread, sample->cpumode, MAP__VARIABLE,
598d02c5a   Stanislav Fomichev   perf trace: Add s...
1790
1791
1792
  				   sample->addr, &al);
  
  	if (!al.map) {
473398a21   Arnaldo Carvalho de Melo   perf tools: Add c...
1793
  		thread__find_addr_location(thread, sample->cpumode,
598d02c5a   Stanislav Fomichev   perf trace: Add s...
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
  					   MAP__FUNCTION, sample->addr, &al);
  
  		if (al.map)
  			map_type = 'x';
  		else
  			map_type = '?';
  	}
  
  	print_location(trace->output, sample, &al, true, false);
  
  	fprintf(trace->output, " (%c%c)
  ", map_type, al.level);
0c3a6ef4e   Arnaldo Carvalho de Melo   perf trace: Make ...
1806

1df542904   Arnaldo Carvalho de Melo   perf trace: Make ...
1807
1808
1809
1810
1811
  	if (callchain_ret > 0)
  		trace__fprintf_callchain(trace, sample);
  	else if (callchain_ret < 0)
  		pr_err("Problem processing %s callchain, skipping...
  ", perf_evsel__name(evsel));
b91fc39f4   Arnaldo Carvalho de Melo   perf machine: Pro...
1812
1813
1814
1815
1816
  out:
  	err = 0;
  out_put:
  	thread__put(thread);
  	return err;
598d02c5a   Stanislav Fomichev   perf trace: Add s...
1817
  }
bdc896617   David Ahern   perf trace: Honor...
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
  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;
  }
e6001980c   Arnaldo Carvalho de Melo   perf trace: Intro...
1829
  static void trace__set_base_time(struct trace *trace,
8a07a8094   Arnaldo Carvalho de Melo   perf trace: Don't...
1830
  				 struct perf_evsel *evsel,
e6001980c   Arnaldo Carvalho de Melo   perf trace: Intro...
1831
1832
  				 struct perf_sample *sample)
  {
8a07a8094   Arnaldo Carvalho de Melo   perf trace: Don't...
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
  	/*
  	 * BPF events were not setting PERF_SAMPLE_TIME, so be more robust
  	 * and don't use sample->time unconditionally, we may end up having
  	 * some other event in the future without PERF_SAMPLE_TIME for good
  	 * reason, i.e. we may not be interested in its timestamps, just in
  	 * it taking place, picking some piece of information when it
  	 * appears in our event stream (vfs_getname comes to mind).
  	 */
  	if (trace->base_time == 0 && !trace->full_time &&
  	    (evsel->attr.sample_type & PERF_SAMPLE_TIME))
e6001980c   Arnaldo Carvalho de Melo   perf trace: Intro...
1843
1844
  		trace->base_time = sample->time;
  }
6810fc915   David Ahern   perf trace: Add o...
1845
  static int trace__process_sample(struct perf_tool *tool,
0c82adcf1   Stanislav Fomichev   perf trace: Add p...
1846
  				 union perf_event *event,
6810fc915   David Ahern   perf trace: Add o...
1847
1848
1849
1850
1851
1852
  				 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...
1853
  	tracepoint_handler handler = evsel->handler;
6810fc915   David Ahern   perf trace: Add o...
1854

bdc896617   David Ahern   perf trace: Honor...
1855
1856
  	if (skip_sample(trace, sample))
  		return 0;
e6001980c   Arnaldo Carvalho de Melo   perf trace: Intro...
1857
  	trace__set_base_time(trace, evsel, sample);
6810fc915   David Ahern   perf trace: Add o...
1858

3160565f0   David Ahern   perf trace: Fix s...
1859
1860
  	if (handler) {
  		++trace->nr_events;
0c82adcf1   Stanislav Fomichev   perf trace: Add p...
1861
  		handler(trace, evsel, event, sample);
3160565f0   David Ahern   perf trace: Fix s...
1862
  	}
6810fc915   David Ahern   perf trace: Add o...
1863
1864
1865
  
  	return err;
  }
bdc896617   David Ahern   perf trace: Honor...
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
  static int parse_target_str(struct trace *trace)
  {
  	if (trace->opts.target.pid) {
  		trace->pid_list = intlist__new(trace->opts.target.pid);
  		if (trace->pid_list == NULL) {
  			pr_err("Error parsing process id string
  ");
  			return -EINVAL;
  		}
  	}
  
  	if (trace->opts.target.tid) {
  		trace->tid_list = intlist__new(trace->opts.target.tid);
  		if (trace->tid_list == NULL) {
  			pr_err("Error parsing thread id string
  ");
  			return -EINVAL;
  		}
  	}
  
  	return 0;
  }
1e28fe0a4   Stanislav Fomichev   perf trace: Add p...
1888
  static int trace__record(struct trace *trace, int argc, const char **argv)
5e2485b1a   David Ahern   perf trace: Add r...
1889
1890
1891
1892
1893
1894
1895
1896
  {
  	unsigned int rec_argc, i, j;
  	const char **rec_argv;
  	const char * const record_args[] = {
  		"record",
  		"-R",
  		"-m", "1024",
  		"-c", "1",
5e2485b1a   David Ahern   perf trace: Add r...
1897
  	};
1e28fe0a4   Stanislav Fomichev   perf trace: Add p...
1898
1899
1900
1901
1902
1903
  	const char * const sc_args[] = { "-e", };
  	unsigned int sc_args_nr = ARRAY_SIZE(sc_args);
  	const char * const majpf_args[] = { "-e", "major-faults" };
  	unsigned int majpf_args_nr = ARRAY_SIZE(majpf_args);
  	const char * const minpf_args[] = { "-e", "minor-faults" };
  	unsigned int minpf_args_nr = ARRAY_SIZE(minpf_args);
9aca7f179   David Ahern   perf trace: Add s...
1904
  	/* +1 is for the event string below */
1e28fe0a4   Stanislav Fomichev   perf trace: Add p...
1905
1906
  	rec_argc = ARRAY_SIZE(record_args) + sc_args_nr + 1 +
  		majpf_args_nr + minpf_args_nr + argc;
5e2485b1a   David Ahern   perf trace: Add r...
1907
1908
1909
1910
  	rec_argv = calloc(rec_argc + 1, sizeof(char *));
  
  	if (rec_argv == NULL)
  		return -ENOMEM;
1e28fe0a4   Stanislav Fomichev   perf trace: Add p...
1911
  	j = 0;
5e2485b1a   David Ahern   perf trace: Add r...
1912
  	for (i = 0; i < ARRAY_SIZE(record_args); i++)
1e28fe0a4   Stanislav Fomichev   perf trace: Add p...
1913
  		rec_argv[j++] = record_args[i];
e281a9606   Stanislav Fomichev   perf trace: Add p...
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
  	if (trace->trace_syscalls) {
  		for (i = 0; i < sc_args_nr; i++)
  			rec_argv[j++] = sc_args[i];
  
  		/* event string may be different for older kernels - e.g., RHEL6 */
  		if (is_valid_tracepoint("raw_syscalls:sys_enter"))
  			rec_argv[j++] = "raw_syscalls:sys_enter,raw_syscalls:sys_exit";
  		else if (is_valid_tracepoint("syscalls:sys_enter"))
  			rec_argv[j++] = "syscalls:sys_enter,syscalls:sys_exit";
  		else {
  			pr_err("Neither raw_syscalls nor syscalls events exist.
  ");
  			return -1;
  		}
9aca7f179   David Ahern   perf trace: Add s...
1928
  	}
9aca7f179   David Ahern   perf trace: Add s...
1929

1e28fe0a4   Stanislav Fomichev   perf trace: Add p...
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
  	if (trace->trace_pgfaults & TRACE_PFMAJ)
  		for (i = 0; i < majpf_args_nr; i++)
  			rec_argv[j++] = majpf_args[i];
  
  	if (trace->trace_pgfaults & TRACE_PFMIN)
  		for (i = 0; i < minpf_args_nr; i++)
  			rec_argv[j++] = minpf_args[i];
  
  	for (i = 0; i < (unsigned int)argc; i++)
  		rec_argv[j++] = argv[i];
5e2485b1a   David Ahern   perf trace: Add r...
1940

1e28fe0a4   Stanislav Fomichev   perf trace: Add p...
1941
  	return cmd_record(j, rec_argv, NULL);
5e2485b1a   David Ahern   perf trace: Add r...
1942
  }
bf2575c12   David Ahern   perf trace: Add s...
1943
  static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp);
08c987763   Arnaldo Carvalho de Melo   perf trace: Remem...
1944
  static bool perf_evlist__add_vfs_getname(struct perf_evlist *evlist)
c522739d7   Arnaldo Carvalho de Melo   perf trace: Use v...
1945
  {
ef503831d   Arnaldo Carvalho de Melo   perf evsel: Remov...
1946
  	struct perf_evsel *evsel = perf_evsel__newtp("probe", "vfs_getname");
8dd2a1317   Jiri Olsa   perf evsel: Propa...
1947
1948
  
  	if (IS_ERR(evsel))
08c987763   Arnaldo Carvalho de Melo   perf trace: Remem...
1949
  		return false;
c522739d7   Arnaldo Carvalho de Melo   perf trace: Use v...
1950
1951
1952
  
  	if (perf_evsel__field(evsel, "pathname") == NULL) {
  		perf_evsel__delete(evsel);
08c987763   Arnaldo Carvalho de Melo   perf trace: Remem...
1953
  		return false;
c522739d7   Arnaldo Carvalho de Melo   perf trace: Use v...
1954
  	}
744a97194   Arnaldo Carvalho de Melo   perf evsel: Ditch...
1955
  	evsel->handler = trace__vfs_getname;
c522739d7   Arnaldo Carvalho de Melo   perf trace: Use v...
1956
  	perf_evlist__add(evlist, evsel);
08c987763   Arnaldo Carvalho de Melo   perf trace: Remem...
1957
  	return true;
c522739d7   Arnaldo Carvalho de Melo   perf trace: Use v...
1958
  }
0ae537cb3   Arnaldo Carvalho de Melo   perf trace: Extra...
1959
  static struct perf_evsel *perf_evsel__new_pgfault(u64 config)
598d02c5a   Stanislav Fomichev   perf trace: Add s...
1960
1961
1962
1963
1964
  {
  	struct perf_evsel *evsel;
  	struct perf_event_attr attr = {
  		.type = PERF_TYPE_SOFTWARE,
  		.mmap_data = 1,
598d02c5a   Stanislav Fomichev   perf trace: Add s...
1965
1966
1967
  	};
  
  	attr.config = config;
0524798cc   Arnaldo Carvalho de Melo   perf tools: Fix b...
1968
  	attr.sample_period = 1;
598d02c5a   Stanislav Fomichev   perf trace: Add s...
1969
1970
1971
1972
  
  	event_attr_init(&attr);
  
  	evsel = perf_evsel__new(&attr);
0ae537cb3   Arnaldo Carvalho de Melo   perf trace: Extra...
1973
1974
  	if (evsel)
  		evsel->handler = trace__pgfault;
598d02c5a   Stanislav Fomichev   perf trace: Add s...
1975

0ae537cb3   Arnaldo Carvalho de Melo   perf trace: Extra...
1976
  	return evsel;
598d02c5a   Stanislav Fomichev   perf trace: Add s...
1977
  }
ddbb1b131   Arnaldo Carvalho de Melo   perf trace: Separ...
1978
1979
1980
1981
  static void trace__handle_event(struct trace *trace, union perf_event *event, struct perf_sample *sample)
  {
  	const u32 type = event->header.type;
  	struct perf_evsel *evsel;
ddbb1b131   Arnaldo Carvalho de Melo   perf trace: Separ...
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
  	if (type != PERF_RECORD_SAMPLE) {
  		trace__process_event(trace, trace->host, event, sample);
  		return;
  	}
  
  	evsel = perf_evlist__id2evsel(trace->evlist, sample->id);
  	if (evsel == NULL) {
  		fprintf(trace->output, "Unknown tp ID %" PRIu64 ", skipping...
  ", sample->id);
  		return;
  	}
e6001980c   Arnaldo Carvalho de Melo   perf trace: Intro...
1993
  	trace__set_base_time(trace, evsel, sample);
ddbb1b131   Arnaldo Carvalho de Melo   perf trace: Separ...
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
  	if (evsel->attr.type == PERF_TYPE_TRACEPOINT &&
  	    sample->raw_data == NULL) {
  		fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...
  ",
  		       perf_evsel__name(evsel), sample->tid,
  		       sample->cpu, sample->raw_size);
  	} else {
  		tracepoint_handler handler = evsel->handler;
  		handler(trace, evsel, event, sample);
  	}
  }
c27366f0f   Arnaldo Carvalho de Melo   perf trace: Remem...
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
  static int trace__add_syscall_newtp(struct trace *trace)
  {
  	int ret = -1;
  	struct perf_evlist *evlist = trace->evlist;
  	struct perf_evsel *sys_enter, *sys_exit;
  
  	sys_enter = perf_evsel__syscall_newtp("sys_enter", trace__sys_enter);
  	if (sys_enter == NULL)
  		goto out;
  
  	if (perf_evsel__init_sc_tp_ptr_field(sys_enter, args))
  		goto out_delete_sys_enter;
  
  	sys_exit = perf_evsel__syscall_newtp("sys_exit", trace__sys_exit);
  	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);
2ddd5c049   Arnaldo Carvalho de Melo   perf tools: Ditch...
2027
  	if (callchain_param.enabled && !trace->kernel_syscallchains) {
44621819d   Arnaldo Carvalho de Melo   perf trace: Exclu...
2028
2029
2030
2031
2032
2033
2034
  		/*
  		 * We're interested only in the user space callchain
  		 * leading to the syscall, allow overriding that for
  		 * debugging reasons using --kernel_syscall_callchains
  		 */
  		sys_exit->attr.exclude_callchain_kernel = 1;
  	}
8b3ce7576   Arnaldo Carvalho de Melo   perf trace: Store...
2035
2036
  	trace->syscalls.events.sys_enter = sys_enter;
  	trace->syscalls.events.sys_exit  = sys_exit;
c27366f0f   Arnaldo Carvalho de Melo   perf trace: Remem...
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
  
  	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;
  }
19867b618   Arnaldo Carvalho de Melo   perf trace: Use e...
2048
2049
2050
  static int trace__set_ev_qualifier_filter(struct trace *trace)
  {
  	int err = -1;
b15d0a4c8   Mathieu Poirier   perf tools: Make ...
2051
  	struct perf_evsel *sys_exit;
19867b618   Arnaldo Carvalho de Melo   perf trace: Use e...
2052
2053
2054
2055
2056
2057
  	char *filter = asprintf_expr_inout_ints("id", !trace->not_ev_qualifier,
  						trace->ev_qualifier_ids.nr,
  						trace->ev_qualifier_ids.entries);
  
  	if (filter == NULL)
  		goto out_enomem;
3541c034d   Mathieu Poirier   perf evsel: New t...
2058
2059
  	if (!perf_evsel__append_tp_filter(trace->syscalls.events.sys_enter,
  					  filter)) {
b15d0a4c8   Mathieu Poirier   perf tools: Make ...
2060
  		sys_exit = trace->syscalls.events.sys_exit;
3541c034d   Mathieu Poirier   perf evsel: New t...
2061
  		err = perf_evsel__append_tp_filter(sys_exit, filter);
b15d0a4c8   Mathieu Poirier   perf tools: Make ...
2062
  	}
19867b618   Arnaldo Carvalho de Melo   perf trace: Use e...
2063
2064
2065
2066
2067
2068
2069
2070
  
  	free(filter);
  out:
  	return err;
  out_enomem:
  	errno = ENOMEM;
  	goto out;
  }
c27366f0f   Arnaldo Carvalho de Melo   perf trace: Remem...
2071

f15eb531d   Namhyung Kim   perf trace: Add s...
2072
  static int trace__run(struct trace *trace, int argc, const char **argv)
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2073
  {
14a052df1   Arnaldo Carvalho de Melo   perf trace: Allow...
2074
  	struct perf_evlist *evlist = trace->evlist;
0ae537cb3   Arnaldo Carvalho de Melo   perf trace: Extra...
2075
  	struct perf_evsel *evsel, *pgfault_maj = NULL, *pgfault_min = NULL;
efd5745e4   Arnaldo Carvalho de Melo   perf trace: Count...
2076
2077
  	int err = -1, i;
  	unsigned long before;
f15eb531d   Namhyung Kim   perf trace: Add s...
2078
  	const bool forks = argc > 0;
46fb3c21d   Arnaldo Carvalho de Melo   perf trace: Filte...
2079
  	bool draining = false;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2080

75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
2081
  	trace->live = true;
c27366f0f   Arnaldo Carvalho de Melo   perf trace: Remem...
2082
  	if (trace->trace_syscalls && trace__add_syscall_newtp(trace))
801c67b05   Arnaldo Carvalho de Melo   tools lib fs: Pas...
2083
  		goto out_error_raw_syscalls;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2084

e281a9606   Stanislav Fomichev   perf trace: Add p...
2085
  	if (trace->trace_syscalls)
08c987763   Arnaldo Carvalho de Melo   perf trace: Remem...
2086
  		trace->vfs_getname = perf_evlist__add_vfs_getname(evlist);
c522739d7   Arnaldo Carvalho de Melo   perf trace: Use v...
2087

0ae537cb3   Arnaldo Carvalho de Melo   perf trace: Extra...
2088
2089
2090
2091
2092
  	if ((trace->trace_pgfaults & TRACE_PFMAJ)) {
  		pgfault_maj = perf_evsel__new_pgfault(PERF_COUNT_SW_PAGE_FAULTS_MAJ);
  		if (pgfault_maj == NULL)
  			goto out_error_mem;
  		perf_evlist__add(evlist, pgfault_maj);
e2726d996   Arnaldo Carvalho de Melo   tools lib fs: Ado...
2093
  	}
598d02c5a   Stanislav Fomichev   perf trace: Add s...
2094

0ae537cb3   Arnaldo Carvalho de Melo   perf trace: Extra...
2095
2096
2097
2098
2099
2100
  	if ((trace->trace_pgfaults & TRACE_PFMIN)) {
  		pgfault_min = perf_evsel__new_pgfault(PERF_COUNT_SW_PAGE_FAULTS_MIN);
  		if (pgfault_min == NULL)
  			goto out_error_mem;
  		perf_evlist__add(evlist, pgfault_min);
  	}
598d02c5a   Stanislav Fomichev   perf trace: Add s...
2101

1302d88e6   Arnaldo Carvalho de Melo   perf trace: Use s...
2102
  	if (trace->sched &&
2cc990ba3   Arnaldo Carvalho de Melo   tools lib fs debu...
2103
2104
2105
  	    perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime",
  				   trace__sched_stat_runtime))
  		goto out_error_sched_stat_runtime;
1302d88e6   Arnaldo Carvalho de Melo   perf trace: Use s...
2106

514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2107
2108
  	err = perf_evlist__create_maps(evlist, &trace->opts.target);
  	if (err < 0) {
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
2109
2110
  		fprintf(trace->output, "Problems parsing the target to trace, check your options!
  ");
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2111
2112
  		goto out_delete_evlist;
  	}
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
2113
2114
  	err = trace__symbols_init(trace, evlist);
  	if (err < 0) {
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
2115
2116
  		fprintf(trace->output, "Problems initializing symbol libraries!
  ");
03ad9747c   Arnaldo Carvalho de Melo   perf evlist: Move...
2117
  		goto out_delete_evlist;
752fde44f   Arnaldo Carvalho de Melo   perf trace: Suppo...
2118
  	}
fde54b786   Arnaldo Carvalho de Melo   perf trace: Make ...
2119
  	perf_evlist__config(evlist, &trace->opts, NULL);
0c3a6ef4e   Arnaldo Carvalho de Melo   perf trace: Make ...
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
  	if (callchain_param.enabled) {
  		bool use_identifier = false;
  
  		if (trace->syscalls.events.sys_exit) {
  			perf_evsel__config_callchain(trace->syscalls.events.sys_exit,
  						     &trace->opts, &callchain_param);
  			use_identifier = true;
  		}
  
  		if (pgfault_maj) {
  			perf_evsel__config_callchain(pgfault_maj, &trace->opts, &callchain_param);
  			use_identifier = true;
  		}
  
  		if (pgfault_min) {
  			perf_evsel__config_callchain(pgfault_min, &trace->opts, &callchain_param);
  			use_identifier = true;
  		}
  
  		if (use_identifier) {
  		       /*
  			* Now we have evsels with different sample_ids, use
  			* PERF_SAMPLE_IDENTIFIER to map from sample to evsel
  			* from a fixed position in each ring buffer record.
  			*
  			* As of this the changeset introducing this comment, this
  			* isn't strictly needed, as the fields that can come before
  			* PERF_SAMPLE_ID are all used, but we'll probably disable
  			* some of those for things like copying the payload of
  			* pointer syscall arguments, and for vfs_getname we don't
  			* need PERF_SAMPLE_ADDR and PERF_SAMPLE_IP, so do this
  			* here as a warning we need to use PERF_SAMPLE_IDENTIFIER.
  			*/
  			perf_evlist__set_sample_bit(evlist, IDENTIFIER);
  			perf_evlist__reset_sample_bit(evlist, ID);
  		}
fde54b786   Arnaldo Carvalho de Melo   perf trace: Make ...
2156
  	}
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2157

f15eb531d   Namhyung Kim   perf trace: Add s...
2158
2159
2160
2161
  	signal(SIGCHLD, sig_handler);
  	signal(SIGINT, sig_handler);
  
  	if (forks) {
6ef73ec44   Namhyung Kim   perf evlist: Pass...
2162
  		err = perf_evlist__prepare_workload(evlist, &trace->opts.target,
735f7e0bb   Arnaldo Carvalho de Melo   perf evlist: Move...
2163
  						    argv, false, NULL);
f15eb531d   Namhyung Kim   perf trace: Add s...
2164
  		if (err < 0) {
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
2165
2166
  			fprintf(trace->output, "Couldn't run the workload!
  ");
03ad9747c   Arnaldo Carvalho de Melo   perf evlist: Move...
2167
  			goto out_delete_evlist;
f15eb531d   Namhyung Kim   perf trace: Add s...
2168
2169
  		}
  	}
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2170
  	err = perf_evlist__open(evlist);
a8f23d8f8   Arnaldo Carvalho de Melo   perf trace: Impro...
2171
2172
  	if (err < 0)
  		goto out_error_open;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2173

ba5042353   Wang Nan   perf trace: Call ...
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
  	err = bpf__apply_obj_config();
  	if (err) {
  		char errbuf[BUFSIZ];
  
  		bpf__strerror_apply_obj_config(err, errbuf, sizeof(errbuf));
  		pr_err("ERROR: Apply config to BPF failed: %s
  ",
  			 errbuf);
  		goto out_error_open;
  	}
241b057ce   Arnaldo Carvalho de Melo   perf trace: Filte...
2184
2185
2186
2187
2188
2189
  	/*
  	 * Better not use !target__has_task() here because we need to cover the
  	 * case where no threads were specified in the command line, but a
  	 * workload was, and in that case we will fill in the thread_map when
  	 * we fork the workload in perf_evlist__prepare_workload.
  	 */
f078c3852   Arnaldo Carvalho de Melo   perf trace: Intro...
2190
2191
  	if (trace->filter_pids.nr > 0)
  		err = perf_evlist__set_filter_pids(evlist, trace->filter_pids.nr, trace->filter_pids.entries);
e13798c77   Jiri Olsa   perf thread_map: ...
2192
  	else if (thread_map__pid(evlist->threads, 0) == -1)
f078c3852   Arnaldo Carvalho de Melo   perf trace: Intro...
2193
  		err = perf_evlist__set_filter_pid(evlist, getpid());
94ad89bc8   Arnaldo Carvalho de Melo   perf evlist: Make...
2194
2195
  	if (err < 0)
  		goto out_error_mem;
19867b618   Arnaldo Carvalho de Melo   perf trace: Use e...
2196
2197
2198
2199
  	if (trace->ev_qualifier_ids.nr > 0) {
  		err = trace__set_ev_qualifier_filter(trace);
  		if (err < 0)
  			goto out_errno;
19867b618   Arnaldo Carvalho de Melo   perf trace: Use e...
2200

2e5e5f876   Arnaldo Carvalho de Melo   perf trace: Do no...
2201
2202
2203
2204
  		pr_debug("event qualifier tracepoint filter: %s
  ",
  			 trace->syscalls.events.sys_exit->filter);
  	}
19867b618   Arnaldo Carvalho de Melo   perf trace: Use e...
2205

94ad89bc8   Arnaldo Carvalho de Melo   perf evlist: Make...
2206
2207
2208
  	err = perf_evlist__apply_filters(evlist, &evsel);
  	if (err < 0)
  		goto out_error_apply_filters;
241b057ce   Arnaldo Carvalho de Melo   perf trace: Filte...
2209

f885037ef   Jiri Olsa   perf trace: Honou...
2210
  	err = perf_evlist__mmap(evlist, trace->opts.mmap_pages, false);
e09b18d49   Arnaldo Carvalho de Melo   perf trace: Provi...
2211
2212
  	if (err < 0)
  		goto out_error_mmap;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2213

cb24d01d2   Arnaldo Carvalho de Melo   perf trace: Enabl...
2214
2215
  	if (!target__none(&trace->opts.target))
  		perf_evlist__enable(evlist);
f15eb531d   Namhyung Kim   perf trace: Add s...
2216
2217
  	if (forks)
  		perf_evlist__start_workload(evlist);
e13798c77   Jiri Olsa   perf thread_map: ...
2218
  	trace->multiple_threads = thread_map__pid(evlist->threads, 0) == -1 ||
42052bea1   Arnaldo Carvalho de Melo   perf trace: Print...
2219
2220
  				  evlist->threads->nr > 1 ||
  				  perf_evlist__first(evlist)->attr.inherit;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2221
  again:
efd5745e4   Arnaldo Carvalho de Melo   perf trace: Count...
2222
  	before = trace->nr_events;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2223
2224
2225
2226
2227
  
  	for (i = 0; i < evlist->nr_mmaps; i++) {
  		union perf_event *event;
  
  		while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2228
  			struct perf_sample sample;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2229

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

514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2232
2233
  			err = perf_evlist__parse_sample(evlist, event, &sample);
  			if (err) {
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
2234
2235
  				fprintf(trace->output, "Can't parse sample, err = %d, skipping...
  ", err);
8e50d384c   Zhouyi Zhou   perf tools: Fixup...
2236
  				goto next_event;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2237
  			}
ddbb1b131   Arnaldo Carvalho de Melo   perf trace: Separ...
2238
  			trace__handle_event(trace, event, &sample);
8e50d384c   Zhouyi Zhou   perf tools: Fixup...
2239
2240
  next_event:
  			perf_evlist__mmap_consume(evlist, i);
20c5f10eb   Arnaldo Carvalho de Melo   perf trace: Check...
2241

ba209f856   Arnaldo Carvalho de Melo   perf trace: Impro...
2242
2243
  			if (interrupted)
  				goto out_disable;
02ac5421d   Arnaldo Carvalho de Melo   perf trace: Disab...
2244
2245
2246
2247
2248
  
  			if (done && !draining) {
  				perf_evlist__disable(evlist);
  				draining = true;
  			}
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2249
2250
  		}
  	}
efd5745e4   Arnaldo Carvalho de Melo   perf trace: Count...
2251
  	if (trace->nr_events == before) {
ba209f856   Arnaldo Carvalho de Melo   perf trace: Impro...
2252
  		int timeout = done ? 100 : -1;
f15eb531d   Namhyung Kim   perf trace: Add s...
2253

46fb3c21d   Arnaldo Carvalho de Melo   perf trace: Filte...
2254
2255
2256
  		if (!draining && perf_evlist__poll(evlist, timeout) > 0) {
  			if (perf_evlist__filter_pollfd(evlist, POLLERR | POLLHUP) == 0)
  				draining = true;
ba209f856   Arnaldo Carvalho de Melo   perf trace: Impro...
2257
  			goto again;
46fb3c21d   Arnaldo Carvalho de Melo   perf trace: Filte...
2258
  		}
ba209f856   Arnaldo Carvalho de Melo   perf trace: Impro...
2259
2260
  	} else {
  		goto again;
f15eb531d   Namhyung Kim   perf trace: Add s...
2261
  	}
ba209f856   Arnaldo Carvalho de Melo   perf trace: Impro...
2262
  out_disable:
f3b623b84   Arnaldo Carvalho de Melo   perf tools: Refer...
2263
  	thread__zput(trace->current);
ba209f856   Arnaldo Carvalho de Melo   perf trace: Impro...
2264
  	perf_evlist__disable(evlist);
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2265

c522739d7   Arnaldo Carvalho de Melo   perf trace: Use v...
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
  	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...
2281

514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2282
2283
  out_delete_evlist:
  	perf_evlist__delete(evlist);
14a052df1   Arnaldo Carvalho de Melo   perf trace: Allow...
2284
  	trace->evlist = NULL;
75b757ca9   Arnaldo Carvalho de Melo   perf trace: Show ...
2285
  	trace->live = false;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2286
  	return err;
6ef068cb8   Arnaldo Carvalho de Melo   perf evlist: Intr...
2287
2288
  {
  	char errbuf[BUFSIZ];
a8f23d8f8   Arnaldo Carvalho de Melo   perf trace: Impro...
2289

2cc990ba3   Arnaldo Carvalho de Melo   tools lib fs debu...
2290
  out_error_sched_stat_runtime:
988bdb319   Jiri Olsa   tools lib api fs:...
2291
  	tracing_path__strerror_open_tp(errno, errbuf, sizeof(errbuf), "sched", "sched_stat_runtime");
2cc990ba3   Arnaldo Carvalho de Melo   tools lib fs debu...
2292
  	goto out_error;
801c67b05   Arnaldo Carvalho de Melo   tools lib fs: Pas...
2293
  out_error_raw_syscalls:
988bdb319   Jiri Olsa   tools lib api fs:...
2294
  	tracing_path__strerror_open_tp(errno, errbuf, sizeof(errbuf), "raw_syscalls", "sys_(enter|exit)");
a8f23d8f8   Arnaldo Carvalho de Melo   perf trace: Impro...
2295
  	goto out_error;
e09b18d49   Arnaldo Carvalho de Melo   perf trace: Provi...
2296
2297
2298
  out_error_mmap:
  	perf_evlist__strerror_mmap(evlist, errno, errbuf, sizeof(errbuf));
  	goto out_error;
a8f23d8f8   Arnaldo Carvalho de Melo   perf trace: Impro...
2299
2300
2301
2302
  out_error_open:
  	perf_evlist__strerror_open(evlist, errno, errbuf, sizeof(errbuf));
  
  out_error:
6ef068cb8   Arnaldo Carvalho de Melo   perf evlist: Intr...
2303
2304
  	fprintf(trace->output, "%s
  ", errbuf);
87f918685   Ramkumar Ramachandra   perf trace: Impro...
2305
  	goto out_delete_evlist;
94ad89bc8   Arnaldo Carvalho de Melo   perf evlist: Make...
2306
2307
2308
2309
2310
2311
  
  out_error_apply_filters:
  	fprintf(trace->output,
  		"Failed to set filter \"%s\" on event %s with %d (%s)
  ",
  		evsel->filter, perf_evsel__name(evsel), errno,
c8b5f2c96   Arnaldo Carvalho de Melo   tools: Introduce ...
2312
  		str_error_r(errno, errbuf, sizeof(errbuf)));
94ad89bc8   Arnaldo Carvalho de Melo   perf evlist: Make...
2313
  	goto out_delete_evlist;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2314
  }
5ed08dae9   Arnaldo Carvalho de Melo   perf trace: Fix e...
2315
2316
2317
2318
  out_error_mem:
  	fprintf(trace->output, "Not enough memory to run!
  ");
  	goto out_delete_evlist;
19867b618   Arnaldo Carvalho de Melo   perf trace: Use e...
2319
2320
2321
2322
2323
  
  out_errno:
  	fprintf(trace->output, "errno=%d,%s
  ", errno, strerror(errno));
  	goto out_delete_evlist;
a8f23d8f8   Arnaldo Carvalho de Melo   perf trace: Impro...
2324
  }
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2325

6810fc915   David Ahern   perf trace: Add o...
2326
2327
2328
  static int trace__replay(struct trace *trace)
  {
  	const struct perf_evsel_str_handler handlers[] = {
c522739d7   Arnaldo Carvalho de Melo   perf trace: Use v...
2329
  		{ "probe:vfs_getname",	     trace__vfs_getname, },
6810fc915   David Ahern   perf trace: Add o...
2330
  	};
f5fc14124   Jiri Olsa   perf tools: Add d...
2331
2332
2333
  	struct perf_data_file file = {
  		.path  = input_name,
  		.mode  = PERF_DATA_MODE_READ,
e366a6d89   Yunlong Song   perf trace: Suppo...
2334
  		.force = trace->force,
f5fc14124   Jiri Olsa   perf tools: Add d...
2335
  	};
6810fc915   David Ahern   perf trace: Add o...
2336
  	struct perf_session *session;
003824e8c   Namhyung Kim   perf trace: Fix s...
2337
  	struct perf_evsel *evsel;
6810fc915   David Ahern   perf trace: Add o...
2338
2339
2340
2341
  	int err = -1;
  
  	trace->tool.sample	  = trace__process_sample;
  	trace->tool.mmap	  = perf_event__process_mmap;
384c671e3   David Ahern   perf trace: Add m...
2342
  	trace->tool.mmap2	  = perf_event__process_mmap2;
6810fc915   David Ahern   perf trace: Add o...
2343
2344
2345
2346
2347
2348
  	trace->tool.comm	  = perf_event__process_comm;
  	trace->tool.exit	  = perf_event__process_exit;
  	trace->tool.fork	  = perf_event__process_fork;
  	trace->tool.attr	  = perf_event__process_attr;
  	trace->tool.tracing_data = perf_event__process_tracing_data;
  	trace->tool.build_id	  = perf_event__process_build_id;
0a8cb85c2   Jiri Olsa   perf tools: Renam...
2349
  	trace->tool.ordered_events = true;
6810fc915   David Ahern   perf trace: Add o...
2350
2351
2352
2353
  	trace->tool.ordering_requires_timestamps = true;
  
  	/* add tid to output */
  	trace->multiple_threads = true;
f5fc14124   Jiri Olsa   perf tools: Add d...
2354
  	session = perf_session__new(&file, false, &trace->tool);
6810fc915   David Ahern   perf trace: Add o...
2355
  	if (session == NULL)
52e028349   Taeung Song   perf tools: Modif...
2356
  		return -1;
6810fc915   David Ahern   perf trace: Add o...
2357

0a7e6d1b6   Namhyung Kim   perf tools: Check...
2358
  	if (symbol__init(&session->header.env) < 0)
cb2ffae24   Namhyung Kim   perf trace: Move ...
2359
  		goto out;
8fb598e5a   David Ahern   perf trace: Fix c...
2360
  	trace->host = &session->machines.host;
6810fc915   David Ahern   perf trace: Add o...
2361
2362
2363
  	err = perf_session__set_tracepoints_handlers(session, handlers);
  	if (err)
  		goto out;
003824e8c   Namhyung Kim   perf trace: Fix s...
2364
2365
  	evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
  						     "raw_syscalls:sys_enter");
9aca7f179   David Ahern   perf trace: Add s...
2366
2367
2368
2369
  	/* 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...
2370

e281a9606   Stanislav Fomichev   perf trace: Add p...
2371
2372
2373
  	if (evsel &&
  	    (perf_evsel__init_syscall_tp(evsel, trace__sys_enter) < 0 ||
  	    perf_evsel__init_sc_tp_ptr_field(evsel, args))) {
003824e8c   Namhyung Kim   perf trace: Fix s...
2374
2375
2376
2377
2378
2379
2380
  		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...
2381
2382
2383
  	if (evsel == NULL)
  		evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
  							     "syscalls:sys_exit");
e281a9606   Stanislav Fomichev   perf trace: Add p...
2384
2385
2386
  	if (evsel &&
  	    (perf_evsel__init_syscall_tp(evsel, trace__sys_exit) < 0 ||
  	    perf_evsel__init_sc_tp_uint_field(evsel, ret))) {
003824e8c   Namhyung Kim   perf trace: Fix s...
2387
2388
  		pr_err("Error during initialize raw_syscalls:sys_exit event
  ");
6810fc915   David Ahern   perf trace: Add o...
2389
2390
  		goto out;
  	}
e5cadb93d   Arnaldo Carvalho de Melo   perf evlist: Rena...
2391
  	evlist__for_each_entry(session->evlist, evsel) {
1e28fe0a4   Stanislav Fomichev   perf trace: Add p...
2392
2393
2394
2395
2396
2397
  		if (evsel->attr.type == PERF_TYPE_SOFTWARE &&
  		    (evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ||
  		     evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MIN ||
  		     evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS))
  			evsel->handler = trace__pgfault;
  	}
bdc896617   David Ahern   perf trace: Honor...
2398
2399
2400
  	err = parse_target_str(trace);
  	if (err != 0)
  		goto out;
6810fc915   David Ahern   perf trace: Add o...
2401
  	setup_pager();
b7b61cbeb   Arnaldo Carvalho de Melo   perf ordered_even...
2402
  	err = perf_session__process_events(session);
6810fc915   David Ahern   perf trace: Add o...
2403
2404
  	if (err)
  		pr_err("Failed to process events, error %d", err);
bf2575c12   David Ahern   perf trace: Add s...
2405
2406
  	else if (trace->summary)
  		trace__fprintf_thread_summary(trace, trace->output);
6810fc915   David Ahern   perf trace: Add o...
2407
2408
2409
2410
2411
  out:
  	perf_session__delete(session);
  
  	return err;
  }
1302d88e6   Arnaldo Carvalho de Melo   perf trace: Use s...
2412
2413
2414
  static size_t trace__fprintf_threads_header(FILE *fp)
  {
  	size_t printed;
99ff71505   Pekka Enberg   perf trace: Simpl...
2415
2416
2417
2418
  	printed  = fprintf(fp, "
   Summary of events:
  
  ");
bf2575c12   David Ahern   perf trace: Add s...
2419
2420
2421
  
  	return printed;
  }
b535d523d   Arnaldo Carvalho de Melo   perf trace: Sort ...
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
  DEFINE_RESORT_RB(syscall_stats, a->msecs > b->msecs,
  	struct stats 	*stats;
  	double		msecs;
  	int		syscall;
  )
  {
  	struct int_node *source = rb_entry(nd, struct int_node, rb_node);
  	struct stats *stats = source->priv;
  
  	entry->syscall = source->i;
  	entry->stats   = stats;
  	entry->msecs   = stats ? (u64)stats->n * (avg_stats(stats) / NSEC_PER_MSEC) : 0;
  }
bf2575c12   David Ahern   perf trace: Add s...
2435
2436
2437
  static size_t thread__dump_stats(struct thread_trace *ttrace,
  				 struct trace *trace, FILE *fp)
  {
bf2575c12   David Ahern   perf trace: Add s...
2438
2439
  	size_t printed = 0;
  	struct syscall *sc;
b535d523d   Arnaldo Carvalho de Melo   perf trace: Sort ...
2440
2441
  	struct rb_node *nd;
  	DECLARE_RESORT_RB_INTLIST(syscall_stats, ttrace->syscall_stats);
bf2575c12   David Ahern   perf trace: Add s...
2442

b535d523d   Arnaldo Carvalho de Melo   perf trace: Sort ...
2443
  	if (syscall_stats == NULL)
bf2575c12   David Ahern   perf trace: Add s...
2444
2445
2446
2447
  		return 0;
  
  	printed += fprintf(fp, "
  ");
834fd46dd   Milian Wolff   perf trace: Add t...
2448
2449
2450
2451
2452
2453
  	printed += fprintf(fp, "   syscall            calls    total       min       avg       max      stddev
  ");
  	printed += fprintf(fp, "                               (msec)    (msec)    (msec)    (msec)        (%%)
  ");
  	printed += fprintf(fp, "   --------------- -------- --------- --------- --------- ---------     ------
  ");
99ff71505   Pekka Enberg   perf trace: Simpl...
2454

98a91837d   Arnaldo Carvalho de Melo   perf rb_resort: R...
2455
  	resort_rb__for_each_entry(nd, syscall_stats) {
b535d523d   Arnaldo Carvalho de Melo   perf trace: Sort ...
2456
  		struct stats *stats = syscall_stats_entry->stats;
bf2575c12   David Ahern   perf trace: Add s...
2457
2458
2459
2460
2461
2462
2463
2464
2465
  		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;
b535d523d   Arnaldo Carvalho de Melo   perf trace: Sort ...
2466
  			sc = &trace->syscalls.table[syscall_stats_entry->syscall];
99ff71505   Pekka Enberg   perf trace: Simpl...
2467
  			printed += fprintf(fp, "   %-15s", sc->name);
834fd46dd   Milian Wolff   perf trace: Add t...
2468
  			printed += fprintf(fp, " %8" PRIu64 " %9.3f %9.3f %9.3f",
b535d523d   Arnaldo Carvalho de Melo   perf trace: Sort ...
2469
  					   n, syscall_stats_entry->msecs, min, avg);
27a778b51   Pekka Enberg   perf trace: Tweak...
2470
2471
  			printed += fprintf(fp, " %9.3f %9.2f%%
  ", max, pct);
bf2575c12   David Ahern   perf trace: Add s...
2472
  		}
bf2575c12   David Ahern   perf trace: Add s...
2473
  	}
b535d523d   Arnaldo Carvalho de Melo   perf trace: Sort ...
2474
  	resort_rb__delete(syscall_stats);
bf2575c12   David Ahern   perf trace: Add s...
2475
2476
2477
  	printed += fprintf(fp, "
  
  ");
1302d88e6   Arnaldo Carvalho de Melo   perf trace: Use s...
2478
2479
2480
  
  	return printed;
  }
96c144512   Arnaldo Carvalho de Melo   perf trace: Sort ...
2481
  static size_t trace__fprintf_thread(FILE *fp, struct thread *thread, struct trace *trace)
896cbb56b   David Ahern   perf trace: Use n...
2482
  {
96c144512   Arnaldo Carvalho de Melo   perf trace: Sort ...
2483
  	size_t printed = 0;
89dceb22c   Namhyung Kim   perf trace: Use t...
2484
  	struct thread_trace *ttrace = thread__priv(thread);
896cbb56b   David Ahern   perf trace: Use n...
2485
2486
2487
2488
2489
2490
  	double ratio;
  
  	if (ttrace == NULL)
  		return 0;
  
  	ratio = (double)ttrace->nr_events / trace->nr_events * 100.0;
15e65c693   Pekka Enberg   perf trace: Remov...
2491
  	printed += fprintf(fp, " %s (%d), ", thread__comm_str(thread), thread->tid);
99ff71505   Pekka Enberg   perf trace: Simpl...
2492
  	printed += fprintf(fp, "%lu events, ", ttrace->nr_events);
15e65c693   Pekka Enberg   perf trace: Remov...
2493
  	printed += fprintf(fp, "%.1f%%", ratio);
a2ea67d7b   Stanislav Fomichev   perf trace: Add p...
2494
2495
2496
2497
  	if (ttrace->pfmaj)
  		printed += fprintf(fp, ", %lu majfaults", ttrace->pfmaj);
  	if (ttrace->pfmin)
  		printed += fprintf(fp, ", %lu minfaults", ttrace->pfmin);
03548ebf6   Arnaldo Carvalho de Melo   perf trace: Do no...
2498
2499
2500
2501
2502
2503
  	if (trace->sched)
  		printed += fprintf(fp, ", %.3f msec
  ", ttrace->runtime_ms);
  	else if (fputc('
  ', fp) != EOF)
  		++printed;
bf2575c12   David Ahern   perf trace: Add s...
2504
  	printed += thread__dump_stats(ttrace, trace, fp);
896cbb56b   David Ahern   perf trace: Use n...
2505

96c144512   Arnaldo Carvalho de Melo   perf trace: Sort ...
2506
2507
  	return printed;
  }
896cbb56b   David Ahern   perf trace: Use n...
2508

96c144512   Arnaldo Carvalho de Melo   perf trace: Sort ...
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
  static unsigned long thread__nr_events(struct thread_trace *ttrace)
  {
  	return ttrace ? ttrace->nr_events : 0;
  }
  
  DEFINE_RESORT_RB(threads, (thread__nr_events(a->thread->priv) < thread__nr_events(b->thread->priv)),
  	struct thread *thread;
  )
  {
  	entry->thread = rb_entry(nd, struct thread, rb_node);
896cbb56b   David Ahern   perf trace: Use n...
2519
  }
1302d88e6   Arnaldo Carvalho de Melo   perf trace: Use s...
2520
2521
  static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp)
  {
96c144512   Arnaldo Carvalho de Melo   perf trace: Sort ...
2522
2523
2524
  	DECLARE_RESORT_RB_MACHINE_THREADS(threads, trace->host);
  	size_t printed = trace__fprintf_threads_header(fp);
  	struct rb_node *nd;
1302d88e6   Arnaldo Carvalho de Melo   perf trace: Use s...
2525

96c144512   Arnaldo Carvalho de Melo   perf trace: Sort ...
2526
2527
2528
2529
2530
  	if (threads == NULL) {
  		fprintf(fp, "%s", "Error sorting output by nr_events!
  ");
  		return 0;
  	}
98a91837d   Arnaldo Carvalho de Melo   perf rb_resort: R...
2531
  	resort_rb__for_each_entry(nd, threads)
96c144512   Arnaldo Carvalho de Melo   perf trace: Sort ...
2532
  		printed += trace__fprintf_thread(fp, threads_entry->thread, trace);
896cbb56b   David Ahern   perf trace: Use n...
2533

96c144512   Arnaldo Carvalho de Melo   perf trace: Sort ...
2534
2535
2536
  	resort_rb__delete(threads);
  
  	return printed;
1302d88e6   Arnaldo Carvalho de Melo   perf trace: Use s...
2537
  }
ae9ed0357   Arnaldo Carvalho de Melo   perf trace: Add d...
2538
2539
2540
2541
2542
2543
2544
2545
  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;
  }
f078c3852   Arnaldo Carvalho de Melo   perf trace: Intro...
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
  static int trace__set_filter_pids(const struct option *opt, const char *str,
  				  int unset __maybe_unused)
  {
  	int ret = -1;
  	size_t i;
  	struct trace *trace = opt->value;
  	/*
  	 * FIXME: introduce a intarray class, plain parse csv and create a
  	 * { int nr, int entries[] } struct...
  	 */
  	struct intlist *list = intlist__new(str);
  
  	if (list == NULL)
  		return -1;
  
  	i = trace->filter_pids.nr = intlist__nr_entries(list) + 1;
  	trace->filter_pids.entries = calloc(i, sizeof(pid_t));
  
  	if (trace->filter_pids.entries == NULL)
  		goto out;
  
  	trace->filter_pids.entries[0] = getpid();
  
  	for (i = 1; i < trace->filter_pids.nr; ++i)
  		trace->filter_pids.entries[i] = intlist__entry(list, i - 1)->i;
  
  	intlist__delete(list);
  	ret = 0;
  out:
  	return ret;
  }
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
  static int trace__open_output(struct trace *trace, const char *filename)
  {
  	struct stat st;
  
  	if (!stat(filename, &st) && st.st_size) {
  		char oldname[PATH_MAX];
  
  		scnprintf(oldname, sizeof(oldname), "%s.old", filename);
  		unlink(oldname);
  		rename(filename, oldname);
  	}
  
  	trace->output = fopen(filename, "w");
  
  	return trace->output == NULL ? -errno : 0;
  }
598d02c5a   Stanislav Fomichev   perf trace: Add s...
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
  static int parse_pagefaults(const struct option *opt, const char *str,
  			    int unset __maybe_unused)
  {
  	int *trace_pgfaults = opt->value;
  
  	if (strcmp(str, "all") == 0)
  		*trace_pgfaults |= TRACE_PFMAJ | TRACE_PFMIN;
  	else if (strcmp(str, "maj") == 0)
  		*trace_pgfaults |= TRACE_PFMAJ;
  	else if (strcmp(str, "min") == 0)
  		*trace_pgfaults |= TRACE_PFMIN;
  	else
  		return -1;
  
  	return 0;
  }
14a052df1   Arnaldo Carvalho de Melo   perf trace: Allow...
2609
2610
2611
  static void evlist__set_evsel_handler(struct perf_evlist *evlist, void *handler)
  {
  	struct perf_evsel *evsel;
e5cadb93d   Arnaldo Carvalho de Melo   perf evlist: Rena...
2612
  	evlist__for_each_entry(evlist, evsel)
14a052df1   Arnaldo Carvalho de Melo   perf trace: Allow...
2613
2614
  		evsel->handler = handler;
  }
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2615
2616
  int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
  {
6fdd9cb70   Yunlong Song   perf tools: Add t...
2617
  	const char *trace_usage[] = {
f15eb531d   Namhyung Kim   perf trace: Add s...
2618
2619
  		"perf trace [<options>] [<command>]",
  		"perf trace [<options>] -- <command> [<options>]",
5e2485b1a   David Ahern   perf trace: Add r...
2620
2621
  		"perf trace record [<options>] [<command>]",
  		"perf trace record [<options>] -- <command> [<options>]",
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2622
2623
2624
  		NULL
  	};
  	struct trace trace = {
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
  		.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...
2635
  			.no_buffering  = true,
38d5447d6   Arnaldo Carvalho de Melo   perf trace: Let t...
2636
  			.mmap_pages    = UINT_MAX,
9d9cad763   Kan Liang   perf tools: Confi...
2637
  			.proc_map_timeout  = 500,
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2638
  		},
007d66a0b   Milian Wolff   perf trace: Write...
2639
  		.output = stderr,
50c95cbd7   Arnaldo Carvalho de Melo   perf trace: Add o...
2640
  		.show_comm = true,
e281a9606   Stanislav Fomichev   perf trace: Add p...
2641
  		.trace_syscalls = true,
44621819d   Arnaldo Carvalho de Melo   perf trace: Exclu...
2642
  		.kernel_syscallchains = false,
056149932   Arnaldo Carvalho de Melo   perf trace: Make ...
2643
  		.max_stack = UINT_MAX,
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2644
  	};
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
2645
  	const char *output_name = NULL;
2ae3a312c   Arnaldo Carvalho de Melo   perf trace: Allow...
2646
  	const char *ev_qualifier_str = NULL;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2647
  	const struct option trace_options[] = {
14a052df1   Arnaldo Carvalho de Melo   perf trace: Allow...
2648
2649
2650
  	OPT_CALLBACK(0, "event", &trace.evlist, "event",
  		     "event selector. use 'perf list' to list available events",
  		     parse_events_option),
50c95cbd7   Arnaldo Carvalho de Melo   perf trace: Add o...
2651
2652
  	OPT_BOOLEAN(0, "comm", &trace.show_comm,
  		    "show the thread COMM next to its id"),
c522739d7   Arnaldo Carvalho de Melo   perf trace: Use v...
2653
  	OPT_BOOLEAN(0, "tool_stats", &trace.show_tool_stats, "show tool stats"),
d303e85a5   Arnaldo Carvalho de Melo   perf trace: Clari...
2654
  	OPT_STRING('e', "expr", &ev_qualifier_str, "expr", "list of syscalls to trace"),
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
2655
  	OPT_STRING('o', "output", &output_name, "file", "output file name"),
6810fc915   David Ahern   perf trace: Add o...
2656
  	OPT_STRING('i', "input", &input_name, "file", "Analyze events in file"),
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2657
2658
  	OPT_STRING('p', "pid", &trace.opts.target.pid, "pid",
  		    "trace events on existing process id"),
ac9be8ee4   David Ahern   perf trace: Make ...
2659
  	OPT_STRING('t', "tid", &trace.opts.target.tid, "tid",
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2660
  		    "trace events on existing thread id"),
fa0e4ffe0   Arnaldo Carvalho de Melo   perf trace: Fix -...
2661
2662
  	OPT_CALLBACK(0, "filter-pids", &trace, "CSV list of pids",
  		     "pids to filter (by the kernel)", trace__set_filter_pids),
ac9be8ee4   David Ahern   perf trace: Make ...
2663
  	OPT_BOOLEAN('a', "all-cpus", &trace.opts.target.system_wide,
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2664
  		    "system-wide collection from all CPUs"),
ac9be8ee4   David Ahern   perf trace: Make ...
2665
  	OPT_STRING('C', "cpu", &trace.opts.target.cpu_list, "cpu",
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2666
  		    "list of cpus to monitor"),
6810fc915   David Ahern   perf trace: Add o...
2667
  	OPT_BOOLEAN(0, "no-inherit", &trace.opts.no_inherit,
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2668
  		    "child tasks do not inherit counters"),
994a1f78b   Jiri Olsa   perf tools: Check...
2669
2670
2671
  	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 ...
2672
  	OPT_STRING('u', "uid", &trace.opts.target.uid_str, "user",
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2673
  		   "user to profile"),
ae9ed0357   Arnaldo Carvalho de Melo   perf trace: Add d...
2674
2675
2676
  	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...
2677
  	OPT_BOOLEAN(0, "sched", &trace.sched, "show blocking scheduler events"),
7c304ee0f   Arnaldo Carvalho de Melo   perf trace: Add -...
2678
  	OPT_INCR('v', "verbose", &verbose, "be more verbose"),
4bb09192d   David Ahern   perf trace: Add o...
2679
2680
  	OPT_BOOLEAN('T', "time", &trace.full_time,
  		    "Show full timestamp, not time relative to first start"),
fd2eabaf1   David Ahern   perf trace: Add s...
2681
2682
2683
2684
  	OPT_BOOLEAN('s', "summary", &trace.summary_only,
  		    "Show only syscall summary with statistics"),
  	OPT_BOOLEAN('S', "with-summary", &trace.summary,
  		    "Show all syscalls and summary with statistics"),
598d02c5a   Stanislav Fomichev   perf trace: Add s...
2685
2686
  	OPT_CALLBACK_DEFAULT('F', "pf", &trace.trace_pgfaults, "all|maj|min",
  		     "Trace pagefaults", parse_pagefaults, "maj"),
e281a9606   Stanislav Fomichev   perf trace: Add p...
2687
  	OPT_BOOLEAN(0, "syscalls", &trace.trace_syscalls, "Trace syscalls"),
e366a6d89   Yunlong Song   perf trace: Suppo...
2688
  	OPT_BOOLEAN('f', "force", &trace.force, "don't complain, do it"),
566a08859   Milian Wolff   perf trace: Add s...
2689
2690
2691
  	OPT_CALLBACK(0, "call-graph", &trace.opts,
  		     "record_mode[,record_size]", record_callchain_help,
  		     &record_parse_callchain_opt),
44621819d   Arnaldo Carvalho de Melo   perf trace: Exclu...
2692
2693
  	OPT_BOOLEAN(0, "kernel-syscall-graph", &trace.kernel_syscallchains,
  		    "Show the kernel callchains on the syscall exit path"),
5cf9c84e2   Arnaldo Carvalho de Melo   perf trace: Intro...
2694
2695
2696
  	OPT_UINTEGER(0, "min-stack", &trace.min_stack,
  		     "Set the minimum stack depth when parsing the callchain, "
  		     "anything below the specified depth will be ignored."),
c6d4a494a   Arnaldo Carvalho de Melo   perf trace: Add -...
2697
2698
2699
  	OPT_UINTEGER(0, "max-stack", &trace.max_stack,
  		     "Set the maximum stack depth when parsing the callchain, "
  		     "anything beyond the specified depth will be ignored. "
4cb93446c   Arnaldo Carvalho de Melo   perf tools: Set t...
2700
  		     "Default: kernel.perf_event_max_stack or " __stringify(PERF_MAX_STACK_DEPTH)),
9d9cad763   Kan Liang   perf tools: Confi...
2701
2702
  	OPT_UINTEGER(0, "proc-map-timeout", &trace.opts.proc_map_timeout,
  			"per thread proc mmap processing timeout in ms"),
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2703
2704
  	OPT_END()
  	};
ccd62a896   Arnaldo Carvalho de Melo   perf trace: Fix b...
2705
  	bool __maybe_unused max_stack_user_set = true;
f3e459d16   Arnaldo Carvalho de Melo   perf trace: Bump ...
2706
  	bool mmap_pages_user_set = true;
6fdd9cb70   Yunlong Song   perf tools: Add t...
2707
  	const char * const trace_subcommands[] = { "record", NULL };
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2708
  	int err;
32caf0d1f   Namhyung Kim   perf trace: Valid...
2709
  	char bf[BUFSIZ];
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2710

4d08cb80e   Arnaldo Carvalho de Melo   perf trace: Dump ...
2711
2712
  	signal(SIGSEGV, sighandler_dump_stack);
  	signal(SIGFPE, sighandler_dump_stack);
14a052df1   Arnaldo Carvalho de Melo   perf trace: Allow...
2713
  	trace.evlist = perf_evlist__new();
fd0db1026   Arnaldo Carvalho de Melo   perf trace: Move ...
2714
  	trace.sctbl = syscalltbl__new();
14a052df1   Arnaldo Carvalho de Melo   perf trace: Allow...
2715

fd0db1026   Arnaldo Carvalho de Melo   perf trace: Move ...
2716
  	if (trace.evlist == NULL || trace.sctbl == NULL) {
14a052df1   Arnaldo Carvalho de Melo   perf trace: Allow...
2717
2718
  		pr_err("Not enough memory to run!
  ");
ff8f695c0   He Kuang   perf trace: Remov...
2719
  		err = -ENOMEM;
14a052df1   Arnaldo Carvalho de Melo   perf trace: Allow...
2720
2721
  		goto out;
  	}
6fdd9cb70   Yunlong Song   perf tools: Add t...
2722
2723
  	argc = parse_options_subcommand(argc, argv, trace_options, trace_subcommands,
  				 trace_usage, PARSE_OPT_STOP_AT_NON_OPTION);
fd2eabaf1   David Ahern   perf trace: Add s...
2724

d78885739   Wang Nan   perf bpf: Clone b...
2725
2726
2727
2728
2729
2730
2731
  	err = bpf__setup_stdout(trace.evlist);
  	if (err) {
  		bpf__strerror_setup_stdout(trace.evlist, err, bf, sizeof(bf));
  		pr_err("ERROR: Setup BPF stdout failed: %s
  ", bf);
  		goto out;
  	}
59247e33f   Arnaldo Carvalho de Melo   perf trace: Do no...
2732
  	err = -1;
598d02c5a   Stanislav Fomichev   perf trace: Add s...
2733
2734
2735
2736
  	if (trace.trace_pgfaults) {
  		trace.opts.sample_address = true;
  		trace.opts.sample_time = true;
  	}
f3e459d16   Arnaldo Carvalho de Melo   perf trace: Bump ...
2737
2738
  	if (trace.opts.mmap_pages == UINT_MAX)
  		mmap_pages_user_set = false;
056149932   Arnaldo Carvalho de Melo   perf trace: Make ...
2739
  	if (trace.max_stack == UINT_MAX) {
fe176085a   Arnaldo Carvalho de Melo   perf tools: Fix u...
2740
  		trace.max_stack = input_name ? PERF_MAX_STACK_DEPTH : sysctl_perf_event_max_stack;
056149932   Arnaldo Carvalho de Melo   perf trace: Make ...
2741
2742
2743
2744
  		max_stack_user_set = false;
  	}
  
  #ifdef HAVE_DWARF_UNWIND_SUPPORT
caa36ed7b   Arnaldo Carvalho de Melo   perf trace: Only ...
2745
  	if ((trace.min_stack || max_stack_user_set) && !callchain_param.enabled && trace.trace_syscalls)
056149932   Arnaldo Carvalho de Melo   perf trace: Make ...
2746
2747
  		record_opts__parse_callchain(&trace.opts, &callchain_param, "dwarf", false);
  #endif
2ddd5c049   Arnaldo Carvalho de Melo   perf tools: Ditch...
2748
  	if (callchain_param.enabled) {
f3e459d16   Arnaldo Carvalho de Melo   perf trace: Bump ...
2749
2750
  		if (!mmap_pages_user_set && geteuid() == 0)
  			trace.opts.mmap_pages = perf_event_mlock_kb_in_pages() * 4;
566a08859   Milian Wolff   perf trace: Add s...
2751
  		symbol_conf.use_callchain = true;
f3e459d16   Arnaldo Carvalho de Melo   perf trace: Bump ...
2752
  	}
566a08859   Milian Wolff   perf trace: Add s...
2753

14a052df1   Arnaldo Carvalho de Melo   perf trace: Allow...
2754
2755
  	if (trace.evlist->nr_entries > 0)
  		evlist__set_evsel_handler(trace.evlist, trace__event_handler);
1e28fe0a4   Stanislav Fomichev   perf trace: Add p...
2756
2757
2758
2759
2760
2761
  	if ((argc >= 1) && (strcmp(argv[0], "record") == 0))
  		return trace__record(&trace, argc-1, &argv[1]);
  
  	/* summary_only implies summary option, but don't overwrite summary if set */
  	if (trace.summary_only)
  		trace.summary = trace.summary_only;
726f3234d   Arnaldo Carvalho de Melo   perf trace: Suppo...
2762
2763
  	if (!trace.trace_syscalls && !trace.trace_pgfaults &&
  	    trace.evlist->nr_entries == 0 /* Was --events used? */) {
e281a9606   Stanislav Fomichev   perf trace: Add p...
2764
2765
2766
2767
  		pr_err("Please specify something to trace.
  ");
  		return -1;
  	}
59247e33f   Arnaldo Carvalho de Melo   perf trace: Do no...
2768
2769
2770
2771
2772
  	if (!trace.trace_syscalls && ev_qualifier_str) {
  		pr_err("The -e option can't be used with --no-syscalls.
  ");
  		goto out;
  	}
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
2773
2774
2775
2776
2777
2778
2779
  	if (output_name != NULL) {
  		err = trace__open_output(&trace, output_name);
  		if (err < 0) {
  			perror("failed to create output file");
  			goto out;
  		}
  	}
fd0db1026   Arnaldo Carvalho de Melo   perf trace: Move ...
2780
  	trace.open_id = syscalltbl__id(trace.sctbl, "open");
2ae3a312c   Arnaldo Carvalho de Melo   perf trace: Allow...
2781
  	if (ev_qualifier_str != NULL) {
b059efdf5   Arnaldo Carvalho de Melo   perf trace: Suppo...
2782
  		const char *s = ev_qualifier_str;
005438a8e   Arnaldo Carvalho de Melo   perf trace: Suppo...
2783
2784
2785
  		struct strlist_config slist_config = {
  			.dirname = system_path(STRACE_GROUPS_DIR),
  		};
b059efdf5   Arnaldo Carvalho de Melo   perf trace: Suppo...
2786
2787
2788
2789
  
  		trace.not_ev_qualifier = *s == '!';
  		if (trace.not_ev_qualifier)
  			++s;
005438a8e   Arnaldo Carvalho de Melo   perf trace: Suppo...
2790
  		trace.ev_qualifier = strlist__new(s, &slist_config);
2ae3a312c   Arnaldo Carvalho de Melo   perf trace: Allow...
2791
  		if (trace.ev_qualifier == NULL) {
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
2792
2793
2794
2795
  			fputs("Not enough memory to parse event qualifier",
  			      trace.output);
  			err = -ENOMEM;
  			goto out_close;
2ae3a312c   Arnaldo Carvalho de Melo   perf trace: Allow...
2796
  		}
d0cc439b3   Arnaldo Carvalho de Melo   perf trace: Valid...
2797
2798
2799
2800
  
  		err = trace__validate_ev_qualifier(&trace);
  		if (err)
  			goto out_close;
2ae3a312c   Arnaldo Carvalho de Melo   perf trace: Allow...
2801
  	}
602ad878d   Arnaldo Carvalho de Melo   perf target: Shor...
2802
  	err = target__validate(&trace.opts.target);
32caf0d1f   Namhyung Kim   perf trace: Valid...
2803
  	if (err) {
602ad878d   Arnaldo Carvalho de Melo   perf target: Shor...
2804
  		target__strerror(&trace.opts.target, err, bf, sizeof(bf));
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
2805
2806
  		fprintf(trace.output, "%s", bf);
  		goto out_close;
32caf0d1f   Namhyung Kim   perf trace: Valid...
2807
  	}
602ad878d   Arnaldo Carvalho de Melo   perf target: Shor...
2808
  	err = target__parse_uid(&trace.opts.target);
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2809
  	if (err) {
602ad878d   Arnaldo Carvalho de Melo   perf target: Shor...
2810
  		target__strerror(&trace.opts.target, err, bf, sizeof(bf));
c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
2811
2812
  		fprintf(trace.output, "%s", bf);
  		goto out_close;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2813
  	}
602ad878d   Arnaldo Carvalho de Melo   perf target: Shor...
2814
  	if (!argc && target__none(&trace.opts.target))
ee76120e2   Namhyung Kim   perf trace: Expli...
2815
  		trace.opts.target.system_wide = true;
6810fc915   David Ahern   perf trace: Add o...
2816
2817
2818
2819
  	if (input_name)
  		err = trace__replay(&trace);
  	else
  		err = trace__run(&trace, argc, argv);
1302d88e6   Arnaldo Carvalho de Melo   perf trace: Use s...
2820

c24ff998f   Arnaldo Carvalho de Melo   perf trace: Imple...
2821
2822
2823
2824
  out_close:
  	if (output_name != NULL)
  		fclose(trace.output);
  out:
1302d88e6   Arnaldo Carvalho de Melo   perf trace: Use s...
2825
  	return err;
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
2826
  }