blob: 206bf72b77fcb9c795486ec9fba184b9d6321b7b [file] [log] [blame]
Arnaldo Carvalho de Meloa598bb52015-08-28 12:02:37 -03001/*
2 * builtin-trace.c
3 *
4 * Builtin 'trace' command:
5 *
6 * Display a continuously updated trace of any workload, CPU, specific PID,
7 * system wide, etc. Default format is loosely strace like, but any other
8 * event may be specified using --event.
9 *
10 * Copyright (C) 2012, 2013, 2014, 2015 Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
11 *
12 * Initially based on the 'trace' prototype by Thomas Gleixner:
13 *
14 * http://lwn.net/Articles/415728/ ("Announcing a new utility: 'trace'")
15 *
16 * Released under the GPL v2. (and only v2, not any later version)
17 */
18
Robert Richter4e319022013-06-11 17:29:18 +020019#include <traceevent/event-parse.h>
Jiri Olsa988bdb32015-09-02 09:56:35 +020020#include <api/fs/tracing_path.h>
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -030021#include "builtin.h"
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -030022#include "util/color.h"
Arnaldo Carvalho de Melo7c304ee02013-08-22 16:49:54 -030023#include "util/debug.h"
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -030024#include "util/evlist.h"
Josh Poimboeuf4b6ab942015-12-15 09:39:39 -060025#include <subcmd/exec-cmd.h>
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -030026#include "util/machine.h"
David Ahern6810fc92013-08-28 22:29:52 -060027#include "util/session.h"
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -030028#include "util/thread.h"
Josh Poimboeuf4b6ab942015-12-15 09:39:39 -060029#include <subcmd/parse-options.h>
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -030030#include "util/strlist.h"
David Ahernbdc89662013-08-28 22:29:53 -060031#include "util/intlist.h"
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -030032#include "util/thread_map.h"
David Ahernbf2575c2013-10-08 21:26:53 -060033#include "util/stat.h"
Jiri Olsa97978b32013-12-03 14:09:24 +010034#include "trace-event.h"
David Ahern9aca7f12013-12-04 19:41:39 -070035#include "util/parse-events.h"
Wang Nanba504232016-02-26 09:31:54 +000036#include "util/bpf-loader.h"
Milian Wolff566a0882016-04-08 13:34:15 +020037#include "callchain.h"
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -030038#include "syscalltbl.h"
Arnaldo Carvalho de Melo96c14452016-05-04 12:47:16 -030039#include "rb_resort.h"
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -030040
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -030041#include <libaudit.h> /* FIXME: Still needed for audit_errno_to_name */
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -030042#include <stdlib.h>
Jiri Olsa8dd2a132015-09-07 10:38:06 +020043#include <linux/err.h>
Arnaldo Carvalho de Melo997bba82016-03-30 19:43:32 -030044#include <linux/filter.h>
45#include <linux/audit.h>
Arnaldo Carvalho de Melo39878d42016-03-30 20:02:15 -030046#include <linux/random.h>
Arnaldo Carvalho de Meloc6d4a492016-04-14 18:29:08 -030047#include <linux/stringify.h>
Arnaldo Carvalho de Melobd48c632016-08-05 15:40:30 -030048#include <linux/time64.h>
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -030049
Arnaldo Carvalho de Meloc188e7a2015-05-14 17:39:03 -030050#ifndef O_CLOEXEC
51# define O_CLOEXEC 02000000
52#endif
53
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -030054struct trace {
55 struct perf_tool tool;
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -030056 struct syscalltbl *sctbl;
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -030057 struct {
58 int max;
59 struct syscall *table;
60 struct {
61 struct perf_evsel *sys_enter,
62 *sys_exit;
63 } events;
64 } syscalls;
65 struct record_opts opts;
66 struct perf_evlist *evlist;
67 struct machine *host;
68 struct thread *current;
69 u64 base_time;
70 FILE *output;
71 unsigned long nr_events;
72 struct strlist *ev_qualifier;
73 struct {
74 size_t nr;
75 int *entries;
76 } ev_qualifier_ids;
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -030077 struct {
78 size_t nr;
79 pid_t *entries;
80 } filter_pids;
81 double duration_filter;
82 double runtime_ms;
83 struct {
84 u64 vfs_getname,
85 proc_getname;
86 } stats;
Arnaldo Carvalho de Meloc6d4a492016-04-14 18:29:08 -030087 unsigned int max_stack;
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -030088 unsigned int min_stack;
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -030089 bool not_ev_qualifier;
90 bool live;
91 bool full_time;
92 bool sched;
93 bool multiple_threads;
94 bool summary;
95 bool summary_only;
96 bool show_comm;
97 bool show_tool_stats;
98 bool trace_syscalls;
Arnaldo Carvalho de Melo44621812016-04-11 15:49:11 -030099 bool kernel_syscallchains;
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -0300100 bool force;
101 bool vfs_getname;
102 int trace_pgfaults;
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -0300103 int open_id;
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -0300104};
Arnaldo Carvalho de Meloa1c25522015-06-11 22:47:54 -0300105
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300106struct tp_field {
107 int offset;
108 union {
109 u64 (*integer)(struct tp_field *field, struct perf_sample *sample);
110 void *(*pointer)(struct tp_field *field, struct perf_sample *sample);
111 };
112};
113
114#define TP_UINT_FIELD(bits) \
115static u64 tp_field__u##bits(struct tp_field *field, struct perf_sample *sample) \
116{ \
David Ahern55d43bc2015-02-19 15:00:22 -0500117 u##bits value; \
118 memcpy(&value, sample->raw_data + field->offset, sizeof(value)); \
119 return value; \
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300120}
121
122TP_UINT_FIELD(8);
123TP_UINT_FIELD(16);
124TP_UINT_FIELD(32);
125TP_UINT_FIELD(64);
126
127#define TP_UINT_FIELD__SWAPPED(bits) \
128static u64 tp_field__swapped_u##bits(struct tp_field *field, struct perf_sample *sample) \
129{ \
David Ahern55d43bc2015-02-19 15:00:22 -0500130 u##bits value; \
131 memcpy(&value, sample->raw_data + field->offset, sizeof(value)); \
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300132 return bswap_##bits(value);\
133}
134
135TP_UINT_FIELD__SWAPPED(16);
136TP_UINT_FIELD__SWAPPED(32);
137TP_UINT_FIELD__SWAPPED(64);
138
139static int tp_field__init_uint(struct tp_field *field,
140 struct format_field *format_field,
141 bool needs_swap)
142{
143 field->offset = format_field->offset;
144
145 switch (format_field->size) {
146 case 1:
147 field->integer = tp_field__u8;
148 break;
149 case 2:
150 field->integer = needs_swap ? tp_field__swapped_u16 : tp_field__u16;
151 break;
152 case 4:
153 field->integer = needs_swap ? tp_field__swapped_u32 : tp_field__u32;
154 break;
155 case 8:
156 field->integer = needs_swap ? tp_field__swapped_u64 : tp_field__u64;
157 break;
158 default:
159 return -1;
160 }
161
162 return 0;
163}
164
165static void *tp_field__ptr(struct tp_field *field, struct perf_sample *sample)
166{
167 return sample->raw_data + field->offset;
168}
169
170static int tp_field__init_ptr(struct tp_field *field, struct format_field *format_field)
171{
172 field->offset = format_field->offset;
173 field->pointer = tp_field__ptr;
174 return 0;
175}
176
177struct syscall_tp {
178 struct tp_field id;
179 union {
180 struct tp_field args, ret;
181 };
182};
183
184static int perf_evsel__init_tp_uint_field(struct perf_evsel *evsel,
185 struct tp_field *field,
186 const char *name)
187{
188 struct format_field *format_field = perf_evsel__field(evsel, name);
189
190 if (format_field == NULL)
191 return -1;
192
193 return tp_field__init_uint(field, format_field, evsel->needs_swap);
194}
195
196#define perf_evsel__init_sc_tp_uint_field(evsel, name) \
197 ({ struct syscall_tp *sc = evsel->priv;\
198 perf_evsel__init_tp_uint_field(evsel, &sc->name, #name); })
199
200static int perf_evsel__init_tp_ptr_field(struct perf_evsel *evsel,
201 struct tp_field *field,
202 const char *name)
203{
204 struct format_field *format_field = perf_evsel__field(evsel, name);
205
206 if (format_field == NULL)
207 return -1;
208
209 return tp_field__init_ptr(field, format_field);
210}
211
212#define perf_evsel__init_sc_tp_ptr_field(evsel, name) \
213 ({ struct syscall_tp *sc = evsel->priv;\
214 perf_evsel__init_tp_ptr_field(evsel, &sc->name, #name); })
215
216static void perf_evsel__delete_priv(struct perf_evsel *evsel)
217{
Arnaldo Carvalho de Melo04662522013-12-26 17:41:15 -0300218 zfree(&evsel->priv);
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300219 perf_evsel__delete(evsel);
220}
221
Namhyung Kim96695d42013-11-12 08:51:45 -0300222static int perf_evsel__init_syscall_tp(struct perf_evsel *evsel, void *handler)
223{
224 evsel->priv = malloc(sizeof(struct syscall_tp));
225 if (evsel->priv != NULL) {
226 if (perf_evsel__init_sc_tp_uint_field(evsel, id))
227 goto out_delete;
228
229 evsel->handler = handler;
230 return 0;
231 }
232
233 return -ENOMEM;
234
235out_delete:
Arnaldo Carvalho de Melo04662522013-12-26 17:41:15 -0300236 zfree(&evsel->priv);
Namhyung Kim96695d42013-11-12 08:51:45 -0300237 return -ENOENT;
238}
239
Arnaldo Carvalho de Meloef503832013-11-07 16:41:19 -0300240static struct perf_evsel *perf_evsel__syscall_newtp(const char *direction, void *handler)
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300241{
Arnaldo Carvalho de Meloef503832013-11-07 16:41:19 -0300242 struct perf_evsel *evsel = perf_evsel__newtp("raw_syscalls", direction);
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300243
David Ahern9aca7f12013-12-04 19:41:39 -0700244 /* older kernel (e.g., RHEL6) use syscalls:{enter,exit} */
Jiri Olsa8dd2a132015-09-07 10:38:06 +0200245 if (IS_ERR(evsel))
David Ahern9aca7f12013-12-04 19:41:39 -0700246 evsel = perf_evsel__newtp("syscalls", direction);
247
Jiri Olsa8dd2a132015-09-07 10:38:06 +0200248 if (IS_ERR(evsel))
249 return NULL;
250
251 if (perf_evsel__init_syscall_tp(evsel, handler))
252 goto out_delete;
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300253
254 return evsel;
255
256out_delete:
257 perf_evsel__delete_priv(evsel);
258 return NULL;
259}
260
261#define perf_evsel__sc_tp_uint(evsel, name, sample) \
262 ({ struct syscall_tp *fields = evsel->priv; \
263 fields->name.integer(&fields->name, sample); })
264
265#define perf_evsel__sc_tp_ptr(evsel, name, sample) \
266 ({ struct syscall_tp *fields = evsel->priv; \
267 fields->name.pointer(&fields->name, sample); })
268
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300269struct syscall_arg {
270 unsigned long val;
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300271 struct thread *thread;
272 struct trace *trace;
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300273 void *parm;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300274 u8 idx;
275 u8 mask;
276};
277
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300278struct strarray {
Arnaldo Carvalho de Melo03e3adc2013-10-08 16:00:21 -0300279 int offset;
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300280 int nr_entries;
281 const char **entries;
282};
283
284#define DEFINE_STRARRAY(array) struct strarray strarray__##array = { \
285 .nr_entries = ARRAY_SIZE(array), \
286 .entries = array, \
287}
288
Arnaldo Carvalho de Melo03e3adc2013-10-08 16:00:21 -0300289#define DEFINE_STRARRAY_OFFSET(array, off) struct strarray strarray__##array = { \
290 .offset = off, \
291 .nr_entries = ARRAY_SIZE(array), \
292 .entries = array, \
293}
294
Arnaldo Carvalho de Melo975b7c22013-10-08 17:17:43 -0300295static size_t __syscall_arg__scnprintf_strarray(char *bf, size_t size,
296 const char *intfmt,
297 struct syscall_arg *arg)
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300298{
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300299 struct strarray *sa = arg->parm;
Arnaldo Carvalho de Melo03e3adc2013-10-08 16:00:21 -0300300 int idx = arg->val - sa->offset;
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300301
302 if (idx < 0 || idx >= sa->nr_entries)
Arnaldo Carvalho de Melo975b7c22013-10-08 17:17:43 -0300303 return scnprintf(bf, size, intfmt, arg->val);
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300304
305 return scnprintf(bf, size, "%s", sa->entries[idx]);
306}
307
Arnaldo Carvalho de Melo975b7c22013-10-08 17:17:43 -0300308static size_t syscall_arg__scnprintf_strarray(char *bf, size_t size,
309 struct syscall_arg *arg)
310{
311 return __syscall_arg__scnprintf_strarray(bf, size, "%d", arg);
312}
313
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300314#define SCA_STRARRAY syscall_arg__scnprintf_strarray
315
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -0300316#if defined(__i386__) || defined(__x86_64__)
317/*
318 * FIXME: Make this available to all arches as soon as the ioctl beautifier
319 * gets rewritten to support all arches.
320 */
Arnaldo Carvalho de Melo78645cf2013-10-08 17:43:20 -0300321static size_t syscall_arg__scnprintf_strhexarray(char *bf, size_t size,
322 struct syscall_arg *arg)
323{
324 return __syscall_arg__scnprintf_strarray(bf, size, "%#x", arg);
325}
326
327#define SCA_STRHEXARRAY syscall_arg__scnprintf_strhexarray
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -0300328#endif /* defined(__i386__) || defined(__x86_64__) */
Arnaldo Carvalho de Melo78645cf2013-10-08 17:43:20 -0300329
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300330static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
331 struct syscall_arg *arg);
332
333#define SCA_FD syscall_arg__scnprintf_fd
334
Arnaldo Carvalho de Melo48e1f912016-07-05 14:43:27 -0300335#ifndef AT_FDCWD
336#define AT_FDCWD -100
337#endif
338
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300339static size_t syscall_arg__scnprintf_fd_at(char *bf, size_t size,
340 struct syscall_arg *arg)
341{
342 int fd = arg->val;
343
344 if (fd == AT_FDCWD)
345 return scnprintf(bf, size, "CWD");
346
347 return syscall_arg__scnprintf_fd(bf, size, arg);
348}
349
350#define SCA_FDAT syscall_arg__scnprintf_fd_at
351
352static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
353 struct syscall_arg *arg);
354
355#define SCA_CLOSE_FD syscall_arg__scnprintf_close_fd
356
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -0300357static size_t syscall_arg__scnprintf_hex(char *bf, size_t size,
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300358 struct syscall_arg *arg)
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -0300359{
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300360 return scnprintf(bf, size, "%#lx", arg->val);
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -0300361}
362
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -0300363#define SCA_HEX syscall_arg__scnprintf_hex
364
Arnaldo Carvalho de Meloa1c25522015-06-11 22:47:54 -0300365static size_t syscall_arg__scnprintf_int(char *bf, size_t size,
366 struct syscall_arg *arg)
367{
368 return scnprintf(bf, size, "%d", arg->val);
369}
370
371#define SCA_INT syscall_arg__scnprintf_int
372
Arnaldo Carvalho de Melo729a7842015-10-29 11:48:18 -0300373static const char *bpf_cmd[] = {
374 "MAP_CREATE", "MAP_LOOKUP_ELEM", "MAP_UPDATE_ELEM", "MAP_DELETE_ELEM",
375 "MAP_GET_NEXT_KEY", "PROG_LOAD",
376};
377static DEFINE_STRARRAY(bpf_cmd);
378
Arnaldo Carvalho de Melo03e3adc2013-10-08 16:00:21 -0300379static const char *epoll_ctl_ops[] = { "ADD", "DEL", "MOD", };
380static DEFINE_STRARRAY_OFFSET(epoll_ctl_ops, 1);
Arnaldo Carvalho de Meloeac032c2013-09-20 11:27:32 -0300381
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300382static const char *itimers[] = { "REAL", "VIRTUAL", "PROF", };
383static DEFINE_STRARRAY(itimers);
384
Arnaldo Carvalho de Melob62bee12015-08-11 11:05:36 -0300385static const char *keyctl_options[] = {
386 "GET_KEYRING_ID", "JOIN_SESSION_KEYRING", "UPDATE", "REVOKE", "CHOWN",
387 "SETPERM", "DESCRIBE", "CLEAR", "LINK", "UNLINK", "SEARCH", "READ",
388 "INSTANTIATE", "NEGATE", "SET_REQKEY_KEYRING", "SET_TIMEOUT",
389 "ASSUME_AUTHORITY", "GET_SECURITY", "SESSION_TO_PARENT", "REJECT",
390 "INSTANTIATE_IOV", "INVALIDATE", "GET_PERSISTENT",
391};
392static DEFINE_STRARRAY(keyctl_options);
393
Arnaldo Carvalho de Meloefe6b882013-09-03 16:15:12 -0300394static const char *whences[] = { "SET", "CUR", "END",
395#ifdef SEEK_DATA
396"DATA",
397#endif
398#ifdef SEEK_HOLE
399"HOLE",
400#endif
401};
402static DEFINE_STRARRAY(whences);
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -0300403
Arnaldo Carvalho de Melo80f587d2013-09-03 16:28:58 -0300404static const char *fcntl_cmds[] = {
405 "DUPFD", "GETFD", "SETFD", "GETFL", "SETFL", "GETLK", "SETLK",
406 "SETLKW", "SETOWN", "GETOWN", "SETSIG", "GETSIG", "F_GETLK64",
407 "F_SETLK64", "F_SETLKW64", "F_SETOWN_EX", "F_GETOWN_EX",
408 "F_GETOWNER_UIDS",
409};
410static DEFINE_STRARRAY(fcntl_cmds);
411
Arnaldo Carvalho de Meloc045bf02013-09-04 11:52:33 -0300412static const char *rlimit_resources[] = {
413 "CPU", "FSIZE", "DATA", "STACK", "CORE", "RSS", "NPROC", "NOFILE",
414 "MEMLOCK", "AS", "LOCKS", "SIGPENDING", "MSGQUEUE", "NICE", "RTPRIO",
415 "RTTIME",
416};
417static DEFINE_STRARRAY(rlimit_resources);
418
Arnaldo Carvalho de Meloeb5b1b12013-09-03 16:37:46 -0300419static const char *sighow[] = { "BLOCK", "UNBLOCK", "SETMASK", };
420static DEFINE_STRARRAY(sighow);
421
David Ahern4f8c1b72013-09-22 19:45:00 -0600422static const char *clockid[] = {
423 "REALTIME", "MONOTONIC", "PROCESS_CPUTIME_ID", "THREAD_CPUTIME_ID",
Arnaldo Carvalho de Melo28ebb872015-08-11 10:38:38 -0300424 "MONOTONIC_RAW", "REALTIME_COARSE", "MONOTONIC_COARSE", "BOOTTIME",
425 "REALTIME_ALARM", "BOOTTIME_ALARM", "SGI_CYCLE", "TAI"
David Ahern4f8c1b72013-09-22 19:45:00 -0600426};
427static DEFINE_STRARRAY(clockid);
428
Arnaldo Carvalho de Meloe10bce82013-09-04 10:27:41 -0300429static const char *socket_families[] = {
430 "UNSPEC", "LOCAL", "INET", "AX25", "IPX", "APPLETALK", "NETROM",
431 "BRIDGE", "ATMPVC", "X25", "INET6", "ROSE", "DECnet", "NETBEUI",
432 "SECURITY", "KEY", "NETLINK", "PACKET", "ASH", "ECONET", "ATMSVC",
433 "RDS", "SNA", "IRDA", "PPPOX", "WANPIPE", "LLC", "IB", "CAN", "TIPC",
434 "BLUETOOTH", "IUCV", "RXRPC", "ISDN", "PHONET", "IEEE802154", "CAIF",
435 "ALG", "NFC", "VSOCK",
436};
437static DEFINE_STRARRAY(socket_families);
438
Arnaldo Carvalho de Melo51108992013-09-04 11:42:27 -0300439static size_t syscall_arg__scnprintf_access_mode(char *bf, size_t size,
440 struct syscall_arg *arg)
441{
442 size_t printed = 0;
443 int mode = arg->val;
444
445 if (mode == F_OK) /* 0 */
446 return scnprintf(bf, size, "F");
447#define P_MODE(n) \
448 if (mode & n##_OK) { \
449 printed += scnprintf(bf + printed, size - printed, "%s", #n); \
450 mode &= ~n##_OK; \
451 }
452
453 P_MODE(R);
454 P_MODE(W);
455 P_MODE(X);
456#undef P_MODE
457
458 if (mode)
459 printed += scnprintf(bf + printed, size - printed, "|%#x", mode);
460
461 return printed;
462}
463
464#define SCA_ACCMODE syscall_arg__scnprintf_access_mode
465
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -0300466static size_t syscall_arg__scnprintf_filename(char *bf, size_t size,
467 struct syscall_arg *arg);
468
469#define SCA_FILENAME syscall_arg__scnprintf_filename
470
Arnaldo Carvalho de Melo46cce192013-09-23 12:52:04 -0300471static size_t syscall_arg__scnprintf_pipe_flags(char *bf, size_t size,
472 struct syscall_arg *arg)
473{
474 int printed = 0, flags = arg->val;
475
476#define P_FLAG(n) \
477 if (flags & O_##n) { \
478 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
479 flags &= ~O_##n; \
480 }
481
482 P_FLAG(CLOEXEC);
483 P_FLAG(NONBLOCK);
484#undef P_FLAG
485
486 if (flags)
487 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
488
489 return printed;
490}
491
492#define SCA_PIPE_FLAGS syscall_arg__scnprintf_pipe_flags
493
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -0300494#if defined(__i386__) || defined(__x86_64__)
495/*
496 * FIXME: Make this available to all arches.
497 */
Arnaldo Carvalho de Melo78645cf2013-10-08 17:43:20 -0300498#define TCGETS 0x5401
499
500static const char *tioctls[] = {
501 "TCGETS", "TCSETS", "TCSETSW", "TCSETSF", "TCGETA", "TCSETA", "TCSETAW",
502 "TCSETAF", "TCSBRK", "TCXONC", "TCFLSH", "TIOCEXCL", "TIOCNXCL",
503 "TIOCSCTTY", "TIOCGPGRP", "TIOCSPGRP", "TIOCOUTQ", "TIOCSTI",
504 "TIOCGWINSZ", "TIOCSWINSZ", "TIOCMGET", "TIOCMBIS", "TIOCMBIC",
505 "TIOCMSET", "TIOCGSOFTCAR", "TIOCSSOFTCAR", "FIONREAD", "TIOCLINUX",
506 "TIOCCONS", "TIOCGSERIAL", "TIOCSSERIAL", "TIOCPKT", "FIONBIO",
507 "TIOCNOTTY", "TIOCSETD", "TIOCGETD", "TCSBRKP", [0x27] = "TIOCSBRK",
508 "TIOCCBRK", "TIOCGSID", "TCGETS2", "TCSETS2", "TCSETSW2", "TCSETSF2",
509 "TIOCGRS485", "TIOCSRS485", "TIOCGPTN", "TIOCSPTLCK",
510 "TIOCGDEV||TCGETX", "TCSETX", "TCSETXF", "TCSETXW", "TIOCSIG",
511 "TIOCVHANGUP", "TIOCGPKT", "TIOCGPTLCK", "TIOCGEXCL",
512 [0x50] = "FIONCLEX", "FIOCLEX", "FIOASYNC", "TIOCSERCONFIG",
513 "TIOCSERGWILD", "TIOCSERSWILD", "TIOCGLCKTRMIOS", "TIOCSLCKTRMIOS",
514 "TIOCSERGSTRUCT", "TIOCSERGETLSR", "TIOCSERGETMULTI", "TIOCSERSETMULTI",
515 "TIOCMIWAIT", "TIOCGICOUNT", [0x60] = "FIOQSIZE",
516};
517
518static DEFINE_STRARRAY_OFFSET(tioctls, 0x5401);
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -0300519#endif /* defined(__i386__) || defined(__x86_64__) */
Arnaldo Carvalho de Melo78645cf2013-10-08 17:43:20 -0300520
Arnaldo Carvalho de Meloa355a612016-04-13 11:55:18 -0300521#ifndef GRND_NONBLOCK
522#define GRND_NONBLOCK 0x0001
523#endif
524#ifndef GRND_RANDOM
525#define GRND_RANDOM 0x0002
526#endif
527
Arnaldo Carvalho de Melo39878d42016-03-30 20:02:15 -0300528static size_t syscall_arg__scnprintf_getrandom_flags(char *bf, size_t size,
529 struct syscall_arg *arg)
530{
531 int printed = 0, flags = arg->val;
532
533#define P_FLAG(n) \
534 if (flags & GRND_##n) { \
535 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
536 flags &= ~GRND_##n; \
537 }
538
539 P_FLAG(RANDOM);
540 P_FLAG(NONBLOCK);
541#undef P_FLAG
542
543 if (flags)
544 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
545
546 return printed;
547}
548
549#define SCA_GETRANDOM_FLAGS syscall_arg__scnprintf_getrandom_flags
550
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300551#define STRARRAY(arg, name, array) \
552 .arg_scnprintf = { [arg] = SCA_STRARRAY, }, \
553 .arg_parm = { [arg] = &strarray__##array, }
554
Arnaldo Carvalho de Meloea8dc3c2016-04-13 12:10:19 -0300555#include "trace/beauty/eventfd.c"
Arnaldo Carvalho de Melo8bf382c2016-05-11 10:29:36 -0300556#include "trace/beauty/flock.c"
Arnaldo Carvalho de Melod5d71e82016-05-06 12:45:25 -0300557#include "trace/beauty/futex_op.c"
Arnaldo Carvalho de Melodf4cb162016-04-13 12:05:44 -0300558#include "trace/beauty/mmap.c"
Arnaldo Carvalho de Meloba2f22c2016-04-07 12:05:51 -0300559#include "trace/beauty/mode_t.c"
Arnaldo Carvalho de Meloa30e6252016-04-27 19:01:52 -0300560#include "trace/beauty/msg_flags.c"
Arnaldo Carvalho de Melo8f48df62016-05-06 10:02:32 -0300561#include "trace/beauty/open_flags.c"
Arnaldo Carvalho de Melo62de3442016-04-26 11:03:03 -0300562#include "trace/beauty/perf_event_open.c"
Arnaldo Carvalho de Melod5d71e82016-05-06 12:45:25 -0300563#include "trace/beauty/pid.c"
Arnaldo Carvalho de Meloa3bca912016-04-06 12:51:33 -0300564#include "trace/beauty/sched_policy.c"
Arnaldo Carvalho de Melof5cd95e2016-05-11 10:32:20 -0300565#include "trace/beauty/seccomp.c"
Arnaldo Carvalho de Melo12199d82016-05-06 09:58:02 -0300566#include "trace/beauty/signum.c"
Arnaldo Carvalho de Melobbf86c42016-04-14 13:53:10 -0300567#include "trace/beauty/socket_type.c"
Arnaldo Carvalho de Melo7206b902016-04-06 14:11:36 -0300568#include "trace/beauty/waitid_options.c"
Arnaldo Carvalho de Meloa3bca912016-04-06 12:51:33 -0300569
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300570static struct syscall_fmt {
571 const char *name;
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -0300572 const char *alias;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300573 size_t (*arg_scnprintf[6])(char *bf, size_t size, struct syscall_arg *arg);
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300574 void *arg_parm[6];
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300575 bool errmsg;
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -0300576 bool errpid;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300577 bool timeout;
Arnaldo Carvalho de Melo04b34722013-08-26 11:36:30 -0300578 bool hexret;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300579} syscall_fmts[] = {
Arnaldo Carvalho de Melo51108992013-09-04 11:42:27 -0300580 { .name = "access", .errmsg = true,
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -0300581 .arg_scnprintf = { [1] = SCA_ACCMODE, /* mode */ }, },
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -0300582 { .name = "arch_prctl", .errmsg = true, .alias = "prctl", },
Arnaldo Carvalho de Melo729a7842015-10-29 11:48:18 -0300583 { .name = "bpf", .errmsg = true, STRARRAY(0, cmd, bpf_cmd), },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -0300584 { .name = "brk", .hexret = true,
585 .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, },
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -0300586 { .name = "chdir", .errmsg = true, },
587 { .name = "chmod", .errmsg = true, },
588 { .name = "chroot", .errmsg = true, },
David Ahern4f8c1b72013-09-22 19:45:00 -0600589 { .name = "clock_gettime", .errmsg = true, STRARRAY(0, clk_id, clockid), },
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -0300590 { .name = "clone", .errpid = true, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300591 { .name = "close", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300592 .arg_scnprintf = { [0] = SCA_CLOSE_FD, /* fd */ }, },
Arnaldo Carvalho de Meloa14bb862013-07-30 16:38:23 -0300593 { .name = "connect", .errmsg = true, },
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -0300594 { .name = "creat", .errmsg = true, },
Arnaldo Carvalho de Melob6565c92016-05-23 12:59:53 -0300595 { .name = "dup", .errmsg = true, },
596 { .name = "dup2", .errmsg = true, },
597 { .name = "dup3", .errmsg = true, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300598 { .name = "epoll_ctl", .errmsg = true, STRARRAY(1, op, epoll_ctl_ops), },
Arnaldo Carvalho de Melo49af9e92013-09-12 12:18:56 -0300599 { .name = "eventfd2", .errmsg = true,
600 .arg_scnprintf = { [1] = SCA_EFD_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -0300601 { .name = "faccessat", .errmsg = true, },
Arnaldo Carvalho de Melob6565c92016-05-23 12:59:53 -0300602 { .name = "fadvise64", .errmsg = true, },
603 { .name = "fallocate", .errmsg = true, },
604 { .name = "fchdir", .errmsg = true, },
605 { .name = "fchmod", .errmsg = true, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300606 { .name = "fchmodat", .errmsg = true,
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -0300607 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
Arnaldo Carvalho de Melob6565c92016-05-23 12:59:53 -0300608 { .name = "fchown", .errmsg = true, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300609 { .name = "fchownat", .errmsg = true,
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -0300610 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300611 { .name = "fcntl", .errmsg = true,
Arnaldo Carvalho de Melob6565c92016-05-23 12:59:53 -0300612 .arg_scnprintf = { [1] = SCA_STRARRAY, /* cmd */ },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300613 .arg_parm = { [1] = &strarray__fcntl_cmds, /* cmd */ }, },
Arnaldo Carvalho de Melob6565c92016-05-23 12:59:53 -0300614 { .name = "fdatasync", .errmsg = true, },
Arnaldo Carvalho de Melo5cea6ff2013-09-20 11:49:50 -0300615 { .name = "flock", .errmsg = true,
Arnaldo Carvalho de Melob6565c92016-05-23 12:59:53 -0300616 .arg_scnprintf = { [1] = SCA_FLOCK, /* cmd */ }, },
617 { .name = "fsetxattr", .errmsg = true, },
618 { .name = "fstat", .errmsg = true, .alias = "newfstat", },
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -0300619 { .name = "fstatat", .errmsg = true, .alias = "newfstatat", },
Arnaldo Carvalho de Melob6565c92016-05-23 12:59:53 -0300620 { .name = "fstatfs", .errmsg = true, },
621 { .name = "fsync", .errmsg = true, },
622 { .name = "ftruncate", .errmsg = true, },
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -0300623 { .name = "futex", .errmsg = true,
624 .arg_scnprintf = { [1] = SCA_FUTEX_OP, /* op */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300625 { .name = "futimesat", .errmsg = true,
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -0300626 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
Arnaldo Carvalho de Melob6565c92016-05-23 12:59:53 -0300627 { .name = "getdents", .errmsg = true, },
628 { .name = "getdents64", .errmsg = true, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300629 { .name = "getitimer", .errmsg = true, STRARRAY(0, which, itimers), },
Arnaldo Carvalho de Meloc65f1072016-04-06 14:55:18 -0300630 { .name = "getpid", .errpid = true, },
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -0300631 { .name = "getpgid", .errpid = true, },
Arnaldo Carvalho de Meloc65f1072016-04-06 14:55:18 -0300632 { .name = "getppid", .errpid = true, },
Arnaldo Carvalho de Melo39878d42016-03-30 20:02:15 -0300633 { .name = "getrandom", .errmsg = true,
634 .arg_scnprintf = { [2] = SCA_GETRANDOM_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300635 { .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -0300636 { .name = "getxattr", .errmsg = true, },
637 { .name = "inotify_add_watch", .errmsg = true, },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -0300638 { .name = "ioctl", .errmsg = true,
Arnaldo Carvalho de Melob6565c92016-05-23 12:59:53 -0300639 .arg_scnprintf = {
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -0300640#if defined(__i386__) || defined(__x86_64__)
641/*
642 * FIXME: Make this available to all arches.
643 */
Arnaldo Carvalho de Melo78645cf2013-10-08 17:43:20 -0300644 [1] = SCA_STRHEXARRAY, /* cmd */
645 [2] = SCA_HEX, /* arg */ },
646 .arg_parm = { [1] = &strarray__tioctls, /* cmd */ }, },
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -0300647#else
648 [2] = SCA_HEX, /* arg */ }, },
649#endif
Arnaldo Carvalho de Melob62bee12015-08-11 11:05:36 -0300650 { .name = "keyctl", .errmsg = true, STRARRAY(0, option, keyctl_options), },
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -0300651 { .name = "kill", .errmsg = true,
652 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -0300653 { .name = "lchown", .errmsg = true, },
654 { .name = "lgetxattr", .errmsg = true, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300655 { .name = "linkat", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300656 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -0300657 { .name = "listxattr", .errmsg = true, },
658 { .name = "llistxattr", .errmsg = true, },
659 { .name = "lremovexattr", .errmsg = true, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300660 { .name = "lseek", .errmsg = true,
Arnaldo Carvalho de Melob6565c92016-05-23 12:59:53 -0300661 .arg_scnprintf = { [2] = SCA_STRARRAY, /* whence */ },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300662 .arg_parm = { [2] = &strarray__whences, /* whence */ }, },
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -0300663 { .name = "lsetxattr", .errmsg = true, },
664 { .name = "lstat", .errmsg = true, .alias = "newlstat", },
665 { .name = "lsxattr", .errmsg = true, },
Arnaldo Carvalho de Melo9e9716d2013-08-23 10:06:41 -0300666 { .name = "madvise", .errmsg = true,
667 .arg_scnprintf = { [0] = SCA_HEX, /* start */
668 [2] = SCA_MADV_BHV, /* behavior */ }, },
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -0300669 { .name = "mkdir", .errmsg = true, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300670 { .name = "mkdirat", .errmsg = true,
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -0300671 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
672 { .name = "mknod", .errmsg = true, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300673 { .name = "mknodat", .errmsg = true,
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -0300674 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
Arnaldo Carvalho de Melo3d903aa2013-09-24 00:09:38 -0300675 { .name = "mlock", .errmsg = true,
676 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
677 { .name = "mlockall", .errmsg = true,
678 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -0300679 { .name = "mmap", .hexret = true,
Arnaldo Carvalho de Meloae685382013-08-20 17:44:42 -0300680 .arg_scnprintf = { [0] = SCA_HEX, /* addr */
Arnaldo Carvalho de Melo941557e2013-08-23 10:48:33 -0300681 [2] = SCA_MMAP_PROT, /* prot */
Arnaldo Carvalho de Melob6565c92016-05-23 12:59:53 -0300682 [3] = SCA_MMAP_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -0300683 { .name = "mprotect", .errmsg = true,
Arnaldo Carvalho de Meloae685382013-08-20 17:44:42 -0300684 .arg_scnprintf = { [0] = SCA_HEX, /* start */
685 [2] = SCA_MMAP_PROT, /* prot */ }, },
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -0300686 { .name = "mq_unlink", .errmsg = true,
687 .arg_scnprintf = { [0] = SCA_FILENAME, /* u_name */ }, },
Arnaldo Carvalho de Meloae685382013-08-20 17:44:42 -0300688 { .name = "mremap", .hexret = true,
689 .arg_scnprintf = { [0] = SCA_HEX, /* addr */
Alex Snast86998dd2014-08-13 18:42:40 +0300690 [3] = SCA_MREMAP_FLAGS, /* flags */
Arnaldo Carvalho de Meloae685382013-08-20 17:44:42 -0300691 [4] = SCA_HEX, /* new_addr */ }, },
Arnaldo Carvalho de Melo3d903aa2013-09-24 00:09:38 -0300692 { .name = "munlock", .errmsg = true,
693 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -0300694 { .name = "munmap", .errmsg = true,
695 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300696 { .name = "name_to_handle_at", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300697 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300698 { .name = "newfstatat", .errmsg = true,
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -0300699 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
Arnaldo Carvalho de Melobe65a892013-09-02 16:22:31 -0300700 { .name = "open", .errmsg = true,
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -0300701 .arg_scnprintf = { [1] = SCA_OPEN_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo31cd3852013-09-02 16:40:40 -0300702 { .name = "open_by_handle_at", .errmsg = true,
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300703 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
704 [2] = SCA_OPEN_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo31cd3852013-09-02 16:40:40 -0300705 { .name = "openat", .errmsg = true,
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300706 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
707 [2] = SCA_OPEN_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Meloa1c25522015-06-11 22:47:54 -0300708 { .name = "perf_event_open", .errmsg = true,
Arnaldo Carvalho de Meloccd9b2a2016-04-26 11:40:17 -0300709 .arg_scnprintf = { [2] = SCA_INT, /* cpu */
Arnaldo Carvalho de Meloa1c25522015-06-11 22:47:54 -0300710 [3] = SCA_FD, /* group_fd */
711 [4] = SCA_PERF_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo46cce192013-09-23 12:52:04 -0300712 { .name = "pipe2", .errmsg = true,
713 .arg_scnprintf = { [1] = SCA_PIPE_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -0300714 { .name = "poll", .errmsg = true, .timeout = true, },
715 { .name = "ppoll", .errmsg = true, .timeout = true, },
Arnaldo Carvalho de Melob6565c92016-05-23 12:59:53 -0300716 { .name = "pread", .errmsg = true, .alias = "pread64", },
717 { .name = "preadv", .errmsg = true, .alias = "pread", },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300718 { .name = "prlimit64", .errmsg = true, STRARRAY(1, resource, rlimit_resources), },
Arnaldo Carvalho de Melob6565c92016-05-23 12:59:53 -0300719 { .name = "pwrite", .errmsg = true, .alias = "pwrite64", },
720 { .name = "pwritev", .errmsg = true, },
721 { .name = "read", .errmsg = true, },
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -0300722 { .name = "readlink", .errmsg = true, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300723 { .name = "readlinkat", .errmsg = true,
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -0300724 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
Arnaldo Carvalho de Melob6565c92016-05-23 12:59:53 -0300725 { .name = "readv", .errmsg = true, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -0300726 { .name = "recvfrom", .errmsg = true,
Arnaldo Carvalho de Melob6565c92016-05-23 12:59:53 -0300727 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -0300728 { .name = "recvmmsg", .errmsg = true,
Arnaldo Carvalho de Melob6565c92016-05-23 12:59:53 -0300729 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -0300730 { .name = "recvmsg", .errmsg = true,
Arnaldo Carvalho de Melob6565c92016-05-23 12:59:53 -0300731 .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -0300732 { .name = "removexattr", .errmsg = true, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300733 { .name = "renameat", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300734 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -0300735 { .name = "rmdir", .errmsg = true, },
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -0300736 { .name = "rt_sigaction", .errmsg = true,
737 .arg_scnprintf = { [0] = SCA_SIGNUM, /* sig */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300738 { .name = "rt_sigprocmask", .errmsg = true, STRARRAY(0, how, sighow), },
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -0300739 { .name = "rt_sigqueueinfo", .errmsg = true,
740 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
741 { .name = "rt_tgsigqueueinfo", .errmsg = true,
742 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
Arnaldo Carvalho de Melof0bbd602016-09-28 13:45:38 -0300743 { .name = "sched_getattr", .errmsg = true, },
744 { .name = "sched_setattr", .errmsg = true, },
Arnaldo Carvalho de Meloa3bca912016-04-06 12:51:33 -0300745 { .name = "sched_setscheduler", .errmsg = true,
746 .arg_scnprintf = { [1] = SCA_SCHED_POLICY, /* policy */ }, },
Arnaldo Carvalho de Melo997bba82016-03-30 19:43:32 -0300747 { .name = "seccomp", .errmsg = true,
748 .arg_scnprintf = { [0] = SCA_SECCOMP_OP, /* op */
749 [1] = SCA_SECCOMP_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -0300750 { .name = "select", .errmsg = true, .timeout = true, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -0300751 { .name = "sendmmsg", .errmsg = true,
Arnaldo Carvalho de Melob6565c92016-05-23 12:59:53 -0300752 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -0300753 { .name = "sendmsg", .errmsg = true,
Arnaldo Carvalho de Melob6565c92016-05-23 12:59:53 -0300754 .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -0300755 { .name = "sendto", .errmsg = true,
Arnaldo Carvalho de Melob6565c92016-05-23 12:59:53 -0300756 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Meloc65f1072016-04-06 14:55:18 -0300757 { .name = "set_tid_address", .errpid = true, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300758 { .name = "setitimer", .errmsg = true, STRARRAY(0, which, itimers), },
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -0300759 { .name = "setpgid", .errmsg = true, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300760 { .name = "setrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -0300761 { .name = "setxattr", .errmsg = true, },
Arnaldo Carvalho de Melob6565c92016-05-23 12:59:53 -0300762 { .name = "shutdown", .errmsg = true, },
Arnaldo Carvalho de Meloe10bce82013-09-04 10:27:41 -0300763 { .name = "socket", .errmsg = true,
Arnaldo Carvalho de Meloa28b24b2013-09-04 11:00:44 -0300764 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
765 [1] = SCA_SK_TYPE, /* type */ },
Arnaldo Carvalho de Meloe10bce82013-09-04 10:27:41 -0300766 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, },
Arnaldo Carvalho de Melo07120aa2013-09-20 12:24:20 -0300767 { .name = "socketpair", .errmsg = true,
768 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
769 [1] = SCA_SK_TYPE, /* type */ },
770 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, },
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -0300771 { .name = "stat", .errmsg = true, .alias = "newstat", },
772 { .name = "statfs", .errmsg = true, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300773 { .name = "swapoff", .errmsg = true,
774 .arg_scnprintf = { [0] = SCA_FILENAME, /* specialfile */ }, },
775 { .name = "swapon", .errmsg = true,
776 .arg_scnprintf = { [0] = SCA_FILENAME, /* specialfile */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300777 { .name = "symlinkat", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300778 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -0300779 { .name = "tgkill", .errmsg = true,
780 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
781 { .name = "tkill", .errmsg = true,
782 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -0300783 { .name = "truncate", .errmsg = true, },
Arnaldo Carvalho de Meloe5959682013-08-26 12:21:41 -0300784 { .name = "uname", .errmsg = true, .alias = "newuname", },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300785 { .name = "unlinkat", .errmsg = true,
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -0300786 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
787 { .name = "utime", .errmsg = true, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300788 { .name = "utimensat", .errmsg = true,
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -0300789 .arg_scnprintf = { [0] = SCA_FDAT, /* dirfd */ }, },
790 { .name = "utimes", .errmsg = true, },
Arnaldo Carvalho de Melob6565c92016-05-23 12:59:53 -0300791 { .name = "vmsplice", .errmsg = true, },
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -0300792 { .name = "wait4", .errpid = true,
Arnaldo Carvalho de Melo7206b902016-04-06 14:11:36 -0300793 .arg_scnprintf = { [2] = SCA_WAITID_OPTIONS, /* options */ }, },
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -0300794 { .name = "waitid", .errpid = true,
Arnaldo Carvalho de Melo7206b902016-04-06 14:11:36 -0300795 .arg_scnprintf = { [3] = SCA_WAITID_OPTIONS, /* options */ }, },
Arnaldo Carvalho de Melob6565c92016-05-23 12:59:53 -0300796 { .name = "write", .errmsg = true, },
797 { .name = "writev", .errmsg = true, },
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300798};
799
800static int syscall_fmt__cmp(const void *name, const void *fmtp)
801{
802 const struct syscall_fmt *fmt = fmtp;
803 return strcmp(name, fmt->name);
804}
805
806static struct syscall_fmt *syscall_fmt__find(const char *name)
807{
808 const int nmemb = ARRAY_SIZE(syscall_fmts);
809 return bsearch(name, syscall_fmts, nmemb, sizeof(struct syscall_fmt), syscall_fmt__cmp);
810}
811
812struct syscall {
813 struct event_format *tp_format;
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -0300814 int nr_args;
815 struct format_field *args;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300816 const char *name;
Arnaldo Carvalho de Melo5089f202014-06-17 14:29:24 -0300817 bool is_exit;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300818 struct syscall_fmt *fmt;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300819 size_t (**arg_scnprintf)(char *bf, size_t size, struct syscall_arg *arg);
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300820 void **arg_parm;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300821};
822
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -0200823static size_t fprintf_duration(unsigned long t, FILE *fp)
824{
825 double duration = (double)t / NSEC_PER_MSEC;
826 size_t printed = fprintf(fp, "(");
827
828 if (duration >= 1.0)
829 printed += color_fprintf(fp, PERF_COLOR_RED, "%6.3f ms", duration);
830 else if (duration >= 0.01)
831 printed += color_fprintf(fp, PERF_COLOR_YELLOW, "%6.3f ms", duration);
832 else
833 printed += color_fprintf(fp, PERF_COLOR_NORMAL, "%6.3f ms", duration);
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -0300834 return printed + fprintf(fp, "): ");
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -0200835}
836
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -0300837/**
838 * filename.ptr: The filename char pointer that will be vfs_getname'd
839 * filename.entry_str_pos: Where to insert the string translated from
840 * filename.ptr by the vfs_getname tracepoint/kprobe.
841 */
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300842struct thread_trace {
843 u64 entry_time;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300844 bool entry_pending;
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -0300845 unsigned long nr_events;
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +0400846 unsigned long pfmaj, pfmin;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300847 char *entry_str;
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -0300848 double runtime_ms;
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -0300849 struct {
850 unsigned long ptr;
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -0300851 short int entry_str_pos;
852 bool pending_open;
853 unsigned int namelen;
854 char *name;
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -0300855 } filename;
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300856 struct {
857 int max;
858 char **table;
859 } paths;
David Ahernbf2575c2013-10-08 21:26:53 -0600860
861 struct intlist *syscall_stats;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300862};
863
864static struct thread_trace *thread_trace__new(void)
865{
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300866 struct thread_trace *ttrace = zalloc(sizeof(struct thread_trace));
867
868 if (ttrace)
869 ttrace->paths.max = -1;
870
David Ahernbf2575c2013-10-08 21:26:53 -0600871 ttrace->syscall_stats = intlist__new(NULL);
872
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300873 return ttrace;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300874}
875
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -0300876static struct thread_trace *thread__trace(struct thread *thread, FILE *fp)
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300877{
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -0300878 struct thread_trace *ttrace;
879
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300880 if (thread == NULL)
881 goto fail;
882
Namhyung Kim89dceb22014-10-06 09:46:03 +0900883 if (thread__priv(thread) == NULL)
884 thread__set_priv(thread, thread_trace__new());
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300885
Namhyung Kim89dceb22014-10-06 09:46:03 +0900886 if (thread__priv(thread) == NULL)
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300887 goto fail;
888
Namhyung Kim89dceb22014-10-06 09:46:03 +0900889 ttrace = thread__priv(thread);
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -0300890 ++ttrace->nr_events;
891
892 return ttrace;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300893fail:
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -0300894 color_fprintf(fp, PERF_COLOR_RED,
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300895 "WARNING: not enough memory, dropping samples!\n");
896 return NULL;
897}
898
Stanislav Fomichev598d02c2014-06-26 20:14:25 +0400899#define TRACE_PFMAJ (1 << 0)
900#define TRACE_PFMIN (1 << 1)
901
Arnaldo Carvalho de Meloe4d44e82015-08-04 22:17:29 -0300902static const size_t trace__entry_str_size = 2048;
903
Arnaldo Carvalho de Melo97119f32013-09-27 17:34:10 -0300904static int trace__set_fd_pathname(struct thread *thread, int fd, const char *pathname)
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300905{
Namhyung Kim89dceb22014-10-06 09:46:03 +0900906 struct thread_trace *ttrace = thread__priv(thread);
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300907
908 if (fd > ttrace->paths.max) {
909 char **npath = realloc(ttrace->paths.table, (fd + 1) * sizeof(char *));
910
911 if (npath == NULL)
912 return -1;
913
914 if (ttrace->paths.max != -1) {
915 memset(npath + ttrace->paths.max + 1, 0,
916 (fd - ttrace->paths.max) * sizeof(char *));
917 } else {
918 memset(npath, 0, (fd + 1) * sizeof(char *));
919 }
920
921 ttrace->paths.table = npath;
922 ttrace->paths.max = fd;
923 }
924
925 ttrace->paths.table[fd] = strdup(pathname);
926
927 return ttrace->paths.table[fd] != NULL ? 0 : -1;
928}
929
Arnaldo Carvalho de Melo97119f32013-09-27 17:34:10 -0300930static int thread__read_fd_path(struct thread *thread, int fd)
931{
932 char linkname[PATH_MAX], pathname[PATH_MAX];
933 struct stat st;
934 int ret;
935
936 if (thread->pid_ == thread->tid) {
937 scnprintf(linkname, sizeof(linkname),
938 "/proc/%d/fd/%d", thread->pid_, fd);
939 } else {
940 scnprintf(linkname, sizeof(linkname),
941 "/proc/%d/task/%d/fd/%d", thread->pid_, thread->tid, fd);
942 }
943
944 if (lstat(linkname, &st) < 0 || st.st_size + 1 > (off_t)sizeof(pathname))
945 return -1;
946
947 ret = readlink(linkname, pathname, sizeof(pathname));
948
949 if (ret < 0 || ret > st.st_size)
950 return -1;
951
952 pathname[ret] = '\0';
953 return trace__set_fd_pathname(thread, fd, pathname);
954}
955
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -0300956static const char *thread__fd_path(struct thread *thread, int fd,
957 struct trace *trace)
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300958{
Namhyung Kim89dceb22014-10-06 09:46:03 +0900959 struct thread_trace *ttrace = thread__priv(thread);
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300960
961 if (ttrace == NULL)
962 return NULL;
963
964 if (fd < 0)
965 return NULL;
966
Arnaldo Carvalho de Melocdcd1e62014-06-10 16:00:18 -0300967 if ((fd > ttrace->paths.max || ttrace->paths.table[fd] == NULL)) {
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -0300968 if (!trace->live)
969 return NULL;
970 ++trace->stats.proc_getname;
Arnaldo Carvalho de Melocdcd1e62014-06-10 16:00:18 -0300971 if (thread__read_fd_path(thread, fd))
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -0300972 return NULL;
973 }
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300974
975 return ttrace->paths.table[fd];
976}
977
978static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
979 struct syscall_arg *arg)
980{
981 int fd = arg->val;
982 size_t printed = scnprintf(bf, size, "%d", fd);
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -0300983 const char *path = thread__fd_path(arg->thread, fd, arg->trace);
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300984
985 if (path)
986 printed += scnprintf(bf + printed, size - printed, "<%s>", path);
987
988 return printed;
989}
990
991static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
992 struct syscall_arg *arg)
993{
994 int fd = arg->val;
995 size_t printed = syscall_arg__scnprintf_fd(bf, size, arg);
Namhyung Kim89dceb22014-10-06 09:46:03 +0900996 struct thread_trace *ttrace = thread__priv(arg->thread);
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300997
Arnaldo Carvalho de Melo04662522013-12-26 17:41:15 -0300998 if (ttrace && fd >= 0 && fd <= ttrace->paths.max)
999 zfree(&ttrace->paths.table[fd]);
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001000
1001 return printed;
1002}
1003
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001004static void thread__set_filename_pos(struct thread *thread, const char *bf,
1005 unsigned long ptr)
1006{
1007 struct thread_trace *ttrace = thread__priv(thread);
1008
1009 ttrace->filename.ptr = ptr;
1010 ttrace->filename.entry_str_pos = bf - ttrace->entry_str;
1011}
1012
1013static size_t syscall_arg__scnprintf_filename(char *bf, size_t size,
1014 struct syscall_arg *arg)
1015{
1016 unsigned long ptr = arg->val;
1017
1018 if (!arg->trace->vfs_getname)
1019 return scnprintf(bf, size, "%#x", ptr);
1020
1021 thread__set_filename_pos(arg->thread, bf, ptr);
1022 return 0;
1023}
1024
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001025static bool trace__filter_duration(struct trace *trace, double t)
1026{
1027 return t < (trace->duration_filter * NSEC_PER_MSEC);
1028}
1029
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001030static size_t trace__fprintf_tstamp(struct trace *trace, u64 tstamp, FILE *fp)
1031{
1032 double ts = (double)(tstamp - trace->base_time) / NSEC_PER_MSEC;
1033
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001034 return fprintf(fp, "%10.3f ", ts);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001035}
1036
Namhyung Kimf15eb532012-10-05 14:02:16 +09001037static bool done = false;
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03001038static bool interrupted = false;
Namhyung Kimf15eb532012-10-05 14:02:16 +09001039
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03001040static void sig_handler(int sig)
Namhyung Kimf15eb532012-10-05 14:02:16 +09001041{
1042 done = true;
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03001043 interrupted = sig == SIGINT;
Namhyung Kimf15eb532012-10-05 14:02:16 +09001044}
1045
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001046static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thread,
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001047 u64 duration, u64 tstamp, FILE *fp)
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001048{
1049 size_t printed = trace__fprintf_tstamp(trace, tstamp, fp);
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001050 printed += fprintf_duration(duration, fp);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001051
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -03001052 if (trace->multiple_threads) {
1053 if (trace->show_comm)
Frederic Weisbecker1902efe2013-09-11 16:56:44 +02001054 printed += fprintf(fp, "%.14s/", thread__comm_str(thread));
Adrian Hunter38051232013-07-04 16:20:31 +03001055 printed += fprintf(fp, "%d ", thread->tid);
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -03001056 }
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001057
1058 return printed;
1059}
1060
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001061static int trace__process_event(struct trace *trace, struct machine *machine,
Frederic Weisbecker162f0be2013-09-11 16:18:24 +02001062 union perf_event *event, struct perf_sample *sample)
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001063{
1064 int ret = 0;
1065
1066 switch (event->header.type) {
1067 case PERF_RECORD_LOST:
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001068 color_fprintf(trace->output, PERF_COLOR_RED,
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001069 "LOST %" PRIu64 " events!\n", event->lost.lost);
Frederic Weisbecker162f0be2013-09-11 16:18:24 +02001070 ret = machine__process_lost_event(machine, event, sample);
Arnaldo Carvalho de Melo3ed5ca22016-03-30 16:51:17 -03001071 break;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001072 default:
Frederic Weisbecker162f0be2013-09-11 16:18:24 +02001073 ret = machine__process_event(machine, event, sample);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001074 break;
1075 }
1076
1077 return ret;
1078}
1079
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001080static int trace__tool_process(struct perf_tool *tool,
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001081 union perf_event *event,
Frederic Weisbecker162f0be2013-09-11 16:18:24 +02001082 struct perf_sample *sample,
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001083 struct machine *machine)
1084{
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001085 struct trace *trace = container_of(tool, struct trace, tool);
Frederic Weisbecker162f0be2013-09-11 16:18:24 +02001086 return trace__process_event(trace, machine, event, sample);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001087}
1088
Arnaldo Carvalho de Melocaf8a0d2016-05-17 11:56:24 -03001089static char *trace__machine__resolve_kernel_addr(void *vmachine, unsigned long long *addrp, char **modp)
1090{
1091 struct machine *machine = vmachine;
1092
1093 if (machine->kptr_restrict_warned)
1094 return NULL;
1095
1096 if (symbol_conf.kptr_restrict) {
1097 pr_warning("Kernel address maps (/proc/{kallsyms,modules}) are restricted.\n\n"
1098 "Check /proc/sys/kernel/kptr_restrict.\n\n"
1099 "Kernel samples will not be resolved.\n");
1100 machine->kptr_restrict_warned = true;
1101 return NULL;
1102 }
1103
1104 return machine__resolve_kernel_addr(vmachine, addrp, modp);
1105}
1106
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001107static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
1108{
Namhyung Kim0a7e6d12014-08-12 15:40:45 +09001109 int err = symbol__init(NULL);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001110
1111 if (err)
1112 return err;
1113
David Ahern8fb598e2013-09-28 13:13:00 -06001114 trace->host = machine__new_host();
1115 if (trace->host == NULL)
1116 return -ENOMEM;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001117
Arnaldo Carvalho de Melocaf8a0d2016-05-17 11:56:24 -03001118 if (trace_event__register_resolver(trace->host, trace__machine__resolve_kernel_addr) < 0)
Arnaldo Carvalho de Melo706c3da2015-07-22 16:16:16 -03001119 return -errno;
1120
Arnaldo Carvalho de Meloa33fbd52013-11-11 11:36:12 -03001121 err = __machine__synthesize_threads(trace->host, &trace->tool, &trace->opts.target,
Kan Liang9d9cad72015-06-17 09:51:11 -04001122 evlist->threads, trace__tool_process, false,
1123 trace->opts.proc_map_timeout);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001124 if (err)
1125 symbol__exit();
1126
1127 return err;
1128}
1129
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001130static int syscall__set_arg_fmts(struct syscall *sc)
1131{
1132 struct format_field *field;
Arnaldo Carvalho de Melob6565c92016-05-23 12:59:53 -03001133 int idx = 0, len;
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001134
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001135 sc->arg_scnprintf = calloc(sc->nr_args, sizeof(void *));
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001136 if (sc->arg_scnprintf == NULL)
1137 return -1;
1138
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -03001139 if (sc->fmt)
1140 sc->arg_parm = sc->fmt->arg_parm;
1141
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001142 for (field = sc->args; field; field = field->next) {
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -03001143 if (sc->fmt && sc->fmt->arg_scnprintf[idx])
1144 sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx];
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -03001145 else if (strcmp(field->type, "const char *") == 0 &&
1146 (strcmp(field->name, "filename") == 0 ||
1147 strcmp(field->name, "path") == 0 ||
1148 strcmp(field->name, "pathname") == 0))
1149 sc->arg_scnprintf[idx] = SCA_FILENAME;
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -03001150 else if (field->flags & FIELD_IS_POINTER)
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001151 sc->arg_scnprintf[idx] = syscall_arg__scnprintf_hex;
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -03001152 else if (strcmp(field->type, "pid_t") == 0)
1153 sc->arg_scnprintf[idx] = SCA_PID;
Arnaldo Carvalho de Meloba2f22c2016-04-07 12:05:51 -03001154 else if (strcmp(field->type, "umode_t") == 0)
1155 sc->arg_scnprintf[idx] = SCA_MODE_T;
Arnaldo Carvalho de Melob6565c92016-05-23 12:59:53 -03001156 else if ((strcmp(field->type, "int") == 0 ||
1157 strcmp(field->type, "unsigned int") == 0 ||
1158 strcmp(field->type, "long") == 0) &&
1159 (len = strlen(field->name)) >= 2 &&
1160 strcmp(field->name + len - 2, "fd") == 0) {
1161 /*
1162 * /sys/kernel/tracing/events/syscalls/sys_enter*
1163 * egrep 'field:.*fd;' .../format|sed -r 's/.*field:([a-z ]+) [a-z_]*fd.+/\1/g'|sort|uniq -c
1164 * 65 int
1165 * 23 unsigned int
1166 * 7 unsigned long
1167 */
1168 sc->arg_scnprintf[idx] = SCA_FD;
1169 }
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001170 ++idx;
1171 }
1172
1173 return 0;
1174}
1175
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001176static int trace__read_syscall_info(struct trace *trace, int id)
1177{
1178 char tp_name[128];
1179 struct syscall *sc;
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03001180 const char *name = syscalltbl__name(trace->sctbl, id);
Arnaldo Carvalho de Melo3a531262012-10-20 12:39:03 -03001181
1182 if (name == NULL)
1183 return -1;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001184
1185 if (id > trace->syscalls.max) {
1186 struct syscall *nsyscalls = realloc(trace->syscalls.table, (id + 1) * sizeof(*sc));
1187
1188 if (nsyscalls == NULL)
1189 return -1;
1190
1191 if (trace->syscalls.max != -1) {
1192 memset(nsyscalls + trace->syscalls.max + 1, 0,
1193 (id - trace->syscalls.max) * sizeof(*sc));
1194 } else {
1195 memset(nsyscalls, 0, (id + 1) * sizeof(*sc));
1196 }
1197
1198 trace->syscalls.table = nsyscalls;
1199 trace->syscalls.max = id;
1200 }
1201
1202 sc = trace->syscalls.table + id;
Arnaldo Carvalho de Melo3a531262012-10-20 12:39:03 -03001203 sc->name = name;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001204
Arnaldo Carvalho de Melo3a531262012-10-20 12:39:03 -03001205 sc->fmt = syscall_fmt__find(sc->name);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001206
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -03001207 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name);
Jiri Olsa97978b32013-12-03 14:09:24 +01001208 sc->tp_format = trace_event__tp_format("syscalls", tp_name);
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -03001209
Jiri Olsa8dd2a132015-09-07 10:38:06 +02001210 if (IS_ERR(sc->tp_format) && sc->fmt && sc->fmt->alias) {
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -03001211 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->fmt->alias);
Jiri Olsa97978b32013-12-03 14:09:24 +01001212 sc->tp_format = trace_event__tp_format("syscalls", tp_name);
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -03001213 }
1214
Jiri Olsa8dd2a132015-09-07 10:38:06 +02001215 if (IS_ERR(sc->tp_format))
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001216 return -1;
1217
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001218 sc->args = sc->tp_format->format.fields;
1219 sc->nr_args = sc->tp_format->format.nr_fields;
Taeung Songc42de702016-02-26 22:14:25 +09001220 /*
1221 * We need to check and discard the first variable '__syscall_nr'
1222 * or 'nr' that mean the syscall number. It is needless here.
1223 * So drop '__syscall_nr' or 'nr' field but does not exist on older kernels.
1224 */
1225 if (sc->args && (!strcmp(sc->args->name, "__syscall_nr") || !strcmp(sc->args->name, "nr"))) {
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001226 sc->args = sc->args->next;
1227 --sc->nr_args;
1228 }
1229
Arnaldo Carvalho de Melo5089f202014-06-17 14:29:24 -03001230 sc->is_exit = !strcmp(name, "exit_group") || !strcmp(name, "exit");
1231
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001232 return syscall__set_arg_fmts(sc);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001233}
1234
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001235static int trace__validate_ev_qualifier(struct trace *trace)
1236{
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001237 int err = 0, i;
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001238 struct str_node *pos;
1239
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001240 trace->ev_qualifier_ids.nr = strlist__nr_entries(trace->ev_qualifier);
1241 trace->ev_qualifier_ids.entries = malloc(trace->ev_qualifier_ids.nr *
1242 sizeof(trace->ev_qualifier_ids.entries[0]));
1243
1244 if (trace->ev_qualifier_ids.entries == NULL) {
1245 fputs("Error:\tNot enough memory for allocating events qualifier ids\n",
1246 trace->output);
1247 err = -EINVAL;
1248 goto out;
1249 }
1250
1251 i = 0;
1252
Arnaldo Carvalho de Melo602a1f42016-06-23 11:31:20 -03001253 strlist__for_each_entry(pos, trace->ev_qualifier) {
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001254 const char *sc = pos->s;
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03001255 int id = syscalltbl__id(trace->sctbl, sc);
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001256
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001257 if (id < 0) {
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001258 if (err == 0) {
1259 fputs("Error:\tInvalid syscall ", trace->output);
1260 err = -EINVAL;
1261 } else {
1262 fputs(", ", trace->output);
1263 }
1264
1265 fputs(sc, trace->output);
1266 }
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001267
1268 trace->ev_qualifier_ids.entries[i++] = id;
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001269 }
1270
1271 if (err < 0) {
1272 fputs("\nHint:\ttry 'perf list syscalls:sys_enter_*'"
1273 "\nHint:\tand: 'man syscalls'\n", trace->output);
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001274 zfree(&trace->ev_qualifier_ids.entries);
1275 trace->ev_qualifier_ids.nr = 0;
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001276 }
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001277out:
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001278 return err;
1279}
1280
David Ahern55d43bc2015-02-19 15:00:22 -05001281/*
1282 * args is to be interpreted as a series of longs but we need to handle
1283 * 8-byte unaligned accesses. args points to raw_data within the event
1284 * and raw_data is guaranteed to be 8-byte unaligned because it is
1285 * preceded by raw_size which is a u32. So we need to copy args to a temp
1286 * variable to read it. Most notably this avoids extended load instructions
1287 * on unaligned addresses
1288 */
1289
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001290static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
David Ahern55d43bc2015-02-19 15:00:22 -05001291 unsigned char *args, struct trace *trace,
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001292 struct thread *thread)
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001293{
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001294 size_t printed = 0;
David Ahern55d43bc2015-02-19 15:00:22 -05001295 unsigned char *p;
1296 unsigned long val;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001297
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001298 if (sc->args != NULL) {
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001299 struct format_field *field;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001300 u8 bit = 1;
1301 struct syscall_arg arg = {
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001302 .idx = 0,
1303 .mask = 0,
1304 .trace = trace,
1305 .thread = thread,
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001306 };
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001307
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001308 for (field = sc->args; field;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001309 field = field->next, ++arg.idx, bit <<= 1) {
1310 if (arg.mask & bit)
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -03001311 continue;
David Ahern55d43bc2015-02-19 15:00:22 -05001312
1313 /* special care for unaligned accesses */
1314 p = args + sizeof(unsigned long) * arg.idx;
1315 memcpy(&val, p, sizeof(val));
1316
Arnaldo Carvalho de Melo4aa58232013-09-20 12:19:41 -03001317 /*
1318 * Suppress this argument if its value is zero and
1319 * and we don't have a string associated in an
1320 * strarray for it.
1321 */
David Ahern55d43bc2015-02-19 15:00:22 -05001322 if (val == 0 &&
Arnaldo Carvalho de Melo4aa58232013-09-20 12:19:41 -03001323 !(sc->arg_scnprintf &&
1324 sc->arg_scnprintf[arg.idx] == SCA_STRARRAY &&
1325 sc->arg_parm[arg.idx]))
Arnaldo Carvalho de Melo22ae5cf12013-09-12 11:27:34 -03001326 continue;
1327
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001328 printed += scnprintf(bf + printed, size - printed,
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001329 "%s%s: ", printed ? ", " : "", field->name);
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001330 if (sc->arg_scnprintf && sc->arg_scnprintf[arg.idx]) {
David Ahern55d43bc2015-02-19 15:00:22 -05001331 arg.val = val;
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -03001332 if (sc->arg_parm)
1333 arg.parm = sc->arg_parm[arg.idx];
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001334 printed += sc->arg_scnprintf[arg.idx](bf + printed,
1335 size - printed, &arg);
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -03001336 } else {
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001337 printed += scnprintf(bf + printed, size - printed,
David Ahern55d43bc2015-02-19 15:00:22 -05001338 "%ld", val);
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -03001339 }
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001340 }
Arnaldo Carvalho de Melo4c4d6e52016-05-05 23:38:05 -03001341 } else if (IS_ERR(sc->tp_format)) {
1342 /*
1343 * If we managed to read the tracepoint /format file, then we
1344 * may end up not having any args, like with gettid(), so only
1345 * print the raw args when we didn't manage to read it.
1346 */
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001347 int i = 0;
1348
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001349 while (i < 6) {
David Ahern55d43bc2015-02-19 15:00:22 -05001350 /* special care for unaligned accesses */
1351 p = args + sizeof(unsigned long) * i;
1352 memcpy(&val, p, sizeof(val));
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001353 printed += scnprintf(bf + printed, size - printed,
1354 "%sarg%d: %ld",
David Ahern55d43bc2015-02-19 15:00:22 -05001355 printed ? ", " : "", i, val);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001356 ++i;
1357 }
1358 }
1359
1360 return printed;
1361}
1362
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001363typedef int (*tracepoint_handler)(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04001364 union perf_event *event,
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001365 struct perf_sample *sample);
1366
1367static struct syscall *trace__syscall_info(struct trace *trace,
David Ahernbf2575c2013-10-08 21:26:53 -06001368 struct perf_evsel *evsel, int id)
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001369{
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001370
1371 if (id < 0) {
Arnaldo Carvalho de Meloadaa18b2013-08-22 17:55:25 -03001372
1373 /*
1374 * XXX: Noticed on x86_64, reproduced as far back as 3.0.36, haven't tried
1375 * before that, leaving at a higher verbosity level till that is
1376 * explained. Reproduced with plain ftrace with:
1377 *
1378 * echo 1 > /t/events/raw_syscalls/sys_exit/enable
1379 * grep "NR -1 " /t/trace_pipe
1380 *
1381 * After generating some load on the machine.
1382 */
1383 if (verbose > 1) {
1384 static u64 n;
1385 fprintf(trace->output, "Invalid syscall %d id, skipping (%s, %" PRIu64 ") ...\n",
1386 id, perf_evsel__name(evsel), ++n);
1387 }
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001388 return NULL;
1389 }
1390
1391 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL) &&
1392 trace__read_syscall_info(trace, id))
1393 goto out_cant_read;
1394
1395 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL))
1396 goto out_cant_read;
1397
1398 return &trace->syscalls.table[id];
1399
1400out_cant_read:
Arnaldo Carvalho de Melo7c304ee02013-08-22 16:49:54 -03001401 if (verbose) {
1402 fprintf(trace->output, "Problems reading syscall %d", id);
1403 if (id <= trace->syscalls.max && trace->syscalls.table[id].name != NULL)
1404 fprintf(trace->output, "(%s)", trace->syscalls.table[id].name);
1405 fputs(" information\n", trace->output);
1406 }
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001407 return NULL;
1408}
1409
David Ahernbf2575c2013-10-08 21:26:53 -06001410static void thread__update_stats(struct thread_trace *ttrace,
1411 int id, struct perf_sample *sample)
1412{
1413 struct int_node *inode;
1414 struct stats *stats;
1415 u64 duration = 0;
1416
1417 inode = intlist__findnew(ttrace->syscall_stats, id);
1418 if (inode == NULL)
1419 return;
1420
1421 stats = inode->priv;
1422 if (stats == NULL) {
1423 stats = malloc(sizeof(struct stats));
1424 if (stats == NULL)
1425 return;
1426 init_stats(stats);
1427 inode->priv = stats;
1428 }
1429
1430 if (ttrace->entry_time && sample->time > ttrace->entry_time)
1431 duration = sample->time - ttrace->entry_time;
1432
1433 update_stats(stats, duration);
1434}
1435
Arnaldo Carvalho de Meloe5966632015-02-13 13:22:21 -03001436static int trace__printf_interrupted_entry(struct trace *trace, struct perf_sample *sample)
1437{
1438 struct thread_trace *ttrace;
1439 u64 duration;
1440 size_t printed;
1441
1442 if (trace->current == NULL)
1443 return 0;
1444
1445 ttrace = thread__priv(trace->current);
1446
1447 if (!ttrace->entry_pending)
1448 return 0;
1449
1450 duration = sample->time - ttrace->entry_time;
1451
Arnaldo Carvalho de Meloecf1e222016-10-18 11:28:32 -03001452 printed = trace__fprintf_entry_head(trace, trace->current, duration, ttrace->entry_time, trace->output);
Arnaldo Carvalho de Meloe5966632015-02-13 13:22:21 -03001453 printed += fprintf(trace->output, "%-70s) ...\n", ttrace->entry_str);
1454 ttrace->entry_pending = false;
1455
1456 return printed;
1457}
1458
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001459static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04001460 union perf_event *event __maybe_unused,
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001461 struct perf_sample *sample)
1462{
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001463 char *msg;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001464 void *args;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001465 size_t printed = 0;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001466 struct thread *thread;
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001467 int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
David Ahernbf2575c2013-10-08 21:26:53 -06001468 struct syscall *sc = trace__syscall_info(trace, evsel, id);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001469 struct thread_trace *ttrace;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001470
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001471 if (sc == NULL)
1472 return -1;
1473
David Ahern8fb598e2013-09-28 13:13:00 -06001474 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001475 ttrace = thread__trace(thread, trace->output);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001476 if (ttrace == NULL)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001477 goto out_put;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001478
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -03001479 args = perf_evsel__sc_tp_ptr(evsel, args, sample);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001480
1481 if (ttrace->entry_str == NULL) {
Arnaldo Carvalho de Meloe4d44e82015-08-04 22:17:29 -03001482 ttrace->entry_str = malloc(trace__entry_str_size);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001483 if (!ttrace->entry_str)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001484 goto out_put;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001485 }
1486
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -03001487 if (!(trace->duration_filter || trace->summary_only || trace->min_stack))
Arnaldo Carvalho de Melo6ebad5c2015-03-25 18:01:15 -03001488 trace__printf_interrupted_entry(trace, sample);
Arnaldo Carvalho de Meloe5966632015-02-13 13:22:21 -03001489
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001490 ttrace->entry_time = sample->time;
1491 msg = ttrace->entry_str;
Arnaldo Carvalho de Meloe4d44e82015-08-04 22:17:29 -03001492 printed += scnprintf(msg + printed, trace__entry_str_size - printed, "%s(", sc->name);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001493
Arnaldo Carvalho de Meloe4d44e82015-08-04 22:17:29 -03001494 printed += syscall__scnprintf_args(sc, msg + printed, trace__entry_str_size - printed,
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001495 args, trace, thread);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001496
Arnaldo Carvalho de Melo5089f202014-06-17 14:29:24 -03001497 if (sc->is_exit) {
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -03001498 if (!(trace->duration_filter || trace->summary_only || trace->min_stack)) {
Arnaldo Carvalho de Meloecf1e222016-10-18 11:28:32 -03001499 trace__fprintf_entry_head(trace, thread, 1, ttrace->entry_time, trace->output);
Arnaldo Carvalho de Meloc008f782016-05-17 12:13:54 -03001500 fprintf(trace->output, "%-70s)\n", ttrace->entry_str);
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001501 }
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03001502 } else {
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001503 ttrace->entry_pending = true;
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03001504 /* See trace__vfs_getname & trace__sys_exit */
1505 ttrace->filename.pending_open = false;
1506 }
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001507
Arnaldo Carvalho de Melof3b623b2015-03-02 22:21:35 -03001508 if (trace->current != thread) {
1509 thread__put(trace->current);
1510 trace->current = thread__get(thread);
1511 }
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001512 err = 0;
1513out_put:
1514 thread__put(thread);
1515 return err;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001516}
1517
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -03001518static int trace__resolve_callchain(struct trace *trace, struct perf_evsel *evsel,
1519 struct perf_sample *sample,
1520 struct callchain_cursor *cursor)
Arnaldo Carvalho de Melo202ff962016-04-12 10:11:07 -03001521{
1522 struct addr_location al;
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -03001523
1524 if (machine__resolve(trace->host, &al, sample) < 0 ||
1525 thread__resolve_callchain(al.thread, cursor, evsel, sample, NULL, NULL, trace->max_stack))
1526 return -1;
1527
1528 return 0;
1529}
1530
1531static int trace__fprintf_callchain(struct trace *trace, struct perf_sample *sample)
1532{
Arnaldo Carvalho de Melo202ff962016-04-12 10:11:07 -03001533 /* TODO: user-configurable print_opts */
Arnaldo Carvalho de Meloe20ab862016-04-12 15:16:15 -03001534 const unsigned int print_opts = EVSEL__PRINT_SYM |
1535 EVSEL__PRINT_DSO |
1536 EVSEL__PRINT_UNKNOWN_AS_ADDR;
Arnaldo Carvalho de Melo202ff962016-04-12 10:11:07 -03001537
Arnaldo Carvalho de Melod327e602016-04-14 17:53:49 -03001538 return sample__fprintf_callchain(sample, 38, print_opts, &callchain_cursor, trace->output);
Arnaldo Carvalho de Melo202ff962016-04-12 10:11:07 -03001539}
1540
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001541static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04001542 union perf_event *event __maybe_unused,
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001543 struct perf_sample *sample)
1544{
Chang Hyun Park2c82c3a2014-09-26 21:54:01 +09001545 long ret;
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001546 u64 duration = 0;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001547 struct thread *thread;
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -03001548 int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1, callchain_ret = 0;
David Ahernbf2575c2013-10-08 21:26:53 -06001549 struct syscall *sc = trace__syscall_info(trace, evsel, id);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001550 struct thread_trace *ttrace;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001551
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001552 if (sc == NULL)
1553 return -1;
1554
David Ahern8fb598e2013-09-28 13:13:00 -06001555 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001556 ttrace = thread__trace(thread, trace->output);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001557 if (ttrace == NULL)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001558 goto out_put;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001559
David Ahernbf2575c2013-10-08 21:26:53 -06001560 if (trace->summary)
1561 thread__update_stats(ttrace, id, sample);
1562
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -03001563 ret = perf_evsel__sc_tp_uint(evsel, ret, sample);
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001564
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03001565 if (id == trace->open_id && ret >= 0 && ttrace->filename.pending_open) {
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03001566 trace__set_fd_pathname(thread, ret, ttrace->filename.name);
1567 ttrace->filename.pending_open = false;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001568 ++trace->stats.vfs_getname;
1569 }
1570
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001571 if (ttrace->entry_time) {
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001572 duration = sample->time - ttrace->entry_time;
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001573 if (trace__filter_duration(trace, duration))
1574 goto out;
1575 } else if (trace->duration_filter)
1576 goto out;
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001577
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -03001578 if (sample->callchain) {
1579 callchain_ret = trace__resolve_callchain(trace, evsel, sample, &callchain_cursor);
1580 if (callchain_ret == 0) {
1581 if (callchain_cursor.nr < trace->min_stack)
1582 goto out;
1583 callchain_ret = 1;
1584 }
1585 }
1586
David Ahernfd2eaba2013-11-12 09:31:15 -07001587 if (trace->summary_only)
1588 goto out;
1589
Arnaldo Carvalho de Meloecf1e222016-10-18 11:28:32 -03001590 trace__fprintf_entry_head(trace, thread, duration, ttrace->entry_time, trace->output);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001591
1592 if (ttrace->entry_pending) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001593 fprintf(trace->output, "%-70s", ttrace->entry_str);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001594 } else {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001595 fprintf(trace->output, " ... [");
1596 color_fprintf(trace->output, PERF_COLOR_YELLOW, "continued");
1597 fprintf(trace->output, "]: %s()", sc->name);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001598 }
1599
Arnaldo Carvalho de Meloda3c9a42013-08-26 11:28:34 -03001600 if (sc->fmt == NULL) {
1601signed_print:
Chang Hyun Park2c82c3a2014-09-26 21:54:01 +09001602 fprintf(trace->output, ") = %ld", ret);
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -03001603 } else if (ret < 0 && (sc->fmt->errmsg || sc->fmt->errpid)) {
Masami Hiramatsu942a91e2014-08-14 02:22:41 +00001604 char bf[STRERR_BUFSIZE];
Arnaldo Carvalho de Meloc8b5f2c2016-07-06 11:56:20 -03001605 const char *emsg = str_error_r(-ret, bf, sizeof(bf)),
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001606 *e = audit_errno_to_name(-ret);
1607
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001608 fprintf(trace->output, ") = -1 %s %s", e, emsg);
Arnaldo Carvalho de Meloda3c9a42013-08-26 11:28:34 -03001609 } else if (ret == 0 && sc->fmt->timeout)
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001610 fprintf(trace->output, ") = 0 Timeout");
Arnaldo Carvalho de Melo04b34722013-08-26 11:36:30 -03001611 else if (sc->fmt->hexret)
Chang Hyun Park2c82c3a2014-09-26 21:54:01 +09001612 fprintf(trace->output, ") = %#lx", ret);
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -03001613 else if (sc->fmt->errpid) {
1614 struct thread *child = machine__find_thread(trace->host, ret, ret);
1615
1616 if (child != NULL) {
1617 fprintf(trace->output, ") = %ld", ret);
1618 if (child->comm_set)
1619 fprintf(trace->output, " (%s)", thread__comm_str(child));
1620 thread__put(child);
1621 }
1622 } else
Arnaldo Carvalho de Meloda3c9a42013-08-26 11:28:34 -03001623 goto signed_print;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001624
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001625 fputc('\n', trace->output);
Milian Wolff566a0882016-04-08 13:34:15 +02001626
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -03001627 if (callchain_ret > 0)
1628 trace__fprintf_callchain(trace, sample);
1629 else if (callchain_ret < 0)
1630 pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel));
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001631out:
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001632 ttrace->entry_pending = false;
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001633 err = 0;
1634out_put:
1635 thread__put(thread);
1636 return err;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001637}
1638
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001639static int trace__vfs_getname(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04001640 union perf_event *event __maybe_unused,
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001641 struct perf_sample *sample)
1642{
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001643 struct thread *thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
1644 struct thread_trace *ttrace;
1645 size_t filename_len, entry_str_len, to_move;
1646 ssize_t remaining_space;
1647 char *pos;
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03001648 const char *filename = perf_evsel__rawptr(evsel, sample, "pathname");
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001649
1650 if (!thread)
1651 goto out;
1652
1653 ttrace = thread__priv(thread);
1654 if (!ttrace)
1655 goto out;
1656
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03001657 filename_len = strlen(filename);
1658
1659 if (ttrace->filename.namelen < filename_len) {
1660 char *f = realloc(ttrace->filename.name, filename_len + 1);
1661
1662 if (f == NULL)
1663 goto out;
1664
1665 ttrace->filename.namelen = filename_len;
1666 ttrace->filename.name = f;
1667 }
1668
1669 strcpy(ttrace->filename.name, filename);
1670 ttrace->filename.pending_open = true;
1671
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001672 if (!ttrace->filename.ptr)
1673 goto out;
1674
1675 entry_str_len = strlen(ttrace->entry_str);
1676 remaining_space = trace__entry_str_size - entry_str_len - 1; /* \0 */
1677 if (remaining_space <= 0)
1678 goto out;
1679
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001680 if (filename_len > (size_t)remaining_space) {
1681 filename += filename_len - remaining_space;
1682 filename_len = remaining_space;
1683 }
1684
1685 to_move = entry_str_len - ttrace->filename.entry_str_pos + 1; /* \0 */
1686 pos = ttrace->entry_str + ttrace->filename.entry_str_pos;
1687 memmove(pos + filename_len, pos, to_move);
1688 memcpy(pos, filename, filename_len);
1689
1690 ttrace->filename.ptr = 0;
1691 ttrace->filename.entry_str_pos = 0;
1692out:
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001693 return 0;
1694}
1695
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001696static int trace__sched_stat_runtime(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04001697 union perf_event *event __maybe_unused,
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001698 struct perf_sample *sample)
1699{
1700 u64 runtime = perf_evsel__intval(evsel, sample, "runtime");
1701 double runtime_ms = (double)runtime / NSEC_PER_MSEC;
David Ahern8fb598e2013-09-28 13:13:00 -06001702 struct thread *thread = machine__findnew_thread(trace->host,
Adrian Hunter314add62013-08-27 11:23:03 +03001703 sample->pid,
1704 sample->tid);
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001705 struct thread_trace *ttrace = thread__trace(thread, trace->output);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001706
1707 if (ttrace == NULL)
1708 goto out_dump;
1709
1710 ttrace->runtime_ms += runtime_ms;
1711 trace->runtime_ms += runtime_ms;
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001712 thread__put(thread);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001713 return 0;
1714
1715out_dump:
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001716 fprintf(trace->output, "%s: comm=%s,pid=%u,runtime=%" PRIu64 ",vruntime=%" PRIu64 ")\n",
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001717 evsel->name,
1718 perf_evsel__strval(evsel, sample, "comm"),
1719 (pid_t)perf_evsel__intval(evsel, sample, "pid"),
1720 runtime,
1721 perf_evsel__intval(evsel, sample, "vruntime"));
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001722 thread__put(thread);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001723 return 0;
1724}
1725
Wang Nan1d6c9402016-02-26 09:31:55 +00001726static void bpf_output__printer(enum binary_printer_ops op,
1727 unsigned int val, void *extra)
1728{
1729 FILE *output = extra;
1730 unsigned char ch = (unsigned char)val;
1731
1732 switch (op) {
1733 case BINARY_PRINT_CHAR_DATA:
1734 fprintf(output, "%c", isprint(ch) ? ch : '.');
1735 break;
1736 case BINARY_PRINT_DATA_BEGIN:
1737 case BINARY_PRINT_LINE_BEGIN:
1738 case BINARY_PRINT_ADDR:
1739 case BINARY_PRINT_NUM_DATA:
1740 case BINARY_PRINT_NUM_PAD:
1741 case BINARY_PRINT_SEP:
1742 case BINARY_PRINT_CHAR_PAD:
1743 case BINARY_PRINT_LINE_END:
1744 case BINARY_PRINT_DATA_END:
1745 default:
1746 break;
1747 }
1748}
1749
1750static void bpf_output__fprintf(struct trace *trace,
1751 struct perf_sample *sample)
1752{
1753 print_binary(sample->raw_data, sample->raw_size, 8,
1754 bpf_output__printer, trace->output);
1755}
1756
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03001757static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
1758 union perf_event *event __maybe_unused,
1759 struct perf_sample *sample)
1760{
Arnaldo Carvalho de Melo7ad35612016-04-20 19:55:48 -03001761 int callchain_ret = 0;
1762
1763 if (sample->callchain) {
1764 callchain_ret = trace__resolve_callchain(trace, evsel, sample, &callchain_cursor);
1765 if (callchain_ret == 0) {
1766 if (callchain_cursor.nr < trace->min_stack)
1767 goto out;
1768 callchain_ret = 1;
1769 }
1770 }
1771
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03001772 trace__printf_interrupted_entry(trace, sample);
1773 trace__fprintf_tstamp(trace, sample->time, trace->output);
Arnaldo Carvalho de Melo08089212015-02-19 21:51:50 -08001774
1775 if (trace->trace_syscalls)
1776 fprintf(trace->output, "( ): ");
1777
1778 fprintf(trace->output, "%s:", evsel->name);
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03001779
Wang Nan1d6c9402016-02-26 09:31:55 +00001780 if (perf_evsel__is_bpf_output(evsel)) {
1781 bpf_output__fprintf(trace, sample);
1782 } else if (evsel->tp_format) {
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03001783 event_format__fprintf(evsel->tp_format, sample->cpu,
1784 sample->raw_data, sample->raw_size,
1785 trace->output);
1786 }
1787
1788 fprintf(trace->output, ")\n");
Arnaldo Carvalho de Melo202ff962016-04-12 10:11:07 -03001789
Arnaldo Carvalho de Melo7ad35612016-04-20 19:55:48 -03001790 if (callchain_ret > 0)
1791 trace__fprintf_callchain(trace, sample);
1792 else if (callchain_ret < 0)
1793 pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel));
1794out:
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03001795 return 0;
1796}
1797
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04001798static void print_location(FILE *f, struct perf_sample *sample,
1799 struct addr_location *al,
1800 bool print_dso, bool print_sym)
1801{
1802
1803 if ((verbose || print_dso) && al->map)
1804 fprintf(f, "%s@", al->map->dso->long_name);
1805
1806 if ((verbose || print_sym) && al->sym)
Arnaldo Carvalho de Melo4414a3c2014-07-08 15:39:21 -03001807 fprintf(f, "%s+0x%" PRIx64, al->sym->name,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04001808 al->addr - al->sym->start);
1809 else if (al->map)
Arnaldo Carvalho de Melo4414a3c2014-07-08 15:39:21 -03001810 fprintf(f, "0x%" PRIx64, al->addr);
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04001811 else
Arnaldo Carvalho de Melo4414a3c2014-07-08 15:39:21 -03001812 fprintf(f, "0x%" PRIx64, sample->addr);
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04001813}
1814
1815static int trace__pgfault(struct trace *trace,
1816 struct perf_evsel *evsel,
Arnaldo Carvalho de Melo473398a2016-03-22 18:23:43 -03001817 union perf_event *event __maybe_unused,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04001818 struct perf_sample *sample)
1819{
1820 struct thread *thread;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04001821 struct addr_location al;
1822 char map_type = 'd';
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04001823 struct thread_trace *ttrace;
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001824 int err = -1;
Arnaldo Carvalho de Melo1df54292016-04-20 20:06:02 -03001825 int callchain_ret = 0;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04001826
1827 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
Arnaldo Carvalho de Melo1df54292016-04-20 20:06:02 -03001828
1829 if (sample->callchain) {
1830 callchain_ret = trace__resolve_callchain(trace, evsel, sample, &callchain_cursor);
1831 if (callchain_ret == 0) {
1832 if (callchain_cursor.nr < trace->min_stack)
1833 goto out_put;
1834 callchain_ret = 1;
1835 }
1836 }
1837
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04001838 ttrace = thread__trace(thread, trace->output);
1839 if (ttrace == NULL)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001840 goto out_put;
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04001841
1842 if (evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ)
1843 ttrace->pfmaj++;
1844 else
1845 ttrace->pfmin++;
1846
1847 if (trace->summary_only)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001848 goto out;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04001849
Arnaldo Carvalho de Melo473398a2016-03-22 18:23:43 -03001850 thread__find_addr_location(thread, sample->cpumode, MAP__FUNCTION,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04001851 sample->ip, &al);
1852
1853 trace__fprintf_entry_head(trace, thread, 0, sample->time, trace->output);
1854
1855 fprintf(trace->output, "%sfault [",
1856 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ?
1857 "maj" : "min");
1858
1859 print_location(trace->output, sample, &al, false, true);
1860
1861 fprintf(trace->output, "] => ");
1862
Arnaldo Carvalho de Melo473398a2016-03-22 18:23:43 -03001863 thread__find_addr_location(thread, sample->cpumode, MAP__VARIABLE,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04001864 sample->addr, &al);
1865
1866 if (!al.map) {
Arnaldo Carvalho de Melo473398a2016-03-22 18:23:43 -03001867 thread__find_addr_location(thread, sample->cpumode,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04001868 MAP__FUNCTION, sample->addr, &al);
1869
1870 if (al.map)
1871 map_type = 'x';
1872 else
1873 map_type = '?';
1874 }
1875
1876 print_location(trace->output, sample, &al, true, false);
1877
1878 fprintf(trace->output, " (%c%c)\n", map_type, al.level);
Arnaldo Carvalho de Melo0c3a6ef2016-04-19 16:31:12 -03001879
Arnaldo Carvalho de Melo1df54292016-04-20 20:06:02 -03001880 if (callchain_ret > 0)
1881 trace__fprintf_callchain(trace, sample);
1882 else if (callchain_ret < 0)
1883 pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel));
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001884out:
1885 err = 0;
1886out_put:
1887 thread__put(thread);
1888 return err;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04001889}
1890
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03001891static void trace__set_base_time(struct trace *trace,
Arnaldo Carvalho de Melo8a07a802016-03-31 15:19:39 -03001892 struct perf_evsel *evsel,
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03001893 struct perf_sample *sample)
1894{
Arnaldo Carvalho de Melo8a07a802016-03-31 15:19:39 -03001895 /*
1896 * BPF events were not setting PERF_SAMPLE_TIME, so be more robust
1897 * and don't use sample->time unconditionally, we may end up having
1898 * some other event in the future without PERF_SAMPLE_TIME for good
1899 * reason, i.e. we may not be interested in its timestamps, just in
1900 * it taking place, picking some piece of information when it
1901 * appears in our event stream (vfs_getname comes to mind).
1902 */
1903 if (trace->base_time == 0 && !trace->full_time &&
1904 (evsel->attr.sample_type & PERF_SAMPLE_TIME))
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03001905 trace->base_time = sample->time;
1906}
1907
David Ahern6810fc92013-08-28 22:29:52 -06001908static int trace__process_sample(struct perf_tool *tool,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04001909 union perf_event *event,
David Ahern6810fc92013-08-28 22:29:52 -06001910 struct perf_sample *sample,
1911 struct perf_evsel *evsel,
1912 struct machine *machine __maybe_unused)
1913{
1914 struct trace *trace = container_of(tool, struct trace, tool);
David Ahernaa07df62016-11-25 09:29:52 -07001915 struct thread *thread;
David Ahern6810fc92013-08-28 22:29:52 -06001916 int err = 0;
1917
Arnaldo Carvalho de Melo744a9712013-11-06 10:17:38 -03001918 tracepoint_handler handler = evsel->handler;
David Ahern6810fc92013-08-28 22:29:52 -06001919
David Ahernaa07df62016-11-25 09:29:52 -07001920 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
1921 if (thread && thread__is_filtered(thread))
David Ahernbdc89662013-08-28 22:29:53 -06001922 return 0;
1923
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03001924 trace__set_base_time(trace, evsel, sample);
David Ahern6810fc92013-08-28 22:29:52 -06001925
David Ahern31605652013-12-04 19:41:41 -07001926 if (handler) {
1927 ++trace->nr_events;
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04001928 handler(trace, evsel, event, sample);
David Ahern31605652013-12-04 19:41:41 -07001929 }
David Ahern6810fc92013-08-28 22:29:52 -06001930
1931 return err;
1932}
1933
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04001934static int trace__record(struct trace *trace, int argc, const char **argv)
David Ahern5e2485b2013-09-28 13:13:01 -06001935{
1936 unsigned int rec_argc, i, j;
1937 const char **rec_argv;
1938 const char * const record_args[] = {
1939 "record",
1940 "-R",
1941 "-m", "1024",
1942 "-c", "1",
David Ahern5e2485b2013-09-28 13:13:01 -06001943 };
1944
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04001945 const char * const sc_args[] = { "-e", };
1946 unsigned int sc_args_nr = ARRAY_SIZE(sc_args);
1947 const char * const majpf_args[] = { "-e", "major-faults" };
1948 unsigned int majpf_args_nr = ARRAY_SIZE(majpf_args);
1949 const char * const minpf_args[] = { "-e", "minor-faults" };
1950 unsigned int minpf_args_nr = ARRAY_SIZE(minpf_args);
1951
David Ahern9aca7f12013-12-04 19:41:39 -07001952 /* +1 is for the event string below */
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04001953 rec_argc = ARRAY_SIZE(record_args) + sc_args_nr + 1 +
1954 majpf_args_nr + minpf_args_nr + argc;
David Ahern5e2485b2013-09-28 13:13:01 -06001955 rec_argv = calloc(rec_argc + 1, sizeof(char *));
1956
1957 if (rec_argv == NULL)
1958 return -ENOMEM;
1959
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04001960 j = 0;
David Ahern5e2485b2013-09-28 13:13:01 -06001961 for (i = 0; i < ARRAY_SIZE(record_args); i++)
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04001962 rec_argv[j++] = record_args[i];
1963
Stanislav Fomicheve281a962014-06-26 20:14:28 +04001964 if (trace->trace_syscalls) {
1965 for (i = 0; i < sc_args_nr; i++)
1966 rec_argv[j++] = sc_args[i];
David Ahern5e2485b2013-09-28 13:13:01 -06001967
Stanislav Fomicheve281a962014-06-26 20:14:28 +04001968 /* event string may be different for older kernels - e.g., RHEL6 */
1969 if (is_valid_tracepoint("raw_syscalls:sys_enter"))
1970 rec_argv[j++] = "raw_syscalls:sys_enter,raw_syscalls:sys_exit";
1971 else if (is_valid_tracepoint("syscalls:sys_enter"))
1972 rec_argv[j++] = "syscalls:sys_enter,syscalls:sys_exit";
1973 else {
1974 pr_err("Neither raw_syscalls nor syscalls events exist.\n");
1975 return -1;
1976 }
David Ahern9aca7f12013-12-04 19:41:39 -07001977 }
David Ahern9aca7f12013-12-04 19:41:39 -07001978
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04001979 if (trace->trace_pgfaults & TRACE_PFMAJ)
1980 for (i = 0; i < majpf_args_nr; i++)
1981 rec_argv[j++] = majpf_args[i];
David Ahern5e2485b2013-09-28 13:13:01 -06001982
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04001983 if (trace->trace_pgfaults & TRACE_PFMIN)
1984 for (i = 0; i < minpf_args_nr; i++)
1985 rec_argv[j++] = minpf_args[i];
1986
1987 for (i = 0; i < (unsigned int)argc; i++)
1988 rec_argv[j++] = argv[i];
1989
1990 return cmd_record(j, rec_argv, NULL);
David Ahern5e2485b2013-09-28 13:13:01 -06001991}
1992
David Ahernbf2575c2013-10-08 21:26:53 -06001993static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp);
1994
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03001995static bool perf_evlist__add_vfs_getname(struct perf_evlist *evlist)
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001996{
Arnaldo Carvalho de Meloef503832013-11-07 16:41:19 -03001997 struct perf_evsel *evsel = perf_evsel__newtp("probe", "vfs_getname");
Jiri Olsa8dd2a132015-09-07 10:38:06 +02001998
1999 if (IS_ERR(evsel))
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002000 return false;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002001
2002 if (perf_evsel__field(evsel, "pathname") == NULL) {
2003 perf_evsel__delete(evsel);
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002004 return false;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002005 }
2006
Arnaldo Carvalho de Melo744a9712013-11-06 10:17:38 -03002007 evsel->handler = trace__vfs_getname;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002008 perf_evlist__add(evlist, evsel);
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002009 return true;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002010}
2011
Arnaldo Carvalho de Melo0ae537c2016-04-19 16:00:01 -03002012static struct perf_evsel *perf_evsel__new_pgfault(u64 config)
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002013{
2014 struct perf_evsel *evsel;
2015 struct perf_event_attr attr = {
2016 .type = PERF_TYPE_SOFTWARE,
2017 .mmap_data = 1,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002018 };
2019
2020 attr.config = config;
Arnaldo Carvalho de Melo05247982014-07-23 18:15:09 -03002021 attr.sample_period = 1;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002022
2023 event_attr_init(&attr);
2024
2025 evsel = perf_evsel__new(&attr);
Arnaldo Carvalho de Melo0ae537c2016-04-19 16:00:01 -03002026 if (evsel)
2027 evsel->handler = trace__pgfault;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002028
Arnaldo Carvalho de Melo0ae537c2016-04-19 16:00:01 -03002029 return evsel;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002030}
2031
Arnaldo Carvalho de Meloddbb1b12015-02-21 12:10:29 -08002032static void trace__handle_event(struct trace *trace, union perf_event *event, struct perf_sample *sample)
2033{
2034 const u32 type = event->header.type;
2035 struct perf_evsel *evsel;
2036
Arnaldo Carvalho de Meloddbb1b12015-02-21 12:10:29 -08002037 if (type != PERF_RECORD_SAMPLE) {
2038 trace__process_event(trace, trace->host, event, sample);
2039 return;
2040 }
2041
2042 evsel = perf_evlist__id2evsel(trace->evlist, sample->id);
2043 if (evsel == NULL) {
2044 fprintf(trace->output, "Unknown tp ID %" PRIu64 ", skipping...\n", sample->id);
2045 return;
2046 }
2047
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03002048 trace__set_base_time(trace, evsel, sample);
2049
Arnaldo Carvalho de Meloddbb1b12015-02-21 12:10:29 -08002050 if (evsel->attr.type == PERF_TYPE_TRACEPOINT &&
2051 sample->raw_data == NULL) {
2052 fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n",
2053 perf_evsel__name(evsel), sample->tid,
2054 sample->cpu, sample->raw_size);
2055 } else {
2056 tracepoint_handler handler = evsel->handler;
2057 handler(trace, evsel, event, sample);
2058 }
2059}
2060
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03002061static int trace__add_syscall_newtp(struct trace *trace)
2062{
2063 int ret = -1;
2064 struct perf_evlist *evlist = trace->evlist;
2065 struct perf_evsel *sys_enter, *sys_exit;
2066
2067 sys_enter = perf_evsel__syscall_newtp("sys_enter", trace__sys_enter);
2068 if (sys_enter == NULL)
2069 goto out;
2070
2071 if (perf_evsel__init_sc_tp_ptr_field(sys_enter, args))
2072 goto out_delete_sys_enter;
2073
2074 sys_exit = perf_evsel__syscall_newtp("sys_exit", trace__sys_exit);
2075 if (sys_exit == NULL)
2076 goto out_delete_sys_enter;
2077
2078 if (perf_evsel__init_sc_tp_uint_field(sys_exit, ret))
2079 goto out_delete_sys_exit;
2080
2081 perf_evlist__add(evlist, sys_enter);
2082 perf_evlist__add(evlist, sys_exit);
2083
Arnaldo Carvalho de Melo2ddd5c02016-04-18 12:09:08 -03002084 if (callchain_param.enabled && !trace->kernel_syscallchains) {
Arnaldo Carvalho de Melo44621812016-04-11 15:49:11 -03002085 /*
2086 * We're interested only in the user space callchain
2087 * leading to the syscall, allow overriding that for
2088 * debugging reasons using --kernel_syscall_callchains
2089 */
2090 sys_exit->attr.exclude_callchain_kernel = 1;
2091 }
2092
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03002093 trace->syscalls.events.sys_enter = sys_enter;
2094 trace->syscalls.events.sys_exit = sys_exit;
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03002095
2096 ret = 0;
2097out:
2098 return ret;
2099
2100out_delete_sys_exit:
2101 perf_evsel__delete_priv(sys_exit);
2102out_delete_sys_enter:
2103 perf_evsel__delete_priv(sys_enter);
2104 goto out;
2105}
2106
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002107static int trace__set_ev_qualifier_filter(struct trace *trace)
2108{
2109 int err = -1;
Mathieu Poirierb15d0a42016-09-16 08:44:03 -06002110 struct perf_evsel *sys_exit;
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002111 char *filter = asprintf_expr_inout_ints("id", !trace->not_ev_qualifier,
2112 trace->ev_qualifier_ids.nr,
2113 trace->ev_qualifier_ids.entries);
2114
2115 if (filter == NULL)
2116 goto out_enomem;
2117
Mathieu Poirier3541c032016-09-16 08:44:04 -06002118 if (!perf_evsel__append_tp_filter(trace->syscalls.events.sys_enter,
2119 filter)) {
Mathieu Poirierb15d0a42016-09-16 08:44:03 -06002120 sys_exit = trace->syscalls.events.sys_exit;
Mathieu Poirier3541c032016-09-16 08:44:04 -06002121 err = perf_evsel__append_tp_filter(sys_exit, filter);
Mathieu Poirierb15d0a42016-09-16 08:44:03 -06002122 }
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002123
2124 free(filter);
2125out:
2126 return err;
2127out_enomem:
2128 errno = ENOMEM;
2129 goto out;
2130}
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03002131
Namhyung Kimf15eb532012-10-05 14:02:16 +09002132static int trace__run(struct trace *trace, int argc, const char **argv)
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002133{
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002134 struct perf_evlist *evlist = trace->evlist;
Arnaldo Carvalho de Melo0ae537c2016-04-19 16:00:01 -03002135 struct perf_evsel *evsel, *pgfault_maj = NULL, *pgfault_min = NULL;
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03002136 int err = -1, i;
2137 unsigned long before;
Namhyung Kimf15eb532012-10-05 14:02:16 +09002138 const bool forks = argc > 0;
Arnaldo Carvalho de Melo46fb3c22014-09-22 14:39:48 -03002139 bool draining = false;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002140
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03002141 trace->live = true;
2142
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03002143 if (trace->trace_syscalls && trace__add_syscall_newtp(trace))
Arnaldo Carvalho de Melo801c67b2015-01-22 10:52:55 -03002144 goto out_error_raw_syscalls;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002145
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002146 if (trace->trace_syscalls)
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002147 trace->vfs_getname = perf_evlist__add_vfs_getname(evlist);
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002148
Arnaldo Carvalho de Melo0ae537c2016-04-19 16:00:01 -03002149 if ((trace->trace_pgfaults & TRACE_PFMAJ)) {
2150 pgfault_maj = perf_evsel__new_pgfault(PERF_COUNT_SW_PAGE_FAULTS_MAJ);
2151 if (pgfault_maj == NULL)
2152 goto out_error_mem;
2153 perf_evlist__add(evlist, pgfault_maj);
Arnaldo Carvalho de Meloe2726d92015-01-22 10:34:22 -03002154 }
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002155
Arnaldo Carvalho de Melo0ae537c2016-04-19 16:00:01 -03002156 if ((trace->trace_pgfaults & TRACE_PFMIN)) {
2157 pgfault_min = perf_evsel__new_pgfault(PERF_COUNT_SW_PAGE_FAULTS_MIN);
2158 if (pgfault_min == NULL)
2159 goto out_error_mem;
2160 perf_evlist__add(evlist, pgfault_min);
2161 }
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002162
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002163 if (trace->sched &&
Arnaldo Carvalho de Melo2cc990b2015-01-22 11:13:43 -03002164 perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime",
2165 trace__sched_stat_runtime))
2166 goto out_error_sched_stat_runtime;
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002167
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002168 err = perf_evlist__create_maps(evlist, &trace->opts.target);
2169 if (err < 0) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002170 fprintf(trace->output, "Problems parsing the target to trace, check your options!\n");
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002171 goto out_delete_evlist;
2172 }
2173
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03002174 err = trace__symbols_init(trace, evlist);
2175 if (err < 0) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002176 fprintf(trace->output, "Problems initializing symbol libraries!\n");
Arnaldo Carvalho de Melo03ad9742014-01-03 15:56:06 -03002177 goto out_delete_evlist;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03002178 }
2179
Arnaldo Carvalho de Melofde54b72016-04-11 18:42:37 -03002180 perf_evlist__config(evlist, &trace->opts, NULL);
2181
Arnaldo Carvalho de Melo0c3a6ef2016-04-19 16:31:12 -03002182 if (callchain_param.enabled) {
2183 bool use_identifier = false;
2184
2185 if (trace->syscalls.events.sys_exit) {
2186 perf_evsel__config_callchain(trace->syscalls.events.sys_exit,
2187 &trace->opts, &callchain_param);
2188 use_identifier = true;
2189 }
2190
2191 if (pgfault_maj) {
2192 perf_evsel__config_callchain(pgfault_maj, &trace->opts, &callchain_param);
2193 use_identifier = true;
2194 }
2195
2196 if (pgfault_min) {
2197 perf_evsel__config_callchain(pgfault_min, &trace->opts, &callchain_param);
2198 use_identifier = true;
2199 }
2200
2201 if (use_identifier) {
2202 /*
2203 * Now we have evsels with different sample_ids, use
2204 * PERF_SAMPLE_IDENTIFIER to map from sample to evsel
2205 * from a fixed position in each ring buffer record.
2206 *
2207 * As of this the changeset introducing this comment, this
2208 * isn't strictly needed, as the fields that can come before
2209 * PERF_SAMPLE_ID are all used, but we'll probably disable
2210 * some of those for things like copying the payload of
2211 * pointer syscall arguments, and for vfs_getname we don't
2212 * need PERF_SAMPLE_ADDR and PERF_SAMPLE_IP, so do this
2213 * here as a warning we need to use PERF_SAMPLE_IDENTIFIER.
2214 */
2215 perf_evlist__set_sample_bit(evlist, IDENTIFIER);
2216 perf_evlist__reset_sample_bit(evlist, ID);
2217 }
Arnaldo Carvalho de Melofde54b72016-04-11 18:42:37 -03002218 }
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002219
Namhyung Kimf15eb532012-10-05 14:02:16 +09002220 signal(SIGCHLD, sig_handler);
2221 signal(SIGINT, sig_handler);
2222
2223 if (forks) {
Namhyung Kim6ef73ec2013-03-11 16:43:15 +09002224 err = perf_evlist__prepare_workload(evlist, &trace->opts.target,
Arnaldo Carvalho de Melo735f7e02014-01-03 14:56:49 -03002225 argv, false, NULL);
Namhyung Kimf15eb532012-10-05 14:02:16 +09002226 if (err < 0) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002227 fprintf(trace->output, "Couldn't run the workload!\n");
Arnaldo Carvalho de Melo03ad9742014-01-03 15:56:06 -03002228 goto out_delete_evlist;
Namhyung Kimf15eb532012-10-05 14:02:16 +09002229 }
2230 }
2231
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002232 err = perf_evlist__open(evlist);
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002233 if (err < 0)
2234 goto out_error_open;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002235
Wang Nanba504232016-02-26 09:31:54 +00002236 err = bpf__apply_obj_config();
2237 if (err) {
2238 char errbuf[BUFSIZ];
2239
2240 bpf__strerror_apply_obj_config(err, errbuf, sizeof(errbuf));
2241 pr_err("ERROR: Apply config to BPF failed: %s\n",
2242 errbuf);
2243 goto out_error_open;
2244 }
2245
Arnaldo Carvalho de Melo241b0572015-02-21 10:15:21 -08002246 /*
2247 * Better not use !target__has_task() here because we need to cover the
2248 * case where no threads were specified in the command line, but a
2249 * workload was, and in that case we will fill in the thread_map when
2250 * we fork the workload in perf_evlist__prepare_workload.
2251 */
Arnaldo Carvalho de Melof078c382015-02-21 11:36:52 -08002252 if (trace->filter_pids.nr > 0)
2253 err = perf_evlist__set_filter_pids(evlist, trace->filter_pids.nr, trace->filter_pids.entries);
Jiri Olsae13798c2015-06-23 00:36:02 +02002254 else if (thread_map__pid(evlist->threads, 0) == -1)
Arnaldo Carvalho de Melof078c382015-02-21 11:36:52 -08002255 err = perf_evlist__set_filter_pid(evlist, getpid());
2256
Arnaldo Carvalho de Melo94ad89b2015-07-03 17:42:03 -03002257 if (err < 0)
2258 goto out_error_mem;
2259
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002260 if (trace->ev_qualifier_ids.nr > 0) {
2261 err = trace__set_ev_qualifier_filter(trace);
2262 if (err < 0)
2263 goto out_errno;
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002264
Arnaldo Carvalho de Melo2e5e5f82015-08-03 17:12:29 -03002265 pr_debug("event qualifier tracepoint filter: %s\n",
2266 trace->syscalls.events.sys_exit->filter);
2267 }
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002268
Arnaldo Carvalho de Melo94ad89b2015-07-03 17:42:03 -03002269 err = perf_evlist__apply_filters(evlist, &evsel);
2270 if (err < 0)
2271 goto out_error_apply_filters;
Arnaldo Carvalho de Melo241b0572015-02-21 10:15:21 -08002272
Jiri Olsaf8850372013-11-28 17:57:22 +01002273 err = perf_evlist__mmap(evlist, trace->opts.mmap_pages, false);
Arnaldo Carvalho de Meloe09b18d2014-12-11 18:04:10 -03002274 if (err < 0)
2275 goto out_error_mmap;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002276
Alexis Berlemonte36b7822016-10-10 07:43:28 +02002277 if (!target__none(&trace->opts.target) && !trace->opts.initial_delay)
Arnaldo Carvalho de Melocb24d012015-04-22 10:04:23 -03002278 perf_evlist__enable(evlist);
2279
Namhyung Kimf15eb532012-10-05 14:02:16 +09002280 if (forks)
2281 perf_evlist__start_workload(evlist);
2282
Alexis Berlemonte36b7822016-10-10 07:43:28 +02002283 if (trace->opts.initial_delay) {
2284 usleep(trace->opts.initial_delay * 1000);
2285 perf_evlist__enable(evlist);
2286 }
2287
Jiri Olsae13798c2015-06-23 00:36:02 +02002288 trace->multiple_threads = thread_map__pid(evlist->threads, 0) == -1 ||
Arnaldo Carvalho de Melo42052be2015-02-13 12:32:45 -03002289 evlist->threads->nr > 1 ||
2290 perf_evlist__first(evlist)->attr.inherit;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002291again:
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03002292 before = trace->nr_events;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002293
2294 for (i = 0; i < evlist->nr_mmaps; i++) {
2295 union perf_event *event;
2296
2297 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002298 struct perf_sample sample;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002299
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03002300 ++trace->nr_events;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002301
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002302 err = perf_evlist__parse_sample(evlist, event, &sample);
2303 if (err) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002304 fprintf(trace->output, "Can't parse sample, err = %d, skipping...\n", err);
Zhouyi Zhou8e50d382013-10-24 15:43:33 +08002305 goto next_event;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002306 }
2307
Arnaldo Carvalho de Meloddbb1b12015-02-21 12:10:29 -08002308 trace__handle_event(trace, event, &sample);
Zhouyi Zhou8e50d382013-10-24 15:43:33 +08002309next_event:
2310 perf_evlist__mmap_consume(evlist, i);
Arnaldo Carvalho de Melo20c5f102013-09-03 11:55:07 -03002311
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002312 if (interrupted)
2313 goto out_disable;
Arnaldo Carvalho de Melo02ac5422015-04-22 11:11:57 -03002314
2315 if (done && !draining) {
2316 perf_evlist__disable(evlist);
2317 draining = true;
2318 }
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002319 }
2320 }
2321
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03002322 if (trace->nr_events == before) {
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002323 int timeout = done ? 100 : -1;
Namhyung Kimf15eb532012-10-05 14:02:16 +09002324
Arnaldo Carvalho de Melo46fb3c22014-09-22 14:39:48 -03002325 if (!draining && perf_evlist__poll(evlist, timeout) > 0) {
2326 if (perf_evlist__filter_pollfd(evlist, POLLERR | POLLHUP) == 0)
2327 draining = true;
2328
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002329 goto again;
Arnaldo Carvalho de Melo46fb3c22014-09-22 14:39:48 -03002330 }
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002331 } else {
2332 goto again;
Namhyung Kimf15eb532012-10-05 14:02:16 +09002333 }
2334
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002335out_disable:
Arnaldo Carvalho de Melof3b623b2015-03-02 22:21:35 -03002336 thread__zput(trace->current);
2337
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002338 perf_evlist__disable(evlist);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002339
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002340 if (!err) {
2341 if (trace->summary)
2342 trace__fprintf_thread_summary(trace, trace->output);
2343
2344 if (trace->show_tool_stats) {
2345 fprintf(trace->output, "Stats:\n "
2346 " vfs_getname : %" PRIu64 "\n"
2347 " proc_getname: %" PRIu64 "\n",
2348 trace->stats.vfs_getname,
2349 trace->stats.proc_getname);
2350 }
2351 }
David Ahernbf2575c2013-10-08 21:26:53 -06002352
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002353out_delete_evlist:
2354 perf_evlist__delete(evlist);
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002355 trace->evlist = NULL;
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03002356 trace->live = false;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002357 return err;
Arnaldo Carvalho de Melo6ef068c2013-10-17 12:07:58 -03002358{
2359 char errbuf[BUFSIZ];
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002360
Arnaldo Carvalho de Melo2cc990b2015-01-22 11:13:43 -03002361out_error_sched_stat_runtime:
Jiri Olsa988bdb32015-09-02 09:56:35 +02002362 tracing_path__strerror_open_tp(errno, errbuf, sizeof(errbuf), "sched", "sched_stat_runtime");
Arnaldo Carvalho de Melo2cc990b2015-01-22 11:13:43 -03002363 goto out_error;
2364
Arnaldo Carvalho de Melo801c67b2015-01-22 10:52:55 -03002365out_error_raw_syscalls:
Jiri Olsa988bdb32015-09-02 09:56:35 +02002366 tracing_path__strerror_open_tp(errno, errbuf, sizeof(errbuf), "raw_syscalls", "sys_(enter|exit)");
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002367 goto out_error;
2368
Arnaldo Carvalho de Meloe09b18d2014-12-11 18:04:10 -03002369out_error_mmap:
2370 perf_evlist__strerror_mmap(evlist, errno, errbuf, sizeof(errbuf));
2371 goto out_error;
2372
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002373out_error_open:
2374 perf_evlist__strerror_open(evlist, errno, errbuf, sizeof(errbuf));
2375
2376out_error:
Arnaldo Carvalho de Melo6ef068c2013-10-17 12:07:58 -03002377 fprintf(trace->output, "%s\n", errbuf);
Ramkumar Ramachandra87f91862013-10-04 10:47:31 +05302378 goto out_delete_evlist;
Arnaldo Carvalho de Melo94ad89b2015-07-03 17:42:03 -03002379
2380out_error_apply_filters:
2381 fprintf(trace->output,
2382 "Failed to set filter \"%s\" on event %s with %d (%s)\n",
2383 evsel->filter, perf_evsel__name(evsel), errno,
Arnaldo Carvalho de Meloc8b5f2c2016-07-06 11:56:20 -03002384 str_error_r(errno, errbuf, sizeof(errbuf)));
Arnaldo Carvalho de Melo94ad89b2015-07-03 17:42:03 -03002385 goto out_delete_evlist;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002386}
Arnaldo Carvalho de Melo5ed08da2015-01-22 11:08:04 -03002387out_error_mem:
2388 fprintf(trace->output, "Not enough memory to run!\n");
2389 goto out_delete_evlist;
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002390
2391out_errno:
2392 fprintf(trace->output, "errno=%d,%s\n", errno, strerror(errno));
2393 goto out_delete_evlist;
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002394}
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002395
David Ahern6810fc92013-08-28 22:29:52 -06002396static int trace__replay(struct trace *trace)
2397{
2398 const struct perf_evsel_str_handler handlers[] = {
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002399 { "probe:vfs_getname", trace__vfs_getname, },
David Ahern6810fc92013-08-28 22:29:52 -06002400 };
Jiri Olsaf5fc1412013-10-15 16:27:32 +02002401 struct perf_data_file file = {
2402 .path = input_name,
2403 .mode = PERF_DATA_MODE_READ,
Yunlong Songe366a6d2015-04-02 21:47:18 +08002404 .force = trace->force,
Jiri Olsaf5fc1412013-10-15 16:27:32 +02002405 };
David Ahern6810fc92013-08-28 22:29:52 -06002406 struct perf_session *session;
Namhyung Kim003824e2013-11-12 15:25:00 +09002407 struct perf_evsel *evsel;
David Ahern6810fc92013-08-28 22:29:52 -06002408 int err = -1;
2409
2410 trace->tool.sample = trace__process_sample;
2411 trace->tool.mmap = perf_event__process_mmap;
David Ahern384c6712013-09-22 19:44:58 -06002412 trace->tool.mmap2 = perf_event__process_mmap2;
David Ahern6810fc92013-08-28 22:29:52 -06002413 trace->tool.comm = perf_event__process_comm;
2414 trace->tool.exit = perf_event__process_exit;
2415 trace->tool.fork = perf_event__process_fork;
2416 trace->tool.attr = perf_event__process_attr;
2417 trace->tool.tracing_data = perf_event__process_tracing_data;
2418 trace->tool.build_id = perf_event__process_build_id;
2419
Jiri Olsa0a8cb852014-07-06 14:18:21 +02002420 trace->tool.ordered_events = true;
David Ahern6810fc92013-08-28 22:29:52 -06002421 trace->tool.ordering_requires_timestamps = true;
2422
2423 /* add tid to output */
2424 trace->multiple_threads = true;
2425
Jiri Olsaf5fc1412013-10-15 16:27:32 +02002426 session = perf_session__new(&file, false, &trace->tool);
David Ahern6810fc92013-08-28 22:29:52 -06002427 if (session == NULL)
Taeung Song52e028342014-09-24 10:33:37 +09002428 return -1;
David Ahern6810fc92013-08-28 22:29:52 -06002429
David Ahernaa07df62016-11-25 09:29:52 -07002430 if (trace->opts.target.pid)
2431 symbol_conf.pid_list_str = strdup(trace->opts.target.pid);
2432
2433 if (trace->opts.target.tid)
2434 symbol_conf.tid_list_str = strdup(trace->opts.target.tid);
2435
Namhyung Kim0a7e6d12014-08-12 15:40:45 +09002436 if (symbol__init(&session->header.env) < 0)
Namhyung Kimcb2ffae2014-08-12 15:40:44 +09002437 goto out;
2438
David Ahern8fb598e2013-09-28 13:13:00 -06002439 trace->host = &session->machines.host;
2440
David Ahern6810fc92013-08-28 22:29:52 -06002441 err = perf_session__set_tracepoints_handlers(session, handlers);
2442 if (err)
2443 goto out;
2444
Namhyung Kim003824e2013-11-12 15:25:00 +09002445 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2446 "raw_syscalls:sys_enter");
David Ahern9aca7f12013-12-04 19:41:39 -07002447 /* older kernels have syscalls tp versus raw_syscalls */
2448 if (evsel == NULL)
2449 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2450 "syscalls:sys_enter");
David Ahern6810fc92013-08-28 22:29:52 -06002451
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002452 if (evsel &&
2453 (perf_evsel__init_syscall_tp(evsel, trace__sys_enter) < 0 ||
2454 perf_evsel__init_sc_tp_ptr_field(evsel, args))) {
Namhyung Kim003824e2013-11-12 15:25:00 +09002455 pr_err("Error during initialize raw_syscalls:sys_enter event\n");
2456 goto out;
2457 }
2458
2459 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2460 "raw_syscalls:sys_exit");
David Ahern9aca7f12013-12-04 19:41:39 -07002461 if (evsel == NULL)
2462 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2463 "syscalls:sys_exit");
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002464 if (evsel &&
2465 (perf_evsel__init_syscall_tp(evsel, trace__sys_exit) < 0 ||
2466 perf_evsel__init_sc_tp_uint_field(evsel, ret))) {
Namhyung Kim003824e2013-11-12 15:25:00 +09002467 pr_err("Error during initialize raw_syscalls:sys_exit event\n");
David Ahern6810fc92013-08-28 22:29:52 -06002468 goto out;
2469 }
2470
Arnaldo Carvalho de Meloe5cadb92016-06-23 11:26:15 -03002471 evlist__for_each_entry(session->evlist, evsel) {
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002472 if (evsel->attr.type == PERF_TYPE_SOFTWARE &&
2473 (evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ||
2474 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MIN ||
2475 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS))
2476 evsel->handler = trace__pgfault;
2477 }
2478
David Ahern6810fc92013-08-28 22:29:52 -06002479 setup_pager();
2480
Arnaldo Carvalho de Melob7b61cb2015-03-03 11:58:45 -03002481 err = perf_session__process_events(session);
David Ahern6810fc92013-08-28 22:29:52 -06002482 if (err)
2483 pr_err("Failed to process events, error %d", err);
2484
David Ahernbf2575c2013-10-08 21:26:53 -06002485 else if (trace->summary)
2486 trace__fprintf_thread_summary(trace, trace->output);
2487
David Ahern6810fc92013-08-28 22:29:52 -06002488out:
2489 perf_session__delete(session);
2490
2491 return err;
2492}
2493
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002494static size_t trace__fprintf_threads_header(FILE *fp)
2495{
2496 size_t printed;
2497
Pekka Enberg99ff7152013-11-12 16:42:14 +02002498 printed = fprintf(fp, "\n Summary of events:\n\n");
David Ahernbf2575c2013-10-08 21:26:53 -06002499
2500 return printed;
2501}
2502
Arnaldo Carvalho de Melob535d522016-05-04 16:06:26 -03002503DEFINE_RESORT_RB(syscall_stats, a->msecs > b->msecs,
2504 struct stats *stats;
2505 double msecs;
2506 int syscall;
2507)
2508{
2509 struct int_node *source = rb_entry(nd, struct int_node, rb_node);
2510 struct stats *stats = source->priv;
2511
2512 entry->syscall = source->i;
2513 entry->stats = stats;
2514 entry->msecs = stats ? (u64)stats->n * (avg_stats(stats) / NSEC_PER_MSEC) : 0;
2515}
2516
David Ahernbf2575c2013-10-08 21:26:53 -06002517static size_t thread__dump_stats(struct thread_trace *ttrace,
2518 struct trace *trace, FILE *fp)
2519{
David Ahernbf2575c2013-10-08 21:26:53 -06002520 size_t printed = 0;
2521 struct syscall *sc;
Arnaldo Carvalho de Melob535d522016-05-04 16:06:26 -03002522 struct rb_node *nd;
2523 DECLARE_RESORT_RB_INTLIST(syscall_stats, ttrace->syscall_stats);
David Ahernbf2575c2013-10-08 21:26:53 -06002524
Arnaldo Carvalho de Melob535d522016-05-04 16:06:26 -03002525 if (syscall_stats == NULL)
David Ahernbf2575c2013-10-08 21:26:53 -06002526 return 0;
2527
2528 printed += fprintf(fp, "\n");
2529
Milian Wolff834fd462015-08-06 11:24:29 +02002530 printed += fprintf(fp, " syscall calls total min avg max stddev\n");
2531 printed += fprintf(fp, " (msec) (msec) (msec) (msec) (%%)\n");
2532 printed += fprintf(fp, " --------------- -------- --------- --------- --------- --------- ------\n");
Pekka Enberg99ff7152013-11-12 16:42:14 +02002533
Arnaldo Carvalho de Melo98a91832016-06-23 11:34:10 -03002534 resort_rb__for_each_entry(nd, syscall_stats) {
Arnaldo Carvalho de Melob535d522016-05-04 16:06:26 -03002535 struct stats *stats = syscall_stats_entry->stats;
David Ahernbf2575c2013-10-08 21:26:53 -06002536 if (stats) {
2537 double min = (double)(stats->min) / NSEC_PER_MSEC;
2538 double max = (double)(stats->max) / NSEC_PER_MSEC;
2539 double avg = avg_stats(stats);
2540 double pct;
2541 u64 n = (u64) stats->n;
2542
2543 pct = avg ? 100.0 * stddev_stats(stats)/avg : 0.0;
2544 avg /= NSEC_PER_MSEC;
2545
Arnaldo Carvalho de Melob535d522016-05-04 16:06:26 -03002546 sc = &trace->syscalls.table[syscall_stats_entry->syscall];
Pekka Enberg99ff7152013-11-12 16:42:14 +02002547 printed += fprintf(fp, " %-15s", sc->name);
Milian Wolff834fd462015-08-06 11:24:29 +02002548 printed += fprintf(fp, " %8" PRIu64 " %9.3f %9.3f %9.3f",
Arnaldo Carvalho de Melob535d522016-05-04 16:06:26 -03002549 n, syscall_stats_entry->msecs, min, avg);
Pekka Enberg27a778b2013-11-13 14:21:48 +02002550 printed += fprintf(fp, " %9.3f %9.2f%%\n", max, pct);
David Ahernbf2575c2013-10-08 21:26:53 -06002551 }
David Ahernbf2575c2013-10-08 21:26:53 -06002552 }
2553
Arnaldo Carvalho de Melob535d522016-05-04 16:06:26 -03002554 resort_rb__delete(syscall_stats);
David Ahernbf2575c2013-10-08 21:26:53 -06002555 printed += fprintf(fp, "\n\n");
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002556
2557 return printed;
2558}
2559
Arnaldo Carvalho de Melo96c14452016-05-04 12:47:16 -03002560static size_t trace__fprintf_thread(FILE *fp, struct thread *thread, struct trace *trace)
David Ahern896cbb52013-09-28 13:12:59 -06002561{
Arnaldo Carvalho de Melo96c14452016-05-04 12:47:16 -03002562 size_t printed = 0;
Namhyung Kim89dceb22014-10-06 09:46:03 +09002563 struct thread_trace *ttrace = thread__priv(thread);
David Ahern896cbb52013-09-28 13:12:59 -06002564 double ratio;
2565
2566 if (ttrace == NULL)
2567 return 0;
2568
2569 ratio = (double)ttrace->nr_events / trace->nr_events * 100.0;
2570
Pekka Enberg15e65c62013-11-14 18:43:30 +02002571 printed += fprintf(fp, " %s (%d), ", thread__comm_str(thread), thread->tid);
Pekka Enberg99ff7152013-11-12 16:42:14 +02002572 printed += fprintf(fp, "%lu events, ", ttrace->nr_events);
Pekka Enberg15e65c62013-11-14 18:43:30 +02002573 printed += fprintf(fp, "%.1f%%", ratio);
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04002574 if (ttrace->pfmaj)
2575 printed += fprintf(fp, ", %lu majfaults", ttrace->pfmaj);
2576 if (ttrace->pfmin)
2577 printed += fprintf(fp, ", %lu minfaults", ttrace->pfmin);
Arnaldo Carvalho de Melo03548eb2016-05-05 15:46:50 -03002578 if (trace->sched)
2579 printed += fprintf(fp, ", %.3f msec\n", ttrace->runtime_ms);
2580 else if (fputc('\n', fp) != EOF)
2581 ++printed;
2582
David Ahernbf2575c2013-10-08 21:26:53 -06002583 printed += thread__dump_stats(ttrace, trace, fp);
David Ahern896cbb52013-09-28 13:12:59 -06002584
Arnaldo Carvalho de Melo96c14452016-05-04 12:47:16 -03002585 return printed;
2586}
David Ahern896cbb52013-09-28 13:12:59 -06002587
Arnaldo Carvalho de Melo96c14452016-05-04 12:47:16 -03002588static unsigned long thread__nr_events(struct thread_trace *ttrace)
2589{
2590 return ttrace ? ttrace->nr_events : 0;
2591}
2592
2593DEFINE_RESORT_RB(threads, (thread__nr_events(a->thread->priv) < thread__nr_events(b->thread->priv)),
2594 struct thread *thread;
2595)
2596{
2597 entry->thread = rb_entry(nd, struct thread, rb_node);
David Ahern896cbb52013-09-28 13:12:59 -06002598}
2599
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002600static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp)
2601{
Arnaldo Carvalho de Melo96c14452016-05-04 12:47:16 -03002602 DECLARE_RESORT_RB_MACHINE_THREADS(threads, trace->host);
2603 size_t printed = trace__fprintf_threads_header(fp);
2604 struct rb_node *nd;
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002605
Arnaldo Carvalho de Melo96c14452016-05-04 12:47:16 -03002606 if (threads == NULL) {
2607 fprintf(fp, "%s", "Error sorting output by nr_events!\n");
2608 return 0;
2609 }
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002610
Arnaldo Carvalho de Melo98a91832016-06-23 11:34:10 -03002611 resort_rb__for_each_entry(nd, threads)
Arnaldo Carvalho de Melo96c14452016-05-04 12:47:16 -03002612 printed += trace__fprintf_thread(fp, threads_entry->thread, trace);
2613
2614 resort_rb__delete(threads);
2615
2616 return printed;
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002617}
2618
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03002619static int trace__set_duration(const struct option *opt, const char *str,
2620 int unset __maybe_unused)
2621{
2622 struct trace *trace = opt->value;
2623
2624 trace->duration_filter = atof(str);
2625 return 0;
2626}
2627
Arnaldo Carvalho de Melof078c382015-02-21 11:36:52 -08002628static int trace__set_filter_pids(const struct option *opt, const char *str,
2629 int unset __maybe_unused)
2630{
2631 int ret = -1;
2632 size_t i;
2633 struct trace *trace = opt->value;
2634 /*
2635 * FIXME: introduce a intarray class, plain parse csv and create a
2636 * { int nr, int entries[] } struct...
2637 */
2638 struct intlist *list = intlist__new(str);
2639
2640 if (list == NULL)
2641 return -1;
2642
2643 i = trace->filter_pids.nr = intlist__nr_entries(list) + 1;
2644 trace->filter_pids.entries = calloc(i, sizeof(pid_t));
2645
2646 if (trace->filter_pids.entries == NULL)
2647 goto out;
2648
2649 trace->filter_pids.entries[0] = getpid();
2650
2651 for (i = 1; i < trace->filter_pids.nr; ++i)
2652 trace->filter_pids.entries[i] = intlist__entry(list, i - 1)->i;
2653
2654 intlist__delete(list);
2655 ret = 0;
2656out:
2657 return ret;
2658}
2659
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002660static int trace__open_output(struct trace *trace, const char *filename)
2661{
2662 struct stat st;
2663
2664 if (!stat(filename, &st) && st.st_size) {
2665 char oldname[PATH_MAX];
2666
2667 scnprintf(oldname, sizeof(oldname), "%s.old", filename);
2668 unlink(oldname);
2669 rename(filename, oldname);
2670 }
2671
2672 trace->output = fopen(filename, "w");
2673
2674 return trace->output == NULL ? -errno : 0;
2675}
2676
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002677static int parse_pagefaults(const struct option *opt, const char *str,
2678 int unset __maybe_unused)
2679{
2680 int *trace_pgfaults = opt->value;
2681
2682 if (strcmp(str, "all") == 0)
2683 *trace_pgfaults |= TRACE_PFMAJ | TRACE_PFMIN;
2684 else if (strcmp(str, "maj") == 0)
2685 *trace_pgfaults |= TRACE_PFMAJ;
2686 else if (strcmp(str, "min") == 0)
2687 *trace_pgfaults |= TRACE_PFMIN;
2688 else
2689 return -1;
2690
2691 return 0;
2692}
2693
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002694static void evlist__set_evsel_handler(struct perf_evlist *evlist, void *handler)
2695{
2696 struct perf_evsel *evsel;
2697
Arnaldo Carvalho de Meloe5cadb92016-06-23 11:26:15 -03002698 evlist__for_each_entry(evlist, evsel)
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002699 evsel->handler = handler;
2700}
2701
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002702int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
2703{
Yunlong Song6fdd9cb2015-03-18 21:35:57 +08002704 const char *trace_usage[] = {
Namhyung Kimf15eb532012-10-05 14:02:16 +09002705 "perf trace [<options>] [<command>]",
2706 "perf trace [<options>] -- <command> [<options>]",
David Ahern5e2485b2013-09-28 13:13:01 -06002707 "perf trace record [<options>] [<command>]",
2708 "perf trace record [<options>] -- <command> [<options>]",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002709 NULL
2710 };
2711 struct trace trace = {
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002712 .syscalls = {
2713 . max = -1,
2714 },
2715 .opts = {
2716 .target = {
2717 .uid = UINT_MAX,
2718 .uses_mmap = true,
2719 },
2720 .user_freq = UINT_MAX,
2721 .user_interval = ULLONG_MAX,
Arnaldo Carvalho de Melo509051e2014-01-14 17:52:14 -03002722 .no_buffering = true,
Arnaldo Carvalho de Melo38d54472014-12-12 17:28:32 -03002723 .mmap_pages = UINT_MAX,
Kan Liang9d9cad72015-06-17 09:51:11 -04002724 .proc_map_timeout = 500,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002725 },
Milian Wolff007d66a2015-08-05 16:52:23 -03002726 .output = stderr,
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -03002727 .show_comm = true,
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002728 .trace_syscalls = true,
Arnaldo Carvalho de Melo44621812016-04-11 15:49:11 -03002729 .kernel_syscallchains = false,
Arnaldo Carvalho de Melo05614992016-04-15 16:41:19 -03002730 .max_stack = UINT_MAX,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002731 };
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002732 const char *output_name = NULL;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03002733 const char *ev_qualifier_str = NULL;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002734 const struct option trace_options[] = {
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002735 OPT_CALLBACK(0, "event", &trace.evlist, "event",
2736 "event selector. use 'perf list' to list available events",
2737 parse_events_option),
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -03002738 OPT_BOOLEAN(0, "comm", &trace.show_comm,
2739 "show the thread COMM next to its id"),
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002740 OPT_BOOLEAN(0, "tool_stats", &trace.show_tool_stats, "show tool stats"),
Arnaldo Carvalho de Melod303e852015-04-23 12:02:07 -03002741 OPT_STRING('e', "expr", &ev_qualifier_str, "expr", "list of syscalls to trace"),
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002742 OPT_STRING('o', "output", &output_name, "file", "output file name"),
David Ahern6810fc92013-08-28 22:29:52 -06002743 OPT_STRING('i', "input", &input_name, "file", "Analyze events in file"),
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002744 OPT_STRING('p', "pid", &trace.opts.target.pid, "pid",
2745 "trace events on existing process id"),
David Ahernac9be8e2013-08-20 11:15:45 -06002746 OPT_STRING('t', "tid", &trace.opts.target.tid, "tid",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002747 "trace events on existing thread id"),
Arnaldo Carvalho de Melofa0e4ff2015-04-23 11:59:20 -03002748 OPT_CALLBACK(0, "filter-pids", &trace, "CSV list of pids",
2749 "pids to filter (by the kernel)", trace__set_filter_pids),
David Ahernac9be8e2013-08-20 11:15:45 -06002750 OPT_BOOLEAN('a', "all-cpus", &trace.opts.target.system_wide,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002751 "system-wide collection from all CPUs"),
David Ahernac9be8e2013-08-20 11:15:45 -06002752 OPT_STRING('C', "cpu", &trace.opts.target.cpu_list, "cpu",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002753 "list of cpus to monitor"),
David Ahern6810fc92013-08-28 22:29:52 -06002754 OPT_BOOLEAN(0, "no-inherit", &trace.opts.no_inherit,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002755 "child tasks do not inherit counters"),
Jiri Olsa994a1f72013-09-01 12:36:12 +02002756 OPT_CALLBACK('m', "mmap-pages", &trace.opts.mmap_pages, "pages",
2757 "number of mmap data pages",
2758 perf_evlist__parse_mmap_pages),
David Ahernac9be8e2013-08-20 11:15:45 -06002759 OPT_STRING('u', "uid", &trace.opts.target.uid_str, "user",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002760 "user to profile"),
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03002761 OPT_CALLBACK(0, "duration", &trace, "float",
2762 "show only events with duration > N.M ms",
2763 trace__set_duration),
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002764 OPT_BOOLEAN(0, "sched", &trace.sched, "show blocking scheduler events"),
Arnaldo Carvalho de Melo7c304ee02013-08-22 16:49:54 -03002765 OPT_INCR('v', "verbose", &verbose, "be more verbose"),
David Ahern4bb09192013-09-04 12:37:43 -06002766 OPT_BOOLEAN('T', "time", &trace.full_time,
2767 "Show full timestamp, not time relative to first start"),
David Ahernfd2eaba2013-11-12 09:31:15 -07002768 OPT_BOOLEAN('s', "summary", &trace.summary_only,
2769 "Show only syscall summary with statistics"),
2770 OPT_BOOLEAN('S', "with-summary", &trace.summary,
2771 "Show all syscalls and summary with statistics"),
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002772 OPT_CALLBACK_DEFAULT('F', "pf", &trace.trace_pgfaults, "all|maj|min",
2773 "Trace pagefaults", parse_pagefaults, "maj"),
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002774 OPT_BOOLEAN(0, "syscalls", &trace.trace_syscalls, "Trace syscalls"),
Yunlong Songe366a6d2015-04-02 21:47:18 +08002775 OPT_BOOLEAN('f', "force", &trace.force, "don't complain, do it"),
Milian Wolff566a0882016-04-08 13:34:15 +02002776 OPT_CALLBACK(0, "call-graph", &trace.opts,
2777 "record_mode[,record_size]", record_callchain_help,
2778 &record_parse_callchain_opt),
Arnaldo Carvalho de Melo44621812016-04-11 15:49:11 -03002779 OPT_BOOLEAN(0, "kernel-syscall-graph", &trace.kernel_syscallchains,
2780 "Show the kernel callchains on the syscall exit path"),
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -03002781 OPT_UINTEGER(0, "min-stack", &trace.min_stack,
2782 "Set the minimum stack depth when parsing the callchain, "
2783 "anything below the specified depth will be ignored."),
Arnaldo Carvalho de Meloc6d4a492016-04-14 18:29:08 -03002784 OPT_UINTEGER(0, "max-stack", &trace.max_stack,
2785 "Set the maximum stack depth when parsing the callchain, "
2786 "anything beyond the specified depth will be ignored. "
Arnaldo Carvalho de Melo4cb93442016-04-27 10:16:24 -03002787 "Default: kernel.perf_event_max_stack or " __stringify(PERF_MAX_STACK_DEPTH)),
Kan Liang9d9cad72015-06-17 09:51:11 -04002788 OPT_UINTEGER(0, "proc-map-timeout", &trace.opts.proc_map_timeout,
2789 "per thread proc mmap processing timeout in ms"),
Alexis Berlemonte36b7822016-10-10 07:43:28 +02002790 OPT_UINTEGER('D', "delay", &trace.opts.initial_delay,
2791 "ms to wait before starting measurement after program "
2792 "start"),
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002793 OPT_END()
2794 };
Arnaldo Carvalho de Meloccd62a82016-04-16 09:36:32 -03002795 bool __maybe_unused max_stack_user_set = true;
Arnaldo Carvalho de Melof3e459d2016-04-15 17:52:34 -03002796 bool mmap_pages_user_set = true;
Yunlong Song6fdd9cb2015-03-18 21:35:57 +08002797 const char * const trace_subcommands[] = { "record", NULL };
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002798 int err;
Namhyung Kim32caf0d2012-10-05 14:02:13 +09002799 char bf[BUFSIZ];
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002800
Arnaldo Carvalho de Melo4d08cb82015-02-24 15:35:55 -03002801 signal(SIGSEGV, sighandler_dump_stack);
2802 signal(SIGFPE, sighandler_dump_stack);
2803
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002804 trace.evlist = perf_evlist__new();
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03002805 trace.sctbl = syscalltbl__new();
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002806
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03002807 if (trace.evlist == NULL || trace.sctbl == NULL) {
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002808 pr_err("Not enough memory to run!\n");
He Kuangff8f6952015-05-11 12:28:36 +00002809 err = -ENOMEM;
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002810 goto out;
2811 }
2812
Yunlong Song6fdd9cb2015-03-18 21:35:57 +08002813 argc = parse_options_subcommand(argc, argv, trace_options, trace_subcommands,
2814 trace_usage, PARSE_OPT_STOP_AT_NON_OPTION);
David Ahernfd2eaba2013-11-12 09:31:15 -07002815
Wang Nand7888572016-04-08 15:07:24 +00002816 err = bpf__setup_stdout(trace.evlist);
2817 if (err) {
2818 bpf__strerror_setup_stdout(trace.evlist, err, bf, sizeof(bf));
2819 pr_err("ERROR: Setup BPF stdout failed: %s\n", bf);
2820 goto out;
2821 }
2822
Arnaldo Carvalho de Melo59247e32016-04-12 16:05:02 -03002823 err = -1;
2824
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002825 if (trace.trace_pgfaults) {
2826 trace.opts.sample_address = true;
2827 trace.opts.sample_time = true;
2828 }
2829
Arnaldo Carvalho de Melof3e459d2016-04-15 17:52:34 -03002830 if (trace.opts.mmap_pages == UINT_MAX)
2831 mmap_pages_user_set = false;
2832
Arnaldo Carvalho de Melo05614992016-04-15 16:41:19 -03002833 if (trace.max_stack == UINT_MAX) {
Arnaldo Carvalho de Melofe176082016-05-19 11:34:06 -03002834 trace.max_stack = input_name ? PERF_MAX_STACK_DEPTH : sysctl_perf_event_max_stack;
Arnaldo Carvalho de Melo05614992016-04-15 16:41:19 -03002835 max_stack_user_set = false;
2836 }
2837
2838#ifdef HAVE_DWARF_UNWIND_SUPPORT
Arnaldo Carvalho de Melocaa36ed2016-05-19 19:00:27 -03002839 if ((trace.min_stack || max_stack_user_set) && !callchain_param.enabled && trace.trace_syscalls)
Arnaldo Carvalho de Melo05614992016-04-15 16:41:19 -03002840 record_opts__parse_callchain(&trace.opts, &callchain_param, "dwarf", false);
2841#endif
2842
Arnaldo Carvalho de Melo2ddd5c02016-04-18 12:09:08 -03002843 if (callchain_param.enabled) {
Arnaldo Carvalho de Melof3e459d2016-04-15 17:52:34 -03002844 if (!mmap_pages_user_set && geteuid() == 0)
2845 trace.opts.mmap_pages = perf_event_mlock_kb_in_pages() * 4;
2846
Milian Wolff566a0882016-04-08 13:34:15 +02002847 symbol_conf.use_callchain = true;
Arnaldo Carvalho de Melof3e459d2016-04-15 17:52:34 -03002848 }
Milian Wolff566a0882016-04-08 13:34:15 +02002849
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002850 if (trace.evlist->nr_entries > 0)
2851 evlist__set_evsel_handler(trace.evlist, trace__event_handler);
2852
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002853 if ((argc >= 1) && (strcmp(argv[0], "record") == 0))
2854 return trace__record(&trace, argc-1, &argv[1]);
2855
2856 /* summary_only implies summary option, but don't overwrite summary if set */
2857 if (trace.summary_only)
2858 trace.summary = trace.summary_only;
2859
Arnaldo Carvalho de Melo726f3232015-02-06 10:16:45 +01002860 if (!trace.trace_syscalls && !trace.trace_pgfaults &&
2861 trace.evlist->nr_entries == 0 /* Was --events used? */) {
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002862 pr_err("Please specify something to trace.\n");
2863 return -1;
2864 }
2865
Arnaldo Carvalho de Melo59247e32016-04-12 16:05:02 -03002866 if (!trace.trace_syscalls && ev_qualifier_str) {
2867 pr_err("The -e option can't be used with --no-syscalls.\n");
2868 goto out;
2869 }
2870
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002871 if (output_name != NULL) {
2872 err = trace__open_output(&trace, output_name);
2873 if (err < 0) {
2874 perror("failed to create output file");
2875 goto out;
2876 }
2877 }
2878
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03002879 trace.open_id = syscalltbl__id(trace.sctbl, "open");
2880
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03002881 if (ev_qualifier_str != NULL) {
Arnaldo Carvalho de Melob059efd2013-08-21 12:56:21 -03002882 const char *s = ev_qualifier_str;
Arnaldo Carvalho de Melo005438a82015-07-20 12:02:09 -03002883 struct strlist_config slist_config = {
2884 .dirname = system_path(STRACE_GROUPS_DIR),
2885 };
Arnaldo Carvalho de Melob059efd2013-08-21 12:56:21 -03002886
2887 trace.not_ev_qualifier = *s == '!';
2888 if (trace.not_ev_qualifier)
2889 ++s;
Arnaldo Carvalho de Melo005438a82015-07-20 12:02:09 -03002890 trace.ev_qualifier = strlist__new(s, &slist_config);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03002891 if (trace.ev_qualifier == NULL) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002892 fputs("Not enough memory to parse event qualifier",
2893 trace.output);
2894 err = -ENOMEM;
2895 goto out_close;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03002896 }
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03002897
2898 err = trace__validate_ev_qualifier(&trace);
2899 if (err)
2900 goto out_close;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03002901 }
2902
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03002903 err = target__validate(&trace.opts.target);
Namhyung Kim32caf0d2012-10-05 14:02:13 +09002904 if (err) {
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03002905 target__strerror(&trace.opts.target, err, bf, sizeof(bf));
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002906 fprintf(trace.output, "%s", bf);
2907 goto out_close;
Namhyung Kim32caf0d2012-10-05 14:02:13 +09002908 }
2909
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03002910 err = target__parse_uid(&trace.opts.target);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002911 if (err) {
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03002912 target__strerror(&trace.opts.target, err, bf, sizeof(bf));
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002913 fprintf(trace.output, "%s", bf);
2914 goto out_close;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002915 }
2916
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03002917 if (!argc && target__none(&trace.opts.target))
Namhyung Kimee761202012-10-05 14:02:14 +09002918 trace.opts.target.system_wide = true;
2919
David Ahern6810fc92013-08-28 22:29:52 -06002920 if (input_name)
2921 err = trace__replay(&trace);
2922 else
2923 err = trace__run(&trace, argc, argv);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002924
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002925out_close:
2926 if (output_name != NULL)
2927 fclose(trace.output);
2928out:
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002929 return err;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002930}