blob: 21f8a81797a04e32b9fc496851e9332f58e5e6d9 [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;
77 struct intlist *tid_list;
78 struct intlist *pid_list;
79 struct {
80 size_t nr;
81 pid_t *entries;
82 } filter_pids;
83 double duration_filter;
84 double runtime_ms;
85 struct {
86 u64 vfs_getname,
87 proc_getname;
88 } stats;
Arnaldo Carvalho de Meloc6d4a492016-04-14 18:29:08 -030089 unsigned int max_stack;
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -030090 unsigned int min_stack;
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -030091 bool not_ev_qualifier;
92 bool live;
93 bool full_time;
94 bool sched;
95 bool multiple_threads;
96 bool summary;
97 bool summary_only;
98 bool show_comm;
99 bool show_tool_stats;
100 bool trace_syscalls;
Arnaldo Carvalho de Melo44621812016-04-11 15:49:11 -0300101 bool kernel_syscallchains;
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -0300102 bool force;
103 bool vfs_getname;
104 int trace_pgfaults;
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -0300105 int open_id;
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -0300106};
Arnaldo Carvalho de Meloa1c25522015-06-11 22:47:54 -0300107
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300108struct tp_field {
109 int offset;
110 union {
111 u64 (*integer)(struct tp_field *field, struct perf_sample *sample);
112 void *(*pointer)(struct tp_field *field, struct perf_sample *sample);
113 };
114};
115
116#define TP_UINT_FIELD(bits) \
117static u64 tp_field__u##bits(struct tp_field *field, struct perf_sample *sample) \
118{ \
David Ahern55d43bc2015-02-19 15:00:22 -0500119 u##bits value; \
120 memcpy(&value, sample->raw_data + field->offset, sizeof(value)); \
121 return value; \
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300122}
123
124TP_UINT_FIELD(8);
125TP_UINT_FIELD(16);
126TP_UINT_FIELD(32);
127TP_UINT_FIELD(64);
128
129#define TP_UINT_FIELD__SWAPPED(bits) \
130static u64 tp_field__swapped_u##bits(struct tp_field *field, struct perf_sample *sample) \
131{ \
David Ahern55d43bc2015-02-19 15:00:22 -0500132 u##bits value; \
133 memcpy(&value, sample->raw_data + field->offset, sizeof(value)); \
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300134 return bswap_##bits(value);\
135}
136
137TP_UINT_FIELD__SWAPPED(16);
138TP_UINT_FIELD__SWAPPED(32);
139TP_UINT_FIELD__SWAPPED(64);
140
141static int tp_field__init_uint(struct tp_field *field,
142 struct format_field *format_field,
143 bool needs_swap)
144{
145 field->offset = format_field->offset;
146
147 switch (format_field->size) {
148 case 1:
149 field->integer = tp_field__u8;
150 break;
151 case 2:
152 field->integer = needs_swap ? tp_field__swapped_u16 : tp_field__u16;
153 break;
154 case 4:
155 field->integer = needs_swap ? tp_field__swapped_u32 : tp_field__u32;
156 break;
157 case 8:
158 field->integer = needs_swap ? tp_field__swapped_u64 : tp_field__u64;
159 break;
160 default:
161 return -1;
162 }
163
164 return 0;
165}
166
167static void *tp_field__ptr(struct tp_field *field, struct perf_sample *sample)
168{
169 return sample->raw_data + field->offset;
170}
171
172static int tp_field__init_ptr(struct tp_field *field, struct format_field *format_field)
173{
174 field->offset = format_field->offset;
175 field->pointer = tp_field__ptr;
176 return 0;
177}
178
179struct syscall_tp {
180 struct tp_field id;
181 union {
182 struct tp_field args, ret;
183 };
184};
185
186static int perf_evsel__init_tp_uint_field(struct perf_evsel *evsel,
187 struct tp_field *field,
188 const char *name)
189{
190 struct format_field *format_field = perf_evsel__field(evsel, name);
191
192 if (format_field == NULL)
193 return -1;
194
195 return tp_field__init_uint(field, format_field, evsel->needs_swap);
196}
197
198#define perf_evsel__init_sc_tp_uint_field(evsel, name) \
199 ({ struct syscall_tp *sc = evsel->priv;\
200 perf_evsel__init_tp_uint_field(evsel, &sc->name, #name); })
201
202static int perf_evsel__init_tp_ptr_field(struct perf_evsel *evsel,
203 struct tp_field *field,
204 const char *name)
205{
206 struct format_field *format_field = perf_evsel__field(evsel, name);
207
208 if (format_field == NULL)
209 return -1;
210
211 return tp_field__init_ptr(field, format_field);
212}
213
214#define perf_evsel__init_sc_tp_ptr_field(evsel, name) \
215 ({ struct syscall_tp *sc = evsel->priv;\
216 perf_evsel__init_tp_ptr_field(evsel, &sc->name, #name); })
217
218static void perf_evsel__delete_priv(struct perf_evsel *evsel)
219{
Arnaldo Carvalho de Melo04662522013-12-26 17:41:15 -0300220 zfree(&evsel->priv);
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300221 perf_evsel__delete(evsel);
222}
223
Namhyung Kim96695d42013-11-12 08:51:45 -0300224static int perf_evsel__init_syscall_tp(struct perf_evsel *evsel, void *handler)
225{
226 evsel->priv = malloc(sizeof(struct syscall_tp));
227 if (evsel->priv != NULL) {
228 if (perf_evsel__init_sc_tp_uint_field(evsel, id))
229 goto out_delete;
230
231 evsel->handler = handler;
232 return 0;
233 }
234
235 return -ENOMEM;
236
237out_delete:
Arnaldo Carvalho de Melo04662522013-12-26 17:41:15 -0300238 zfree(&evsel->priv);
Namhyung Kim96695d42013-11-12 08:51:45 -0300239 return -ENOENT;
240}
241
Arnaldo Carvalho de Meloef503832013-11-07 16:41:19 -0300242static struct perf_evsel *perf_evsel__syscall_newtp(const char *direction, void *handler)
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300243{
Arnaldo Carvalho de Meloef503832013-11-07 16:41:19 -0300244 struct perf_evsel *evsel = perf_evsel__newtp("raw_syscalls", direction);
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300245
David Ahern9aca7f12013-12-04 19:41:39 -0700246 /* older kernel (e.g., RHEL6) use syscalls:{enter,exit} */
Jiri Olsa8dd2a132015-09-07 10:38:06 +0200247 if (IS_ERR(evsel))
David Ahern9aca7f12013-12-04 19:41:39 -0700248 evsel = perf_evsel__newtp("syscalls", direction);
249
Jiri Olsa8dd2a132015-09-07 10:38:06 +0200250 if (IS_ERR(evsel))
251 return NULL;
252
253 if (perf_evsel__init_syscall_tp(evsel, handler))
254 goto out_delete;
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300255
256 return evsel;
257
258out_delete:
259 perf_evsel__delete_priv(evsel);
260 return NULL;
261}
262
263#define perf_evsel__sc_tp_uint(evsel, name, sample) \
264 ({ struct syscall_tp *fields = evsel->priv; \
265 fields->name.integer(&fields->name, sample); })
266
267#define perf_evsel__sc_tp_ptr(evsel, name, sample) \
268 ({ struct syscall_tp *fields = evsel->priv; \
269 fields->name.pointer(&fields->name, sample); })
270
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300271struct syscall_arg {
272 unsigned long val;
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300273 struct thread *thread;
274 struct trace *trace;
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300275 void *parm;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300276 u8 idx;
277 u8 mask;
278};
279
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300280struct strarray {
Arnaldo Carvalho de Melo03e3adc2013-10-08 16:00:21 -0300281 int offset;
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300282 int nr_entries;
283 const char **entries;
284};
285
286#define DEFINE_STRARRAY(array) struct strarray strarray__##array = { \
287 .nr_entries = ARRAY_SIZE(array), \
288 .entries = array, \
289}
290
Arnaldo Carvalho de Melo03e3adc2013-10-08 16:00:21 -0300291#define DEFINE_STRARRAY_OFFSET(array, off) struct strarray strarray__##array = { \
292 .offset = off, \
293 .nr_entries = ARRAY_SIZE(array), \
294 .entries = array, \
295}
296
Arnaldo Carvalho de Melo975b7c22013-10-08 17:17:43 -0300297static size_t __syscall_arg__scnprintf_strarray(char *bf, size_t size,
298 const char *intfmt,
299 struct syscall_arg *arg)
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300300{
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300301 struct strarray *sa = arg->parm;
Arnaldo Carvalho de Melo03e3adc2013-10-08 16:00:21 -0300302 int idx = arg->val - sa->offset;
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300303
304 if (idx < 0 || idx >= sa->nr_entries)
Arnaldo Carvalho de Melo975b7c22013-10-08 17:17:43 -0300305 return scnprintf(bf, size, intfmt, arg->val);
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300306
307 return scnprintf(bf, size, "%s", sa->entries[idx]);
308}
309
Arnaldo Carvalho de Melo975b7c22013-10-08 17:17:43 -0300310static size_t syscall_arg__scnprintf_strarray(char *bf, size_t size,
311 struct syscall_arg *arg)
312{
313 return __syscall_arg__scnprintf_strarray(bf, size, "%d", arg);
314}
315
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300316#define SCA_STRARRAY syscall_arg__scnprintf_strarray
317
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -0300318#if defined(__i386__) || defined(__x86_64__)
319/*
320 * FIXME: Make this available to all arches as soon as the ioctl beautifier
321 * gets rewritten to support all arches.
322 */
Arnaldo Carvalho de Melo78645cf2013-10-08 17:43:20 -0300323static size_t syscall_arg__scnprintf_strhexarray(char *bf, size_t size,
324 struct syscall_arg *arg)
325{
326 return __syscall_arg__scnprintf_strarray(bf, size, "%#x", arg);
327}
328
329#define SCA_STRHEXARRAY syscall_arg__scnprintf_strhexarray
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -0300330#endif /* defined(__i386__) || defined(__x86_64__) */
Arnaldo Carvalho de Melo78645cf2013-10-08 17:43:20 -0300331
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300332static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
333 struct syscall_arg *arg);
334
335#define SCA_FD syscall_arg__scnprintf_fd
336
Arnaldo Carvalho de Melo48e1f912016-07-05 14:43:27 -0300337#ifndef AT_FDCWD
338#define AT_FDCWD -100
339#endif
340
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300341static size_t syscall_arg__scnprintf_fd_at(char *bf, size_t size,
342 struct syscall_arg *arg)
343{
344 int fd = arg->val;
345
346 if (fd == AT_FDCWD)
347 return scnprintf(bf, size, "CWD");
348
349 return syscall_arg__scnprintf_fd(bf, size, arg);
350}
351
352#define SCA_FDAT syscall_arg__scnprintf_fd_at
353
354static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
355 struct syscall_arg *arg);
356
357#define SCA_CLOSE_FD syscall_arg__scnprintf_close_fd
358
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -0300359static size_t syscall_arg__scnprintf_hex(char *bf, size_t size,
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300360 struct syscall_arg *arg)
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -0300361{
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300362 return scnprintf(bf, size, "%#lx", arg->val);
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -0300363}
364
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -0300365#define SCA_HEX syscall_arg__scnprintf_hex
366
Arnaldo Carvalho de Meloa1c25522015-06-11 22:47:54 -0300367static size_t syscall_arg__scnprintf_int(char *bf, size_t size,
368 struct syscall_arg *arg)
369{
370 return scnprintf(bf, size, "%d", arg->val);
371}
372
373#define SCA_INT syscall_arg__scnprintf_int
374
Arnaldo Carvalho de Melo729a7842015-10-29 11:48:18 -0300375static const char *bpf_cmd[] = {
376 "MAP_CREATE", "MAP_LOOKUP_ELEM", "MAP_UPDATE_ELEM", "MAP_DELETE_ELEM",
377 "MAP_GET_NEXT_KEY", "PROG_LOAD",
378};
379static DEFINE_STRARRAY(bpf_cmd);
380
Arnaldo Carvalho de Melo03e3adc2013-10-08 16:00:21 -0300381static const char *epoll_ctl_ops[] = { "ADD", "DEL", "MOD", };
382static DEFINE_STRARRAY_OFFSET(epoll_ctl_ops, 1);
Arnaldo Carvalho de Meloeac032c2013-09-20 11:27:32 -0300383
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300384static const char *itimers[] = { "REAL", "VIRTUAL", "PROF", };
385static DEFINE_STRARRAY(itimers);
386
Arnaldo Carvalho de Melob62bee12015-08-11 11:05:36 -0300387static const char *keyctl_options[] = {
388 "GET_KEYRING_ID", "JOIN_SESSION_KEYRING", "UPDATE", "REVOKE", "CHOWN",
389 "SETPERM", "DESCRIBE", "CLEAR", "LINK", "UNLINK", "SEARCH", "READ",
390 "INSTANTIATE", "NEGATE", "SET_REQKEY_KEYRING", "SET_TIMEOUT",
391 "ASSUME_AUTHORITY", "GET_SECURITY", "SESSION_TO_PARENT", "REJECT",
392 "INSTANTIATE_IOV", "INVALIDATE", "GET_PERSISTENT",
393};
394static DEFINE_STRARRAY(keyctl_options);
395
Arnaldo Carvalho de Meloefe6b882013-09-03 16:15:12 -0300396static const char *whences[] = { "SET", "CUR", "END",
397#ifdef SEEK_DATA
398"DATA",
399#endif
400#ifdef SEEK_HOLE
401"HOLE",
402#endif
403};
404static DEFINE_STRARRAY(whences);
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -0300405
Arnaldo Carvalho de Melo80f587d2013-09-03 16:28:58 -0300406static const char *fcntl_cmds[] = {
407 "DUPFD", "GETFD", "SETFD", "GETFL", "SETFL", "GETLK", "SETLK",
408 "SETLKW", "SETOWN", "GETOWN", "SETSIG", "GETSIG", "F_GETLK64",
409 "F_SETLK64", "F_SETLKW64", "F_SETOWN_EX", "F_GETOWN_EX",
410 "F_GETOWNER_UIDS",
411};
412static DEFINE_STRARRAY(fcntl_cmds);
413
Arnaldo Carvalho de Meloc045bf02013-09-04 11:52:33 -0300414static const char *rlimit_resources[] = {
415 "CPU", "FSIZE", "DATA", "STACK", "CORE", "RSS", "NPROC", "NOFILE",
416 "MEMLOCK", "AS", "LOCKS", "SIGPENDING", "MSGQUEUE", "NICE", "RTPRIO",
417 "RTTIME",
418};
419static DEFINE_STRARRAY(rlimit_resources);
420
Arnaldo Carvalho de Meloeb5b1b12013-09-03 16:37:46 -0300421static const char *sighow[] = { "BLOCK", "UNBLOCK", "SETMASK", };
422static DEFINE_STRARRAY(sighow);
423
David Ahern4f8c1b72013-09-22 19:45:00 -0600424static const char *clockid[] = {
425 "REALTIME", "MONOTONIC", "PROCESS_CPUTIME_ID", "THREAD_CPUTIME_ID",
Arnaldo Carvalho de Melo28ebb872015-08-11 10:38:38 -0300426 "MONOTONIC_RAW", "REALTIME_COARSE", "MONOTONIC_COARSE", "BOOTTIME",
427 "REALTIME_ALARM", "BOOTTIME_ALARM", "SGI_CYCLE", "TAI"
David Ahern4f8c1b72013-09-22 19:45:00 -0600428};
429static DEFINE_STRARRAY(clockid);
430
Arnaldo Carvalho de Meloe10bce82013-09-04 10:27:41 -0300431static const char *socket_families[] = {
432 "UNSPEC", "LOCAL", "INET", "AX25", "IPX", "APPLETALK", "NETROM",
433 "BRIDGE", "ATMPVC", "X25", "INET6", "ROSE", "DECnet", "NETBEUI",
434 "SECURITY", "KEY", "NETLINK", "PACKET", "ASH", "ECONET", "ATMSVC",
435 "RDS", "SNA", "IRDA", "PPPOX", "WANPIPE", "LLC", "IB", "CAN", "TIPC",
436 "BLUETOOTH", "IUCV", "RXRPC", "ISDN", "PHONET", "IEEE802154", "CAIF",
437 "ALG", "NFC", "VSOCK",
438};
439static DEFINE_STRARRAY(socket_families);
440
Arnaldo Carvalho de Melo51108992013-09-04 11:42:27 -0300441static size_t syscall_arg__scnprintf_access_mode(char *bf, size_t size,
442 struct syscall_arg *arg)
443{
444 size_t printed = 0;
445 int mode = arg->val;
446
447 if (mode == F_OK) /* 0 */
448 return scnprintf(bf, size, "F");
449#define P_MODE(n) \
450 if (mode & n##_OK) { \
451 printed += scnprintf(bf + printed, size - printed, "%s", #n); \
452 mode &= ~n##_OK; \
453 }
454
455 P_MODE(R);
456 P_MODE(W);
457 P_MODE(X);
458#undef P_MODE
459
460 if (mode)
461 printed += scnprintf(bf + printed, size - printed, "|%#x", mode);
462
463 return printed;
464}
465
466#define SCA_ACCMODE syscall_arg__scnprintf_access_mode
467
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -0300468static size_t syscall_arg__scnprintf_filename(char *bf, size_t size,
469 struct syscall_arg *arg);
470
471#define SCA_FILENAME syscall_arg__scnprintf_filename
472
Arnaldo Carvalho de Melo46cce192013-09-23 12:52:04 -0300473static size_t syscall_arg__scnprintf_pipe_flags(char *bf, size_t size,
474 struct syscall_arg *arg)
475{
476 int printed = 0, flags = arg->val;
477
478#define P_FLAG(n) \
479 if (flags & O_##n) { \
480 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
481 flags &= ~O_##n; \
482 }
483
484 P_FLAG(CLOEXEC);
485 P_FLAG(NONBLOCK);
486#undef P_FLAG
487
488 if (flags)
489 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
490
491 return printed;
492}
493
494#define SCA_PIPE_FLAGS syscall_arg__scnprintf_pipe_flags
495
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -0300496#if defined(__i386__) || defined(__x86_64__)
497/*
498 * FIXME: Make this available to all arches.
499 */
Arnaldo Carvalho de Melo78645cf2013-10-08 17:43:20 -0300500#define TCGETS 0x5401
501
502static const char *tioctls[] = {
503 "TCGETS", "TCSETS", "TCSETSW", "TCSETSF", "TCGETA", "TCSETA", "TCSETAW",
504 "TCSETAF", "TCSBRK", "TCXONC", "TCFLSH", "TIOCEXCL", "TIOCNXCL",
505 "TIOCSCTTY", "TIOCGPGRP", "TIOCSPGRP", "TIOCOUTQ", "TIOCSTI",
506 "TIOCGWINSZ", "TIOCSWINSZ", "TIOCMGET", "TIOCMBIS", "TIOCMBIC",
507 "TIOCMSET", "TIOCGSOFTCAR", "TIOCSSOFTCAR", "FIONREAD", "TIOCLINUX",
508 "TIOCCONS", "TIOCGSERIAL", "TIOCSSERIAL", "TIOCPKT", "FIONBIO",
509 "TIOCNOTTY", "TIOCSETD", "TIOCGETD", "TCSBRKP", [0x27] = "TIOCSBRK",
510 "TIOCCBRK", "TIOCGSID", "TCGETS2", "TCSETS2", "TCSETSW2", "TCSETSF2",
511 "TIOCGRS485", "TIOCSRS485", "TIOCGPTN", "TIOCSPTLCK",
512 "TIOCGDEV||TCGETX", "TCSETX", "TCSETXF", "TCSETXW", "TIOCSIG",
513 "TIOCVHANGUP", "TIOCGPKT", "TIOCGPTLCK", "TIOCGEXCL",
514 [0x50] = "FIONCLEX", "FIOCLEX", "FIOASYNC", "TIOCSERCONFIG",
515 "TIOCSERGWILD", "TIOCSERSWILD", "TIOCGLCKTRMIOS", "TIOCSLCKTRMIOS",
516 "TIOCSERGSTRUCT", "TIOCSERGETLSR", "TIOCSERGETMULTI", "TIOCSERSETMULTI",
517 "TIOCMIWAIT", "TIOCGICOUNT", [0x60] = "FIOQSIZE",
518};
519
520static DEFINE_STRARRAY_OFFSET(tioctls, 0x5401);
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -0300521#endif /* defined(__i386__) || defined(__x86_64__) */
Arnaldo Carvalho de Melo78645cf2013-10-08 17:43:20 -0300522
Arnaldo Carvalho de Meloa355a612016-04-13 11:55:18 -0300523#ifndef GRND_NONBLOCK
524#define GRND_NONBLOCK 0x0001
525#endif
526#ifndef GRND_RANDOM
527#define GRND_RANDOM 0x0002
528#endif
529
Arnaldo Carvalho de Melo39878d42016-03-30 20:02:15 -0300530static size_t syscall_arg__scnprintf_getrandom_flags(char *bf, size_t size,
531 struct syscall_arg *arg)
532{
533 int printed = 0, flags = arg->val;
534
535#define P_FLAG(n) \
536 if (flags & GRND_##n) { \
537 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
538 flags &= ~GRND_##n; \
539 }
540
541 P_FLAG(RANDOM);
542 P_FLAG(NONBLOCK);
543#undef P_FLAG
544
545 if (flags)
546 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
547
548 return printed;
549}
550
551#define SCA_GETRANDOM_FLAGS syscall_arg__scnprintf_getrandom_flags
552
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300553#define STRARRAY(arg, name, array) \
554 .arg_scnprintf = { [arg] = SCA_STRARRAY, }, \
555 .arg_parm = { [arg] = &strarray__##array, }
556
Arnaldo Carvalho de Meloea8dc3c2016-04-13 12:10:19 -0300557#include "trace/beauty/eventfd.c"
Arnaldo Carvalho de Melo8bf382c2016-05-11 10:29:36 -0300558#include "trace/beauty/flock.c"
Arnaldo Carvalho de Melod5d71e82016-05-06 12:45:25 -0300559#include "trace/beauty/futex_op.c"
Arnaldo Carvalho de Melodf4cb162016-04-13 12:05:44 -0300560#include "trace/beauty/mmap.c"
Arnaldo Carvalho de Meloba2f22c2016-04-07 12:05:51 -0300561#include "trace/beauty/mode_t.c"
Arnaldo Carvalho de Meloa30e6252016-04-27 19:01:52 -0300562#include "trace/beauty/msg_flags.c"
Arnaldo Carvalho de Melo8f48df62016-05-06 10:02:32 -0300563#include "trace/beauty/open_flags.c"
Arnaldo Carvalho de Melo62de3442016-04-26 11:03:03 -0300564#include "trace/beauty/perf_event_open.c"
Arnaldo Carvalho de Melod5d71e82016-05-06 12:45:25 -0300565#include "trace/beauty/pid.c"
Arnaldo Carvalho de Meloa3bca912016-04-06 12:51:33 -0300566#include "trace/beauty/sched_policy.c"
Arnaldo Carvalho de Melof5cd95e2016-05-11 10:32:20 -0300567#include "trace/beauty/seccomp.c"
Arnaldo Carvalho de Melo12199d82016-05-06 09:58:02 -0300568#include "trace/beauty/signum.c"
Arnaldo Carvalho de Melobbf86c42016-04-14 13:53:10 -0300569#include "trace/beauty/socket_type.c"
Arnaldo Carvalho de Melo7206b902016-04-06 14:11:36 -0300570#include "trace/beauty/waitid_options.c"
Arnaldo Carvalho de Meloa3bca912016-04-06 12:51:33 -0300571
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300572static struct syscall_fmt {
573 const char *name;
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -0300574 const char *alias;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300575 size_t (*arg_scnprintf[6])(char *bf, size_t size, struct syscall_arg *arg);
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300576 void *arg_parm[6];
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300577 bool errmsg;
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -0300578 bool errpid;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300579 bool timeout;
Arnaldo Carvalho de Melo04b34722013-08-26 11:36:30 -0300580 bool hexret;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300581} syscall_fmts[] = {
Arnaldo Carvalho de Melo51108992013-09-04 11:42:27 -0300582 { .name = "access", .errmsg = true,
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -0300583 .arg_scnprintf = { [1] = SCA_ACCMODE, /* mode */ }, },
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -0300584 { .name = "arch_prctl", .errmsg = true, .alias = "prctl", },
Arnaldo Carvalho de Melo729a7842015-10-29 11:48:18 -0300585 { .name = "bpf", .errmsg = true, STRARRAY(0, cmd, bpf_cmd), },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -0300586 { .name = "brk", .hexret = true,
587 .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, },
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -0300588 { .name = "chdir", .errmsg = true, },
589 { .name = "chmod", .errmsg = true, },
590 { .name = "chroot", .errmsg = true, },
David Ahern4f8c1b72013-09-22 19:45:00 -0600591 { .name = "clock_gettime", .errmsg = true, STRARRAY(0, clk_id, clockid), },
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -0300592 { .name = "clone", .errpid = true, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300593 { .name = "close", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300594 .arg_scnprintf = { [0] = SCA_CLOSE_FD, /* fd */ }, },
Arnaldo Carvalho de Meloa14bb862013-07-30 16:38:23 -0300595 { .name = "connect", .errmsg = true, },
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -0300596 { .name = "creat", .errmsg = true, },
Arnaldo Carvalho de Melob6565c92016-05-23 12:59:53 -0300597 { .name = "dup", .errmsg = true, },
598 { .name = "dup2", .errmsg = true, },
599 { .name = "dup3", .errmsg = true, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300600 { .name = "epoll_ctl", .errmsg = true, STRARRAY(1, op, epoll_ctl_ops), },
Arnaldo Carvalho de Melo49af9e92013-09-12 12:18:56 -0300601 { .name = "eventfd2", .errmsg = true,
602 .arg_scnprintf = { [1] = SCA_EFD_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -0300603 { .name = "faccessat", .errmsg = true, },
Arnaldo Carvalho de Melob6565c92016-05-23 12:59:53 -0300604 { .name = "fadvise64", .errmsg = true, },
605 { .name = "fallocate", .errmsg = true, },
606 { .name = "fchdir", .errmsg = true, },
607 { .name = "fchmod", .errmsg = true, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300608 { .name = "fchmodat", .errmsg = true,
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -0300609 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
Arnaldo Carvalho de Melob6565c92016-05-23 12:59:53 -0300610 { .name = "fchown", .errmsg = true, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300611 { .name = "fchownat", .errmsg = true,
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -0300612 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300613 { .name = "fcntl", .errmsg = true,
Arnaldo Carvalho de Melob6565c92016-05-23 12:59:53 -0300614 .arg_scnprintf = { [1] = SCA_STRARRAY, /* cmd */ },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300615 .arg_parm = { [1] = &strarray__fcntl_cmds, /* cmd */ }, },
Arnaldo Carvalho de Melob6565c92016-05-23 12:59:53 -0300616 { .name = "fdatasync", .errmsg = true, },
Arnaldo Carvalho de Melo5cea6ff2013-09-20 11:49:50 -0300617 { .name = "flock", .errmsg = true,
Arnaldo Carvalho de Melob6565c92016-05-23 12:59:53 -0300618 .arg_scnprintf = { [1] = SCA_FLOCK, /* cmd */ }, },
619 { .name = "fsetxattr", .errmsg = true, },
620 { .name = "fstat", .errmsg = true, .alias = "newfstat", },
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -0300621 { .name = "fstatat", .errmsg = true, .alias = "newfstatat", },
Arnaldo Carvalho de Melob6565c92016-05-23 12:59:53 -0300622 { .name = "fstatfs", .errmsg = true, },
623 { .name = "fsync", .errmsg = true, },
624 { .name = "ftruncate", .errmsg = true, },
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -0300625 { .name = "futex", .errmsg = true,
626 .arg_scnprintf = { [1] = SCA_FUTEX_OP, /* op */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300627 { .name = "futimesat", .errmsg = true,
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -0300628 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
Arnaldo Carvalho de Melob6565c92016-05-23 12:59:53 -0300629 { .name = "getdents", .errmsg = true, },
630 { .name = "getdents64", .errmsg = true, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300631 { .name = "getitimer", .errmsg = true, STRARRAY(0, which, itimers), },
Arnaldo Carvalho de Meloc65f1072016-04-06 14:55:18 -0300632 { .name = "getpid", .errpid = true, },
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -0300633 { .name = "getpgid", .errpid = true, },
Arnaldo Carvalho de Meloc65f1072016-04-06 14:55:18 -0300634 { .name = "getppid", .errpid = true, },
Arnaldo Carvalho de Melo39878d42016-03-30 20:02:15 -0300635 { .name = "getrandom", .errmsg = true,
636 .arg_scnprintf = { [2] = SCA_GETRANDOM_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300637 { .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -0300638 { .name = "getxattr", .errmsg = true, },
639 { .name = "inotify_add_watch", .errmsg = true, },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -0300640 { .name = "ioctl", .errmsg = true,
Arnaldo Carvalho de Melob6565c92016-05-23 12:59:53 -0300641 .arg_scnprintf = {
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -0300642#if defined(__i386__) || defined(__x86_64__)
643/*
644 * FIXME: Make this available to all arches.
645 */
Arnaldo Carvalho de Melo78645cf2013-10-08 17:43:20 -0300646 [1] = SCA_STRHEXARRAY, /* cmd */
647 [2] = SCA_HEX, /* arg */ },
648 .arg_parm = { [1] = &strarray__tioctls, /* cmd */ }, },
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -0300649#else
650 [2] = SCA_HEX, /* arg */ }, },
651#endif
Arnaldo Carvalho de Melob62bee12015-08-11 11:05:36 -0300652 { .name = "keyctl", .errmsg = true, STRARRAY(0, option, keyctl_options), },
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -0300653 { .name = "kill", .errmsg = true,
654 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -0300655 { .name = "lchown", .errmsg = true, },
656 { .name = "lgetxattr", .errmsg = true, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300657 { .name = "linkat", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300658 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -0300659 { .name = "listxattr", .errmsg = true, },
660 { .name = "llistxattr", .errmsg = true, },
661 { .name = "lremovexattr", .errmsg = true, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300662 { .name = "lseek", .errmsg = true,
Arnaldo Carvalho de Melob6565c92016-05-23 12:59:53 -0300663 .arg_scnprintf = { [2] = SCA_STRARRAY, /* whence */ },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300664 .arg_parm = { [2] = &strarray__whences, /* whence */ }, },
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -0300665 { .name = "lsetxattr", .errmsg = true, },
666 { .name = "lstat", .errmsg = true, .alias = "newlstat", },
667 { .name = "lsxattr", .errmsg = true, },
Arnaldo Carvalho de Melo9e9716d2013-08-23 10:06:41 -0300668 { .name = "madvise", .errmsg = true,
669 .arg_scnprintf = { [0] = SCA_HEX, /* start */
670 [2] = SCA_MADV_BHV, /* behavior */ }, },
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -0300671 { .name = "mkdir", .errmsg = true, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300672 { .name = "mkdirat", .errmsg = true,
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -0300673 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
674 { .name = "mknod", .errmsg = true, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300675 { .name = "mknodat", .errmsg = true,
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -0300676 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
Arnaldo Carvalho de Melo3d903aa2013-09-24 00:09:38 -0300677 { .name = "mlock", .errmsg = true,
678 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
679 { .name = "mlockall", .errmsg = true,
680 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -0300681 { .name = "mmap", .hexret = true,
Arnaldo Carvalho de Meloae685382013-08-20 17:44:42 -0300682 .arg_scnprintf = { [0] = SCA_HEX, /* addr */
Arnaldo Carvalho de Melo941557e2013-08-23 10:48:33 -0300683 [2] = SCA_MMAP_PROT, /* prot */
Arnaldo Carvalho de Melob6565c92016-05-23 12:59:53 -0300684 [3] = SCA_MMAP_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -0300685 { .name = "mprotect", .errmsg = true,
Arnaldo Carvalho de Meloae685382013-08-20 17:44:42 -0300686 .arg_scnprintf = { [0] = SCA_HEX, /* start */
687 [2] = SCA_MMAP_PROT, /* prot */ }, },
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -0300688 { .name = "mq_unlink", .errmsg = true,
689 .arg_scnprintf = { [0] = SCA_FILENAME, /* u_name */ }, },
Arnaldo Carvalho de Meloae685382013-08-20 17:44:42 -0300690 { .name = "mremap", .hexret = true,
691 .arg_scnprintf = { [0] = SCA_HEX, /* addr */
Alex Snast86998dd2014-08-13 18:42:40 +0300692 [3] = SCA_MREMAP_FLAGS, /* flags */
Arnaldo Carvalho de Meloae685382013-08-20 17:44:42 -0300693 [4] = SCA_HEX, /* new_addr */ }, },
Arnaldo Carvalho de Melo3d903aa2013-09-24 00:09:38 -0300694 { .name = "munlock", .errmsg = true,
695 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -0300696 { .name = "munmap", .errmsg = true,
697 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300698 { .name = "name_to_handle_at", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300699 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300700 { .name = "newfstatat", .errmsg = true,
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -0300701 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
Arnaldo Carvalho de Melobe65a892013-09-02 16:22:31 -0300702 { .name = "open", .errmsg = true,
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -0300703 .arg_scnprintf = { [1] = SCA_OPEN_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo31cd3852013-09-02 16:40:40 -0300704 { .name = "open_by_handle_at", .errmsg = true,
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300705 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
706 [2] = SCA_OPEN_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo31cd3852013-09-02 16:40:40 -0300707 { .name = "openat", .errmsg = true,
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300708 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
709 [2] = SCA_OPEN_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Meloa1c25522015-06-11 22:47:54 -0300710 { .name = "perf_event_open", .errmsg = true,
Arnaldo Carvalho de Meloccd9b2a2016-04-26 11:40:17 -0300711 .arg_scnprintf = { [2] = SCA_INT, /* cpu */
Arnaldo Carvalho de Meloa1c25522015-06-11 22:47:54 -0300712 [3] = SCA_FD, /* group_fd */
713 [4] = SCA_PERF_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo46cce192013-09-23 12:52:04 -0300714 { .name = "pipe2", .errmsg = true,
715 .arg_scnprintf = { [1] = SCA_PIPE_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -0300716 { .name = "poll", .errmsg = true, .timeout = true, },
717 { .name = "ppoll", .errmsg = true, .timeout = true, },
Arnaldo Carvalho de Melob6565c92016-05-23 12:59:53 -0300718 { .name = "pread", .errmsg = true, .alias = "pread64", },
719 { .name = "preadv", .errmsg = true, .alias = "pread", },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300720 { .name = "prlimit64", .errmsg = true, STRARRAY(1, resource, rlimit_resources), },
Arnaldo Carvalho de Melob6565c92016-05-23 12:59:53 -0300721 { .name = "pwrite", .errmsg = true, .alias = "pwrite64", },
722 { .name = "pwritev", .errmsg = true, },
723 { .name = "read", .errmsg = true, },
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -0300724 { .name = "readlink", .errmsg = true, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300725 { .name = "readlinkat", .errmsg = true,
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -0300726 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
Arnaldo Carvalho de Melob6565c92016-05-23 12:59:53 -0300727 { .name = "readv", .errmsg = true, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -0300728 { .name = "recvfrom", .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 = "recvmmsg", .errmsg = true,
Arnaldo Carvalho de Melob6565c92016-05-23 12:59:53 -0300731 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -0300732 { .name = "recvmsg", .errmsg = true,
Arnaldo Carvalho de Melob6565c92016-05-23 12:59:53 -0300733 .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -0300734 { .name = "removexattr", .errmsg = true, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300735 { .name = "renameat", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300736 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -0300737 { .name = "rmdir", .errmsg = true, },
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -0300738 { .name = "rt_sigaction", .errmsg = true,
739 .arg_scnprintf = { [0] = SCA_SIGNUM, /* sig */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300740 { .name = "rt_sigprocmask", .errmsg = true, STRARRAY(0, how, sighow), },
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -0300741 { .name = "rt_sigqueueinfo", .errmsg = true,
742 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
743 { .name = "rt_tgsigqueueinfo", .errmsg = true,
744 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
Arnaldo Carvalho de Melof0bbd602016-09-28 13:45:38 -0300745 { .name = "sched_getattr", .errmsg = true, },
746 { .name = "sched_setattr", .errmsg = true, },
Arnaldo Carvalho de Meloa3bca912016-04-06 12:51:33 -0300747 { .name = "sched_setscheduler", .errmsg = true,
748 .arg_scnprintf = { [1] = SCA_SCHED_POLICY, /* policy */ }, },
Arnaldo Carvalho de Melo997bba82016-03-30 19:43:32 -0300749 { .name = "seccomp", .errmsg = true,
750 .arg_scnprintf = { [0] = SCA_SECCOMP_OP, /* op */
751 [1] = SCA_SECCOMP_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -0300752 { .name = "select", .errmsg = true, .timeout = true, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -0300753 { .name = "sendmmsg", .errmsg = true,
Arnaldo Carvalho de Melob6565c92016-05-23 12:59:53 -0300754 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -0300755 { .name = "sendmsg", .errmsg = true,
Arnaldo Carvalho de Melob6565c92016-05-23 12:59:53 -0300756 .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -0300757 { .name = "sendto", .errmsg = true,
Arnaldo Carvalho de Melob6565c92016-05-23 12:59:53 -0300758 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Meloc65f1072016-04-06 14:55:18 -0300759 { .name = "set_tid_address", .errpid = true, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300760 { .name = "setitimer", .errmsg = true, STRARRAY(0, which, itimers), },
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -0300761 { .name = "setpgid", .errmsg = true, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300762 { .name = "setrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -0300763 { .name = "setxattr", .errmsg = true, },
Arnaldo Carvalho de Melob6565c92016-05-23 12:59:53 -0300764 { .name = "shutdown", .errmsg = true, },
Arnaldo Carvalho de Meloe10bce82013-09-04 10:27:41 -0300765 { .name = "socket", .errmsg = true,
Arnaldo Carvalho de Meloa28b24b2013-09-04 11:00:44 -0300766 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
767 [1] = SCA_SK_TYPE, /* type */ },
Arnaldo Carvalho de Meloe10bce82013-09-04 10:27:41 -0300768 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, },
Arnaldo Carvalho de Melo07120aa2013-09-20 12:24:20 -0300769 { .name = "socketpair", .errmsg = true,
770 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
771 [1] = SCA_SK_TYPE, /* type */ },
772 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, },
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -0300773 { .name = "stat", .errmsg = true, .alias = "newstat", },
774 { .name = "statfs", .errmsg = true, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300775 { .name = "swapoff", .errmsg = true,
776 .arg_scnprintf = { [0] = SCA_FILENAME, /* specialfile */ }, },
777 { .name = "swapon", .errmsg = true,
778 .arg_scnprintf = { [0] = SCA_FILENAME, /* specialfile */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300779 { .name = "symlinkat", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300780 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -0300781 { .name = "tgkill", .errmsg = true,
782 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
783 { .name = "tkill", .errmsg = true,
784 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -0300785 { .name = "truncate", .errmsg = true, },
Arnaldo Carvalho de Meloe5959682013-08-26 12:21:41 -0300786 { .name = "uname", .errmsg = true, .alias = "newuname", },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300787 { .name = "unlinkat", .errmsg = true,
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -0300788 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
789 { .name = "utime", .errmsg = true, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300790 { .name = "utimensat", .errmsg = true,
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -0300791 .arg_scnprintf = { [0] = SCA_FDAT, /* dirfd */ }, },
792 { .name = "utimes", .errmsg = true, },
Arnaldo Carvalho de Melob6565c92016-05-23 12:59:53 -0300793 { .name = "vmsplice", .errmsg = true, },
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -0300794 { .name = "wait4", .errpid = true,
Arnaldo Carvalho de Melo7206b902016-04-06 14:11:36 -0300795 .arg_scnprintf = { [2] = SCA_WAITID_OPTIONS, /* options */ }, },
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -0300796 { .name = "waitid", .errpid = true,
Arnaldo Carvalho de Melo7206b902016-04-06 14:11:36 -0300797 .arg_scnprintf = { [3] = SCA_WAITID_OPTIONS, /* options */ }, },
Arnaldo Carvalho de Melob6565c92016-05-23 12:59:53 -0300798 { .name = "write", .errmsg = true, },
799 { .name = "writev", .errmsg = true, },
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300800};
801
802static int syscall_fmt__cmp(const void *name, const void *fmtp)
803{
804 const struct syscall_fmt *fmt = fmtp;
805 return strcmp(name, fmt->name);
806}
807
808static struct syscall_fmt *syscall_fmt__find(const char *name)
809{
810 const int nmemb = ARRAY_SIZE(syscall_fmts);
811 return bsearch(name, syscall_fmts, nmemb, sizeof(struct syscall_fmt), syscall_fmt__cmp);
812}
813
814struct syscall {
815 struct event_format *tp_format;
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -0300816 int nr_args;
817 struct format_field *args;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300818 const char *name;
Arnaldo Carvalho de Melo5089f202014-06-17 14:29:24 -0300819 bool is_exit;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300820 struct syscall_fmt *fmt;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300821 size_t (**arg_scnprintf)(char *bf, size_t size, struct syscall_arg *arg);
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300822 void **arg_parm;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300823};
824
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -0200825static size_t fprintf_duration(unsigned long t, FILE *fp)
826{
827 double duration = (double)t / NSEC_PER_MSEC;
828 size_t printed = fprintf(fp, "(");
829
830 if (duration >= 1.0)
831 printed += color_fprintf(fp, PERF_COLOR_RED, "%6.3f ms", duration);
832 else if (duration >= 0.01)
833 printed += color_fprintf(fp, PERF_COLOR_YELLOW, "%6.3f ms", duration);
834 else
835 printed += color_fprintf(fp, PERF_COLOR_NORMAL, "%6.3f ms", duration);
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -0300836 return printed + fprintf(fp, "): ");
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -0200837}
838
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -0300839/**
840 * filename.ptr: The filename char pointer that will be vfs_getname'd
841 * filename.entry_str_pos: Where to insert the string translated from
842 * filename.ptr by the vfs_getname tracepoint/kprobe.
843 */
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300844struct thread_trace {
845 u64 entry_time;
846 u64 exit_time;
847 bool entry_pending;
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -0300848 unsigned long nr_events;
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +0400849 unsigned long pfmaj, pfmin;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300850 char *entry_str;
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -0300851 double runtime_ms;
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -0300852 struct {
853 unsigned long ptr;
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -0300854 short int entry_str_pos;
855 bool pending_open;
856 unsigned int namelen;
857 char *name;
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -0300858 } filename;
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300859 struct {
860 int max;
861 char **table;
862 } paths;
David Ahernbf2575c2013-10-08 21:26:53 -0600863
864 struct intlist *syscall_stats;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300865};
866
867static struct thread_trace *thread_trace__new(void)
868{
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300869 struct thread_trace *ttrace = zalloc(sizeof(struct thread_trace));
870
871 if (ttrace)
872 ttrace->paths.max = -1;
873
David Ahernbf2575c2013-10-08 21:26:53 -0600874 ttrace->syscall_stats = intlist__new(NULL);
875
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300876 return ttrace;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300877}
878
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -0300879static struct thread_trace *thread__trace(struct thread *thread, FILE *fp)
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300880{
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -0300881 struct thread_trace *ttrace;
882
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300883 if (thread == NULL)
884 goto fail;
885
Namhyung Kim89dceb22014-10-06 09:46:03 +0900886 if (thread__priv(thread) == NULL)
887 thread__set_priv(thread, thread_trace__new());
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300888
Namhyung Kim89dceb22014-10-06 09:46:03 +0900889 if (thread__priv(thread) == NULL)
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300890 goto fail;
891
Namhyung Kim89dceb22014-10-06 09:46:03 +0900892 ttrace = thread__priv(thread);
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -0300893 ++ttrace->nr_events;
894
895 return ttrace;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300896fail:
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -0300897 color_fprintf(fp, PERF_COLOR_RED,
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -0300898 "WARNING: not enough memory, dropping samples!\n");
899 return NULL;
900}
901
Stanislav Fomichev598d02c2014-06-26 20:14:25 +0400902#define TRACE_PFMAJ (1 << 0)
903#define TRACE_PFMIN (1 << 1)
904
Arnaldo Carvalho de Meloe4d44e82015-08-04 22:17:29 -0300905static const size_t trace__entry_str_size = 2048;
906
Arnaldo Carvalho de Melo97119f32013-09-27 17:34:10 -0300907static int trace__set_fd_pathname(struct thread *thread, int fd, const char *pathname)
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300908{
Namhyung Kim89dceb22014-10-06 09:46:03 +0900909 struct thread_trace *ttrace = thread__priv(thread);
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300910
911 if (fd > ttrace->paths.max) {
912 char **npath = realloc(ttrace->paths.table, (fd + 1) * sizeof(char *));
913
914 if (npath == NULL)
915 return -1;
916
917 if (ttrace->paths.max != -1) {
918 memset(npath + ttrace->paths.max + 1, 0,
919 (fd - ttrace->paths.max) * sizeof(char *));
920 } else {
921 memset(npath, 0, (fd + 1) * sizeof(char *));
922 }
923
924 ttrace->paths.table = npath;
925 ttrace->paths.max = fd;
926 }
927
928 ttrace->paths.table[fd] = strdup(pathname);
929
930 return ttrace->paths.table[fd] != NULL ? 0 : -1;
931}
932
Arnaldo Carvalho de Melo97119f32013-09-27 17:34:10 -0300933static int thread__read_fd_path(struct thread *thread, int fd)
934{
935 char linkname[PATH_MAX], pathname[PATH_MAX];
936 struct stat st;
937 int ret;
938
939 if (thread->pid_ == thread->tid) {
940 scnprintf(linkname, sizeof(linkname),
941 "/proc/%d/fd/%d", thread->pid_, fd);
942 } else {
943 scnprintf(linkname, sizeof(linkname),
944 "/proc/%d/task/%d/fd/%d", thread->pid_, thread->tid, fd);
945 }
946
947 if (lstat(linkname, &st) < 0 || st.st_size + 1 > (off_t)sizeof(pathname))
948 return -1;
949
950 ret = readlink(linkname, pathname, sizeof(pathname));
951
952 if (ret < 0 || ret > st.st_size)
953 return -1;
954
955 pathname[ret] = '\0';
956 return trace__set_fd_pathname(thread, fd, pathname);
957}
958
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -0300959static const char *thread__fd_path(struct thread *thread, int fd,
960 struct trace *trace)
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300961{
Namhyung Kim89dceb22014-10-06 09:46:03 +0900962 struct thread_trace *ttrace = thread__priv(thread);
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300963
964 if (ttrace == NULL)
965 return NULL;
966
967 if (fd < 0)
968 return NULL;
969
Arnaldo Carvalho de Melocdcd1e62014-06-10 16:00:18 -0300970 if ((fd > ttrace->paths.max || ttrace->paths.table[fd] == NULL)) {
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -0300971 if (!trace->live)
972 return NULL;
973 ++trace->stats.proc_getname;
Arnaldo Carvalho de Melocdcd1e62014-06-10 16:00:18 -0300974 if (thread__read_fd_path(thread, fd))
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -0300975 return NULL;
976 }
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300977
978 return ttrace->paths.table[fd];
979}
980
981static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
982 struct syscall_arg *arg)
983{
984 int fd = arg->val;
985 size_t printed = scnprintf(bf, size, "%d", fd);
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -0300986 const char *path = thread__fd_path(arg->thread, fd, arg->trace);
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300987
988 if (path)
989 printed += scnprintf(bf + printed, size - printed, "<%s>", path);
990
991 return printed;
992}
993
994static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
995 struct syscall_arg *arg)
996{
997 int fd = arg->val;
998 size_t printed = syscall_arg__scnprintf_fd(bf, size, arg);
Namhyung Kim89dceb22014-10-06 09:46:03 +0900999 struct thread_trace *ttrace = thread__priv(arg->thread);
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001000
Arnaldo Carvalho de Melo04662522013-12-26 17:41:15 -03001001 if (ttrace && fd >= 0 && fd <= ttrace->paths.max)
1002 zfree(&ttrace->paths.table[fd]);
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001003
1004 return printed;
1005}
1006
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001007static void thread__set_filename_pos(struct thread *thread, const char *bf,
1008 unsigned long ptr)
1009{
1010 struct thread_trace *ttrace = thread__priv(thread);
1011
1012 ttrace->filename.ptr = ptr;
1013 ttrace->filename.entry_str_pos = bf - ttrace->entry_str;
1014}
1015
1016static size_t syscall_arg__scnprintf_filename(char *bf, size_t size,
1017 struct syscall_arg *arg)
1018{
1019 unsigned long ptr = arg->val;
1020
1021 if (!arg->trace->vfs_getname)
1022 return scnprintf(bf, size, "%#x", ptr);
1023
1024 thread__set_filename_pos(arg->thread, bf, ptr);
1025 return 0;
1026}
1027
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001028static bool trace__filter_duration(struct trace *trace, double t)
1029{
1030 return t < (trace->duration_filter * NSEC_PER_MSEC);
1031}
1032
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001033static size_t trace__fprintf_tstamp(struct trace *trace, u64 tstamp, FILE *fp)
1034{
1035 double ts = (double)(tstamp - trace->base_time) / NSEC_PER_MSEC;
1036
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001037 return fprintf(fp, "%10.3f ", ts);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001038}
1039
Namhyung Kimf15eb532012-10-05 14:02:16 +09001040static bool done = false;
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03001041static bool interrupted = false;
Namhyung Kimf15eb532012-10-05 14:02:16 +09001042
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03001043static void sig_handler(int sig)
Namhyung Kimf15eb532012-10-05 14:02:16 +09001044{
1045 done = true;
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03001046 interrupted = sig == SIGINT;
Namhyung Kimf15eb532012-10-05 14:02:16 +09001047}
1048
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001049static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thread,
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001050 u64 duration, u64 tstamp, FILE *fp)
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001051{
1052 size_t printed = trace__fprintf_tstamp(trace, tstamp, fp);
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001053 printed += fprintf_duration(duration, fp);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001054
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -03001055 if (trace->multiple_threads) {
1056 if (trace->show_comm)
Frederic Weisbecker1902efe2013-09-11 16:56:44 +02001057 printed += fprintf(fp, "%.14s/", thread__comm_str(thread));
Adrian Hunter38051232013-07-04 16:20:31 +03001058 printed += fprintf(fp, "%d ", thread->tid);
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -03001059 }
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001060
1061 return printed;
1062}
1063
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001064static int trace__process_event(struct trace *trace, struct machine *machine,
Frederic Weisbecker162f0be2013-09-11 16:18:24 +02001065 union perf_event *event, struct perf_sample *sample)
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001066{
1067 int ret = 0;
1068
1069 switch (event->header.type) {
1070 case PERF_RECORD_LOST:
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001071 color_fprintf(trace->output, PERF_COLOR_RED,
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001072 "LOST %" PRIu64 " events!\n", event->lost.lost);
Frederic Weisbecker162f0be2013-09-11 16:18:24 +02001073 ret = machine__process_lost_event(machine, event, sample);
Arnaldo Carvalho de Melo3ed5ca22016-03-30 16:51:17 -03001074 break;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001075 default:
Frederic Weisbecker162f0be2013-09-11 16:18:24 +02001076 ret = machine__process_event(machine, event, sample);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001077 break;
1078 }
1079
1080 return ret;
1081}
1082
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001083static int trace__tool_process(struct perf_tool *tool,
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001084 union perf_event *event,
Frederic Weisbecker162f0be2013-09-11 16:18:24 +02001085 struct perf_sample *sample,
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001086 struct machine *machine)
1087{
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001088 struct trace *trace = container_of(tool, struct trace, tool);
Frederic Weisbecker162f0be2013-09-11 16:18:24 +02001089 return trace__process_event(trace, machine, event, sample);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001090}
1091
Arnaldo Carvalho de Melocaf8a0d2016-05-17 11:56:24 -03001092static char *trace__machine__resolve_kernel_addr(void *vmachine, unsigned long long *addrp, char **modp)
1093{
1094 struct machine *machine = vmachine;
1095
1096 if (machine->kptr_restrict_warned)
1097 return NULL;
1098
1099 if (symbol_conf.kptr_restrict) {
1100 pr_warning("Kernel address maps (/proc/{kallsyms,modules}) are restricted.\n\n"
1101 "Check /proc/sys/kernel/kptr_restrict.\n\n"
1102 "Kernel samples will not be resolved.\n");
1103 machine->kptr_restrict_warned = true;
1104 return NULL;
1105 }
1106
1107 return machine__resolve_kernel_addr(vmachine, addrp, modp);
1108}
1109
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001110static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
1111{
Namhyung Kim0a7e6d12014-08-12 15:40:45 +09001112 int err = symbol__init(NULL);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001113
1114 if (err)
1115 return err;
1116
David Ahern8fb598e2013-09-28 13:13:00 -06001117 trace->host = machine__new_host();
1118 if (trace->host == NULL)
1119 return -ENOMEM;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001120
Arnaldo Carvalho de Melocaf8a0d2016-05-17 11:56:24 -03001121 if (trace_event__register_resolver(trace->host, trace__machine__resolve_kernel_addr) < 0)
Arnaldo Carvalho de Melo706c3da2015-07-22 16:16:16 -03001122 return -errno;
1123
Arnaldo Carvalho de Meloa33fbd52013-11-11 11:36:12 -03001124 err = __machine__synthesize_threads(trace->host, &trace->tool, &trace->opts.target,
Kan Liang9d9cad72015-06-17 09:51:11 -04001125 evlist->threads, trace__tool_process, false,
1126 trace->opts.proc_map_timeout);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001127 if (err)
1128 symbol__exit();
1129
1130 return err;
1131}
1132
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001133static int syscall__set_arg_fmts(struct syscall *sc)
1134{
1135 struct format_field *field;
Arnaldo Carvalho de Melob6565c92016-05-23 12:59:53 -03001136 int idx = 0, len;
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001137
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001138 sc->arg_scnprintf = calloc(sc->nr_args, sizeof(void *));
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001139 if (sc->arg_scnprintf == NULL)
1140 return -1;
1141
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -03001142 if (sc->fmt)
1143 sc->arg_parm = sc->fmt->arg_parm;
1144
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001145 for (field = sc->args; field; field = field->next) {
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -03001146 if (sc->fmt && sc->fmt->arg_scnprintf[idx])
1147 sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx];
Arnaldo Carvalho de Melo12f3ca42016-05-23 16:37:55 -03001148 else if (strcmp(field->type, "const char *") == 0 &&
1149 (strcmp(field->name, "filename") == 0 ||
1150 strcmp(field->name, "path") == 0 ||
1151 strcmp(field->name, "pathname") == 0))
1152 sc->arg_scnprintf[idx] = SCA_FILENAME;
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -03001153 else if (field->flags & FIELD_IS_POINTER)
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001154 sc->arg_scnprintf[idx] = syscall_arg__scnprintf_hex;
Arnaldo Carvalho de Melod1d438a2016-04-06 18:02:41 -03001155 else if (strcmp(field->type, "pid_t") == 0)
1156 sc->arg_scnprintf[idx] = SCA_PID;
Arnaldo Carvalho de Meloba2f22c2016-04-07 12:05:51 -03001157 else if (strcmp(field->type, "umode_t") == 0)
1158 sc->arg_scnprintf[idx] = SCA_MODE_T;
Arnaldo Carvalho de Melob6565c92016-05-23 12:59:53 -03001159 else if ((strcmp(field->type, "int") == 0 ||
1160 strcmp(field->type, "unsigned int") == 0 ||
1161 strcmp(field->type, "long") == 0) &&
1162 (len = strlen(field->name)) >= 2 &&
1163 strcmp(field->name + len - 2, "fd") == 0) {
1164 /*
1165 * /sys/kernel/tracing/events/syscalls/sys_enter*
1166 * egrep 'field:.*fd;' .../format|sed -r 's/.*field:([a-z ]+) [a-z_]*fd.+/\1/g'|sort|uniq -c
1167 * 65 int
1168 * 23 unsigned int
1169 * 7 unsigned long
1170 */
1171 sc->arg_scnprintf[idx] = SCA_FD;
1172 }
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001173 ++idx;
1174 }
1175
1176 return 0;
1177}
1178
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001179static int trace__read_syscall_info(struct trace *trace, int id)
1180{
1181 char tp_name[128];
1182 struct syscall *sc;
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03001183 const char *name = syscalltbl__name(trace->sctbl, id);
Arnaldo Carvalho de Melo3a531262012-10-20 12:39:03 -03001184
1185 if (name == NULL)
1186 return -1;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001187
1188 if (id > trace->syscalls.max) {
1189 struct syscall *nsyscalls = realloc(trace->syscalls.table, (id + 1) * sizeof(*sc));
1190
1191 if (nsyscalls == NULL)
1192 return -1;
1193
1194 if (trace->syscalls.max != -1) {
1195 memset(nsyscalls + trace->syscalls.max + 1, 0,
1196 (id - trace->syscalls.max) * sizeof(*sc));
1197 } else {
1198 memset(nsyscalls, 0, (id + 1) * sizeof(*sc));
1199 }
1200
1201 trace->syscalls.table = nsyscalls;
1202 trace->syscalls.max = id;
1203 }
1204
1205 sc = trace->syscalls.table + id;
Arnaldo Carvalho de Melo3a531262012-10-20 12:39:03 -03001206 sc->name = name;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001207
Arnaldo Carvalho de Melo3a531262012-10-20 12:39:03 -03001208 sc->fmt = syscall_fmt__find(sc->name);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001209
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -03001210 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name);
Jiri Olsa97978b32013-12-03 14:09:24 +01001211 sc->tp_format = trace_event__tp_format("syscalls", tp_name);
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -03001212
Jiri Olsa8dd2a132015-09-07 10:38:06 +02001213 if (IS_ERR(sc->tp_format) && sc->fmt && sc->fmt->alias) {
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -03001214 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->fmt->alias);
Jiri Olsa97978b32013-12-03 14:09:24 +01001215 sc->tp_format = trace_event__tp_format("syscalls", tp_name);
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -03001216 }
1217
Jiri Olsa8dd2a132015-09-07 10:38:06 +02001218 if (IS_ERR(sc->tp_format))
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001219 return -1;
1220
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001221 sc->args = sc->tp_format->format.fields;
1222 sc->nr_args = sc->tp_format->format.nr_fields;
Taeung Songc42de702016-02-26 22:14:25 +09001223 /*
1224 * We need to check and discard the first variable '__syscall_nr'
1225 * or 'nr' that mean the syscall number. It is needless here.
1226 * So drop '__syscall_nr' or 'nr' field but does not exist on older kernels.
1227 */
1228 if (sc->args && (!strcmp(sc->args->name, "__syscall_nr") || !strcmp(sc->args->name, "nr"))) {
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001229 sc->args = sc->args->next;
1230 --sc->nr_args;
1231 }
1232
Arnaldo Carvalho de Melo5089f202014-06-17 14:29:24 -03001233 sc->is_exit = !strcmp(name, "exit_group") || !strcmp(name, "exit");
1234
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001235 return syscall__set_arg_fmts(sc);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001236}
1237
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001238static int trace__validate_ev_qualifier(struct trace *trace)
1239{
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001240 int err = 0, i;
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001241 struct str_node *pos;
1242
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001243 trace->ev_qualifier_ids.nr = strlist__nr_entries(trace->ev_qualifier);
1244 trace->ev_qualifier_ids.entries = malloc(trace->ev_qualifier_ids.nr *
1245 sizeof(trace->ev_qualifier_ids.entries[0]));
1246
1247 if (trace->ev_qualifier_ids.entries == NULL) {
1248 fputs("Error:\tNot enough memory for allocating events qualifier ids\n",
1249 trace->output);
1250 err = -EINVAL;
1251 goto out;
1252 }
1253
1254 i = 0;
1255
Arnaldo Carvalho de Melo602a1f42016-06-23 11:31:20 -03001256 strlist__for_each_entry(pos, trace->ev_qualifier) {
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001257 const char *sc = pos->s;
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03001258 int id = syscalltbl__id(trace->sctbl, sc);
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001259
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001260 if (id < 0) {
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001261 if (err == 0) {
1262 fputs("Error:\tInvalid syscall ", trace->output);
1263 err = -EINVAL;
1264 } else {
1265 fputs(", ", trace->output);
1266 }
1267
1268 fputs(sc, trace->output);
1269 }
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001270
1271 trace->ev_qualifier_ids.entries[i++] = id;
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001272 }
1273
1274 if (err < 0) {
1275 fputs("\nHint:\ttry 'perf list syscalls:sys_enter_*'"
1276 "\nHint:\tand: 'man syscalls'\n", trace->output);
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001277 zfree(&trace->ev_qualifier_ids.entries);
1278 trace->ev_qualifier_ids.nr = 0;
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001279 }
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001280out:
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001281 return err;
1282}
1283
David Ahern55d43bc2015-02-19 15:00:22 -05001284/*
1285 * args is to be interpreted as a series of longs but we need to handle
1286 * 8-byte unaligned accesses. args points to raw_data within the event
1287 * and raw_data is guaranteed to be 8-byte unaligned because it is
1288 * preceded by raw_size which is a u32. So we need to copy args to a temp
1289 * variable to read it. Most notably this avoids extended load instructions
1290 * on unaligned addresses
1291 */
1292
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001293static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
David Ahern55d43bc2015-02-19 15:00:22 -05001294 unsigned char *args, struct trace *trace,
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001295 struct thread *thread)
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001296{
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001297 size_t printed = 0;
David Ahern55d43bc2015-02-19 15:00:22 -05001298 unsigned char *p;
1299 unsigned long val;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001300
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001301 if (sc->args != NULL) {
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001302 struct format_field *field;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001303 u8 bit = 1;
1304 struct syscall_arg arg = {
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001305 .idx = 0,
1306 .mask = 0,
1307 .trace = trace,
1308 .thread = thread,
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001309 };
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001310
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001311 for (field = sc->args; field;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001312 field = field->next, ++arg.idx, bit <<= 1) {
1313 if (arg.mask & bit)
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -03001314 continue;
David Ahern55d43bc2015-02-19 15:00:22 -05001315
1316 /* special care for unaligned accesses */
1317 p = args + sizeof(unsigned long) * arg.idx;
1318 memcpy(&val, p, sizeof(val));
1319
Arnaldo Carvalho de Melo4aa58232013-09-20 12:19:41 -03001320 /*
1321 * Suppress this argument if its value is zero and
1322 * and we don't have a string associated in an
1323 * strarray for it.
1324 */
David Ahern55d43bc2015-02-19 15:00:22 -05001325 if (val == 0 &&
Arnaldo Carvalho de Melo4aa58232013-09-20 12:19:41 -03001326 !(sc->arg_scnprintf &&
1327 sc->arg_scnprintf[arg.idx] == SCA_STRARRAY &&
1328 sc->arg_parm[arg.idx]))
Arnaldo Carvalho de Melo22ae5cf12013-09-12 11:27:34 -03001329 continue;
1330
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001331 printed += scnprintf(bf + printed, size - printed,
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001332 "%s%s: ", printed ? ", " : "", field->name);
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001333 if (sc->arg_scnprintf && sc->arg_scnprintf[arg.idx]) {
David Ahern55d43bc2015-02-19 15:00:22 -05001334 arg.val = val;
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -03001335 if (sc->arg_parm)
1336 arg.parm = sc->arg_parm[arg.idx];
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001337 printed += sc->arg_scnprintf[arg.idx](bf + printed,
1338 size - printed, &arg);
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -03001339 } else {
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001340 printed += scnprintf(bf + printed, size - printed,
David Ahern55d43bc2015-02-19 15:00:22 -05001341 "%ld", val);
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -03001342 }
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001343 }
Arnaldo Carvalho de Melo4c4d6e52016-05-05 23:38:05 -03001344 } else if (IS_ERR(sc->tp_format)) {
1345 /*
1346 * If we managed to read the tracepoint /format file, then we
1347 * may end up not having any args, like with gettid(), so only
1348 * print the raw args when we didn't manage to read it.
1349 */
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001350 int i = 0;
1351
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001352 while (i < 6) {
David Ahern55d43bc2015-02-19 15:00:22 -05001353 /* special care for unaligned accesses */
1354 p = args + sizeof(unsigned long) * i;
1355 memcpy(&val, p, sizeof(val));
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001356 printed += scnprintf(bf + printed, size - printed,
1357 "%sarg%d: %ld",
David Ahern55d43bc2015-02-19 15:00:22 -05001358 printed ? ", " : "", i, val);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001359 ++i;
1360 }
1361 }
1362
1363 return printed;
1364}
1365
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001366typedef int (*tracepoint_handler)(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04001367 union perf_event *event,
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001368 struct perf_sample *sample);
1369
1370static struct syscall *trace__syscall_info(struct trace *trace,
David Ahernbf2575c2013-10-08 21:26:53 -06001371 struct perf_evsel *evsel, int id)
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001372{
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001373
1374 if (id < 0) {
Arnaldo Carvalho de Meloadaa18b2013-08-22 17:55:25 -03001375
1376 /*
1377 * XXX: Noticed on x86_64, reproduced as far back as 3.0.36, haven't tried
1378 * before that, leaving at a higher verbosity level till that is
1379 * explained. Reproduced with plain ftrace with:
1380 *
1381 * echo 1 > /t/events/raw_syscalls/sys_exit/enable
1382 * grep "NR -1 " /t/trace_pipe
1383 *
1384 * After generating some load on the machine.
1385 */
1386 if (verbose > 1) {
1387 static u64 n;
1388 fprintf(trace->output, "Invalid syscall %d id, skipping (%s, %" PRIu64 ") ...\n",
1389 id, perf_evsel__name(evsel), ++n);
1390 }
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001391 return NULL;
1392 }
1393
1394 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL) &&
1395 trace__read_syscall_info(trace, id))
1396 goto out_cant_read;
1397
1398 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL))
1399 goto out_cant_read;
1400
1401 return &trace->syscalls.table[id];
1402
1403out_cant_read:
Arnaldo Carvalho de Melo7c304ee02013-08-22 16:49:54 -03001404 if (verbose) {
1405 fprintf(trace->output, "Problems reading syscall %d", id);
1406 if (id <= trace->syscalls.max && trace->syscalls.table[id].name != NULL)
1407 fprintf(trace->output, "(%s)", trace->syscalls.table[id].name);
1408 fputs(" information\n", trace->output);
1409 }
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001410 return NULL;
1411}
1412
David Ahernbf2575c2013-10-08 21:26:53 -06001413static void thread__update_stats(struct thread_trace *ttrace,
1414 int id, struct perf_sample *sample)
1415{
1416 struct int_node *inode;
1417 struct stats *stats;
1418 u64 duration = 0;
1419
1420 inode = intlist__findnew(ttrace->syscall_stats, id);
1421 if (inode == NULL)
1422 return;
1423
1424 stats = inode->priv;
1425 if (stats == NULL) {
1426 stats = malloc(sizeof(struct stats));
1427 if (stats == NULL)
1428 return;
1429 init_stats(stats);
1430 inode->priv = stats;
1431 }
1432
1433 if (ttrace->entry_time && sample->time > ttrace->entry_time)
1434 duration = sample->time - ttrace->entry_time;
1435
1436 update_stats(stats, duration);
1437}
1438
Arnaldo Carvalho de Meloe5966632015-02-13 13:22:21 -03001439static int trace__printf_interrupted_entry(struct trace *trace, struct perf_sample *sample)
1440{
1441 struct thread_trace *ttrace;
1442 u64 duration;
1443 size_t printed;
1444
1445 if (trace->current == NULL)
1446 return 0;
1447
1448 ttrace = thread__priv(trace->current);
1449
1450 if (!ttrace->entry_pending)
1451 return 0;
1452
1453 duration = sample->time - ttrace->entry_time;
1454
Arnaldo Carvalho de Melo567eea52016-10-18 11:28:32 -03001455 printed = trace__fprintf_entry_head(trace, trace->current, duration, ttrace->entry_time, trace->output);
Arnaldo Carvalho de Meloe5966632015-02-13 13:22:21 -03001456 printed += fprintf(trace->output, "%-70s) ...\n", ttrace->entry_str);
1457 ttrace->entry_pending = false;
1458
1459 return printed;
1460}
1461
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001462static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04001463 union perf_event *event __maybe_unused,
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001464 struct perf_sample *sample)
1465{
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001466 char *msg;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001467 void *args;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001468 size_t printed = 0;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001469 struct thread *thread;
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001470 int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
David Ahernbf2575c2013-10-08 21:26:53 -06001471 struct syscall *sc = trace__syscall_info(trace, evsel, id);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001472 struct thread_trace *ttrace;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001473
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001474 if (sc == NULL)
1475 return -1;
1476
David Ahern8fb598e2013-09-28 13:13:00 -06001477 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001478 ttrace = thread__trace(thread, trace->output);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001479 if (ttrace == NULL)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001480 goto out_put;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001481
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -03001482 args = perf_evsel__sc_tp_ptr(evsel, args, sample);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001483
1484 if (ttrace->entry_str == NULL) {
Arnaldo Carvalho de Meloe4d44e82015-08-04 22:17:29 -03001485 ttrace->entry_str = malloc(trace__entry_str_size);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001486 if (!ttrace->entry_str)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001487 goto out_put;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001488 }
1489
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -03001490 if (!(trace->duration_filter || trace->summary_only || trace->min_stack))
Arnaldo Carvalho de Melo6ebad5c2015-03-25 18:01:15 -03001491 trace__printf_interrupted_entry(trace, sample);
Arnaldo Carvalho de Meloe5966632015-02-13 13:22:21 -03001492
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001493 ttrace->entry_time = sample->time;
1494 msg = ttrace->entry_str;
Arnaldo Carvalho de Meloe4d44e82015-08-04 22:17:29 -03001495 printed += scnprintf(msg + printed, trace__entry_str_size - printed, "%s(", sc->name);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001496
Arnaldo Carvalho de Meloe4d44e82015-08-04 22:17:29 -03001497 printed += syscall__scnprintf_args(sc, msg + printed, trace__entry_str_size - printed,
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001498 args, trace, thread);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001499
Arnaldo Carvalho de Melo5089f202014-06-17 14:29:24 -03001500 if (sc->is_exit) {
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -03001501 if (!(trace->duration_filter || trace->summary_only || trace->min_stack)) {
Arnaldo Carvalho de Melo567eea52016-10-18 11:28:32 -03001502 trace__fprintf_entry_head(trace, thread, 1, ttrace->entry_time, trace->output);
Arnaldo Carvalho de Meloc008f782016-05-17 12:13:54 -03001503 fprintf(trace->output, "%-70s)\n", ttrace->entry_str);
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001504 }
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03001505 } else {
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001506 ttrace->entry_pending = true;
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03001507 /* See trace__vfs_getname & trace__sys_exit */
1508 ttrace->filename.pending_open = false;
1509 }
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001510
Arnaldo Carvalho de Melof3b623b2015-03-02 22:21:35 -03001511 if (trace->current != thread) {
1512 thread__put(trace->current);
1513 trace->current = thread__get(thread);
1514 }
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001515 err = 0;
1516out_put:
1517 thread__put(thread);
1518 return err;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001519}
1520
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -03001521static int trace__resolve_callchain(struct trace *trace, struct perf_evsel *evsel,
1522 struct perf_sample *sample,
1523 struct callchain_cursor *cursor)
Arnaldo Carvalho de Melo202ff962016-04-12 10:11:07 -03001524{
1525 struct addr_location al;
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -03001526
1527 if (machine__resolve(trace->host, &al, sample) < 0 ||
1528 thread__resolve_callchain(al.thread, cursor, evsel, sample, NULL, NULL, trace->max_stack))
1529 return -1;
1530
1531 return 0;
1532}
1533
1534static int trace__fprintf_callchain(struct trace *trace, struct perf_sample *sample)
1535{
Arnaldo Carvalho de Melo202ff962016-04-12 10:11:07 -03001536 /* TODO: user-configurable print_opts */
Arnaldo Carvalho de Meloe20ab862016-04-12 15:16:15 -03001537 const unsigned int print_opts = EVSEL__PRINT_SYM |
1538 EVSEL__PRINT_DSO |
1539 EVSEL__PRINT_UNKNOWN_AS_ADDR;
Arnaldo Carvalho de Melo202ff962016-04-12 10:11:07 -03001540
Arnaldo Carvalho de Melod327e602016-04-14 17:53:49 -03001541 return sample__fprintf_callchain(sample, 38, print_opts, &callchain_cursor, trace->output);
Arnaldo Carvalho de Melo202ff962016-04-12 10:11:07 -03001542}
1543
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001544static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04001545 union perf_event *event __maybe_unused,
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001546 struct perf_sample *sample)
1547{
Chang Hyun Park2c82c3a2014-09-26 21:54:01 +09001548 long ret;
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001549 u64 duration = 0;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001550 struct thread *thread;
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -03001551 int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1, callchain_ret = 0;
David Ahernbf2575c2013-10-08 21:26:53 -06001552 struct syscall *sc = trace__syscall_info(trace, evsel, id);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001553 struct thread_trace *ttrace;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001554
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001555 if (sc == NULL)
1556 return -1;
1557
David Ahern8fb598e2013-09-28 13:13:00 -06001558 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001559 ttrace = thread__trace(thread, trace->output);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001560 if (ttrace == NULL)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001561 goto out_put;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001562
David Ahernbf2575c2013-10-08 21:26:53 -06001563 if (trace->summary)
1564 thread__update_stats(ttrace, id, sample);
1565
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -03001566 ret = perf_evsel__sc_tp_uint(evsel, ret, sample);
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001567
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03001568 if (id == trace->open_id && ret >= 0 && ttrace->filename.pending_open) {
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03001569 trace__set_fd_pathname(thread, ret, ttrace->filename.name);
1570 ttrace->filename.pending_open = false;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001571 ++trace->stats.vfs_getname;
1572 }
1573
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001574 ttrace->exit_time = sample->time;
1575
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001576 if (ttrace->entry_time) {
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001577 duration = sample->time - ttrace->entry_time;
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001578 if (trace__filter_duration(trace, duration))
1579 goto out;
1580 } else if (trace->duration_filter)
1581 goto out;
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001582
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -03001583 if (sample->callchain) {
1584 callchain_ret = trace__resolve_callchain(trace, evsel, sample, &callchain_cursor);
1585 if (callchain_ret == 0) {
1586 if (callchain_cursor.nr < trace->min_stack)
1587 goto out;
1588 callchain_ret = 1;
1589 }
1590 }
1591
David Ahernfd2eaba2013-11-12 09:31:15 -07001592 if (trace->summary_only)
1593 goto out;
1594
Arnaldo Carvalho de Melo567eea52016-10-18 11:28:32 -03001595 trace__fprintf_entry_head(trace, thread, duration, ttrace->entry_time, trace->output);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001596
1597 if (ttrace->entry_pending) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001598 fprintf(trace->output, "%-70s", ttrace->entry_str);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001599 } else {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001600 fprintf(trace->output, " ... [");
1601 color_fprintf(trace->output, PERF_COLOR_YELLOW, "continued");
1602 fprintf(trace->output, "]: %s()", sc->name);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001603 }
1604
Arnaldo Carvalho de Meloda3c9a42013-08-26 11:28:34 -03001605 if (sc->fmt == NULL) {
1606signed_print:
Chang Hyun Park2c82c3a2014-09-26 21:54:01 +09001607 fprintf(trace->output, ") = %ld", ret);
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -03001608 } else if (ret < 0 && (sc->fmt->errmsg || sc->fmt->errpid)) {
Masami Hiramatsu942a91e2014-08-14 02:22:41 +00001609 char bf[STRERR_BUFSIZE];
Arnaldo Carvalho de Meloc8b5f2c2016-07-06 11:56:20 -03001610 const char *emsg = str_error_r(-ret, bf, sizeof(bf)),
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001611 *e = audit_errno_to_name(-ret);
1612
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001613 fprintf(trace->output, ") = -1 %s %s", e, emsg);
Arnaldo Carvalho de Meloda3c9a42013-08-26 11:28:34 -03001614 } else if (ret == 0 && sc->fmt->timeout)
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001615 fprintf(trace->output, ") = 0 Timeout");
Arnaldo Carvalho de Melo04b34722013-08-26 11:36:30 -03001616 else if (sc->fmt->hexret)
Chang Hyun Park2c82c3a2014-09-26 21:54:01 +09001617 fprintf(trace->output, ") = %#lx", ret);
Arnaldo Carvalho de Melo11c8e392016-04-06 14:33:07 -03001618 else if (sc->fmt->errpid) {
1619 struct thread *child = machine__find_thread(trace->host, ret, ret);
1620
1621 if (child != NULL) {
1622 fprintf(trace->output, ") = %ld", ret);
1623 if (child->comm_set)
1624 fprintf(trace->output, " (%s)", thread__comm_str(child));
1625 thread__put(child);
1626 }
1627 } else
Arnaldo Carvalho de Meloda3c9a42013-08-26 11:28:34 -03001628 goto signed_print;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001629
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001630 fputc('\n', trace->output);
Milian Wolff566a0882016-04-08 13:34:15 +02001631
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -03001632 if (callchain_ret > 0)
1633 trace__fprintf_callchain(trace, sample);
1634 else if (callchain_ret < 0)
1635 pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel));
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001636out:
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001637 ttrace->entry_pending = false;
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001638 err = 0;
1639out_put:
1640 thread__put(thread);
1641 return err;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001642}
1643
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001644static int trace__vfs_getname(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04001645 union perf_event *event __maybe_unused,
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001646 struct perf_sample *sample)
1647{
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001648 struct thread *thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
1649 struct thread_trace *ttrace;
1650 size_t filename_len, entry_str_len, to_move;
1651 ssize_t remaining_space;
1652 char *pos;
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03001653 const char *filename = perf_evsel__rawptr(evsel, sample, "pathname");
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001654
1655 if (!thread)
1656 goto out;
1657
1658 ttrace = thread__priv(thread);
1659 if (!ttrace)
1660 goto out;
1661
Arnaldo Carvalho de Melo7f4f8002015-08-14 13:16:27 -03001662 filename_len = strlen(filename);
1663
1664 if (ttrace->filename.namelen < filename_len) {
1665 char *f = realloc(ttrace->filename.name, filename_len + 1);
1666
1667 if (f == NULL)
1668 goto out;
1669
1670 ttrace->filename.namelen = filename_len;
1671 ttrace->filename.name = f;
1672 }
1673
1674 strcpy(ttrace->filename.name, filename);
1675 ttrace->filename.pending_open = true;
1676
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001677 if (!ttrace->filename.ptr)
1678 goto out;
1679
1680 entry_str_len = strlen(ttrace->entry_str);
1681 remaining_space = trace__entry_str_size - entry_str_len - 1; /* \0 */
1682 if (remaining_space <= 0)
1683 goto out;
1684
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001685 if (filename_len > (size_t)remaining_space) {
1686 filename += filename_len - remaining_space;
1687 filename_len = remaining_space;
1688 }
1689
1690 to_move = entry_str_len - ttrace->filename.entry_str_pos + 1; /* \0 */
1691 pos = ttrace->entry_str + ttrace->filename.entry_str_pos;
1692 memmove(pos + filename_len, pos, to_move);
1693 memcpy(pos, filename, filename_len);
1694
1695 ttrace->filename.ptr = 0;
1696 ttrace->filename.entry_str_pos = 0;
1697out:
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001698 return 0;
1699}
1700
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001701static int trace__sched_stat_runtime(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04001702 union perf_event *event __maybe_unused,
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001703 struct perf_sample *sample)
1704{
1705 u64 runtime = perf_evsel__intval(evsel, sample, "runtime");
1706 double runtime_ms = (double)runtime / NSEC_PER_MSEC;
David Ahern8fb598e2013-09-28 13:13:00 -06001707 struct thread *thread = machine__findnew_thread(trace->host,
Adrian Hunter314add62013-08-27 11:23:03 +03001708 sample->pid,
1709 sample->tid);
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001710 struct thread_trace *ttrace = thread__trace(thread, trace->output);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001711
1712 if (ttrace == NULL)
1713 goto out_dump;
1714
1715 ttrace->runtime_ms += runtime_ms;
1716 trace->runtime_ms += runtime_ms;
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001717 thread__put(thread);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001718 return 0;
1719
1720out_dump:
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001721 fprintf(trace->output, "%s: comm=%s,pid=%u,runtime=%" PRIu64 ",vruntime=%" PRIu64 ")\n",
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001722 evsel->name,
1723 perf_evsel__strval(evsel, sample, "comm"),
1724 (pid_t)perf_evsel__intval(evsel, sample, "pid"),
1725 runtime,
1726 perf_evsel__intval(evsel, sample, "vruntime"));
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001727 thread__put(thread);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001728 return 0;
1729}
1730
Wang Nan1d6c9402016-02-26 09:31:55 +00001731static void bpf_output__printer(enum binary_printer_ops op,
1732 unsigned int val, void *extra)
1733{
1734 FILE *output = extra;
1735 unsigned char ch = (unsigned char)val;
1736
1737 switch (op) {
1738 case BINARY_PRINT_CHAR_DATA:
1739 fprintf(output, "%c", isprint(ch) ? ch : '.');
1740 break;
1741 case BINARY_PRINT_DATA_BEGIN:
1742 case BINARY_PRINT_LINE_BEGIN:
1743 case BINARY_PRINT_ADDR:
1744 case BINARY_PRINT_NUM_DATA:
1745 case BINARY_PRINT_NUM_PAD:
1746 case BINARY_PRINT_SEP:
1747 case BINARY_PRINT_CHAR_PAD:
1748 case BINARY_PRINT_LINE_END:
1749 case BINARY_PRINT_DATA_END:
1750 default:
1751 break;
1752 }
1753}
1754
1755static void bpf_output__fprintf(struct trace *trace,
1756 struct perf_sample *sample)
1757{
1758 print_binary(sample->raw_data, sample->raw_size, 8,
1759 bpf_output__printer, trace->output);
1760}
1761
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03001762static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
1763 union perf_event *event __maybe_unused,
1764 struct perf_sample *sample)
1765{
Arnaldo Carvalho de Melo7ad35612016-04-20 19:55:48 -03001766 int callchain_ret = 0;
1767
1768 if (sample->callchain) {
1769 callchain_ret = trace__resolve_callchain(trace, evsel, sample, &callchain_cursor);
1770 if (callchain_ret == 0) {
1771 if (callchain_cursor.nr < trace->min_stack)
1772 goto out;
1773 callchain_ret = 1;
1774 }
1775 }
1776
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03001777 trace__printf_interrupted_entry(trace, sample);
1778 trace__fprintf_tstamp(trace, sample->time, trace->output);
Arnaldo Carvalho de Melo08089212015-02-19 21:51:50 -08001779
1780 if (trace->trace_syscalls)
1781 fprintf(trace->output, "( ): ");
1782
1783 fprintf(trace->output, "%s:", evsel->name);
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03001784
Wang Nan1d6c9402016-02-26 09:31:55 +00001785 if (perf_evsel__is_bpf_output(evsel)) {
1786 bpf_output__fprintf(trace, sample);
1787 } else if (evsel->tp_format) {
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03001788 event_format__fprintf(evsel->tp_format, sample->cpu,
1789 sample->raw_data, sample->raw_size,
1790 trace->output);
1791 }
1792
1793 fprintf(trace->output, ")\n");
Arnaldo Carvalho de Melo202ff962016-04-12 10:11:07 -03001794
Arnaldo Carvalho de Melo7ad35612016-04-20 19:55:48 -03001795 if (callchain_ret > 0)
1796 trace__fprintf_callchain(trace, sample);
1797 else if (callchain_ret < 0)
1798 pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel));
1799out:
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03001800 return 0;
1801}
1802
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04001803static void print_location(FILE *f, struct perf_sample *sample,
1804 struct addr_location *al,
1805 bool print_dso, bool print_sym)
1806{
1807
1808 if ((verbose || print_dso) && al->map)
1809 fprintf(f, "%s@", al->map->dso->long_name);
1810
1811 if ((verbose || print_sym) && al->sym)
Arnaldo Carvalho de Melo4414a3c2014-07-08 15:39:21 -03001812 fprintf(f, "%s+0x%" PRIx64, al->sym->name,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04001813 al->addr - al->sym->start);
1814 else if (al->map)
Arnaldo Carvalho de Melo4414a3c2014-07-08 15:39:21 -03001815 fprintf(f, "0x%" PRIx64, al->addr);
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04001816 else
Arnaldo Carvalho de Melo4414a3c2014-07-08 15:39:21 -03001817 fprintf(f, "0x%" PRIx64, sample->addr);
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04001818}
1819
1820static int trace__pgfault(struct trace *trace,
1821 struct perf_evsel *evsel,
Arnaldo Carvalho de Melo473398a2016-03-22 18:23:43 -03001822 union perf_event *event __maybe_unused,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04001823 struct perf_sample *sample)
1824{
1825 struct thread *thread;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04001826 struct addr_location al;
1827 char map_type = 'd';
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04001828 struct thread_trace *ttrace;
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001829 int err = -1;
Arnaldo Carvalho de Melo1df54292016-04-20 20:06:02 -03001830 int callchain_ret = 0;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04001831
1832 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
Arnaldo Carvalho de Melo1df54292016-04-20 20:06:02 -03001833
1834 if (sample->callchain) {
1835 callchain_ret = trace__resolve_callchain(trace, evsel, sample, &callchain_cursor);
1836 if (callchain_ret == 0) {
1837 if (callchain_cursor.nr < trace->min_stack)
1838 goto out_put;
1839 callchain_ret = 1;
1840 }
1841 }
1842
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04001843 ttrace = thread__trace(thread, trace->output);
1844 if (ttrace == NULL)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001845 goto out_put;
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04001846
1847 if (evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ)
1848 ttrace->pfmaj++;
1849 else
1850 ttrace->pfmin++;
1851
1852 if (trace->summary_only)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001853 goto out;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04001854
Arnaldo Carvalho de Melo473398a2016-03-22 18:23:43 -03001855 thread__find_addr_location(thread, sample->cpumode, MAP__FUNCTION,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04001856 sample->ip, &al);
1857
1858 trace__fprintf_entry_head(trace, thread, 0, sample->time, trace->output);
1859
1860 fprintf(trace->output, "%sfault [",
1861 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ?
1862 "maj" : "min");
1863
1864 print_location(trace->output, sample, &al, false, true);
1865
1866 fprintf(trace->output, "] => ");
1867
Arnaldo Carvalho de Melo473398a2016-03-22 18:23:43 -03001868 thread__find_addr_location(thread, sample->cpumode, MAP__VARIABLE,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04001869 sample->addr, &al);
1870
1871 if (!al.map) {
Arnaldo Carvalho de Melo473398a2016-03-22 18:23:43 -03001872 thread__find_addr_location(thread, sample->cpumode,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04001873 MAP__FUNCTION, sample->addr, &al);
1874
1875 if (al.map)
1876 map_type = 'x';
1877 else
1878 map_type = '?';
1879 }
1880
1881 print_location(trace->output, sample, &al, true, false);
1882
1883 fprintf(trace->output, " (%c%c)\n", map_type, al.level);
Arnaldo Carvalho de Melo0c3a6ef2016-04-19 16:31:12 -03001884
Arnaldo Carvalho de Melo1df54292016-04-20 20:06:02 -03001885 if (callchain_ret > 0)
1886 trace__fprintf_callchain(trace, sample);
1887 else if (callchain_ret < 0)
1888 pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel));
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001889out:
1890 err = 0;
1891out_put:
1892 thread__put(thread);
1893 return err;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04001894}
1895
David Ahernbdc89662013-08-28 22:29:53 -06001896static bool skip_sample(struct trace *trace, struct perf_sample *sample)
1897{
1898 if ((trace->pid_list && intlist__find(trace->pid_list, sample->pid)) ||
1899 (trace->tid_list && intlist__find(trace->tid_list, sample->tid)))
1900 return false;
1901
1902 if (trace->pid_list || trace->tid_list)
1903 return true;
1904
1905 return false;
1906}
1907
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03001908static void trace__set_base_time(struct trace *trace,
Arnaldo Carvalho de Melo8a07a802016-03-31 15:19:39 -03001909 struct perf_evsel *evsel,
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03001910 struct perf_sample *sample)
1911{
Arnaldo Carvalho de Melo8a07a802016-03-31 15:19:39 -03001912 /*
1913 * BPF events were not setting PERF_SAMPLE_TIME, so be more robust
1914 * and don't use sample->time unconditionally, we may end up having
1915 * some other event in the future without PERF_SAMPLE_TIME for good
1916 * reason, i.e. we may not be interested in its timestamps, just in
1917 * it taking place, picking some piece of information when it
1918 * appears in our event stream (vfs_getname comes to mind).
1919 */
1920 if (trace->base_time == 0 && !trace->full_time &&
1921 (evsel->attr.sample_type & PERF_SAMPLE_TIME))
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03001922 trace->base_time = sample->time;
1923}
1924
David Ahern6810fc92013-08-28 22:29:52 -06001925static int trace__process_sample(struct perf_tool *tool,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04001926 union perf_event *event,
David Ahern6810fc92013-08-28 22:29:52 -06001927 struct perf_sample *sample,
1928 struct perf_evsel *evsel,
1929 struct machine *machine __maybe_unused)
1930{
1931 struct trace *trace = container_of(tool, struct trace, tool);
1932 int err = 0;
1933
Arnaldo Carvalho de Melo744a9712013-11-06 10:17:38 -03001934 tracepoint_handler handler = evsel->handler;
David Ahern6810fc92013-08-28 22:29:52 -06001935
David Ahernbdc89662013-08-28 22:29:53 -06001936 if (skip_sample(trace, sample))
1937 return 0;
1938
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03001939 trace__set_base_time(trace, evsel, sample);
David Ahern6810fc92013-08-28 22:29:52 -06001940
David Ahern31605652013-12-04 19:41:41 -07001941 if (handler) {
1942 ++trace->nr_events;
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04001943 handler(trace, evsel, event, sample);
David Ahern31605652013-12-04 19:41:41 -07001944 }
David Ahern6810fc92013-08-28 22:29:52 -06001945
1946 return err;
1947}
1948
David Ahernbdc89662013-08-28 22:29:53 -06001949static int parse_target_str(struct trace *trace)
1950{
1951 if (trace->opts.target.pid) {
1952 trace->pid_list = intlist__new(trace->opts.target.pid);
1953 if (trace->pid_list == NULL) {
1954 pr_err("Error parsing process id string\n");
1955 return -EINVAL;
1956 }
1957 }
1958
1959 if (trace->opts.target.tid) {
1960 trace->tid_list = intlist__new(trace->opts.target.tid);
1961 if (trace->tid_list == NULL) {
1962 pr_err("Error parsing thread id string\n");
1963 return -EINVAL;
1964 }
1965 }
1966
1967 return 0;
1968}
1969
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04001970static int trace__record(struct trace *trace, int argc, const char **argv)
David Ahern5e2485b2013-09-28 13:13:01 -06001971{
1972 unsigned int rec_argc, i, j;
1973 const char **rec_argv;
1974 const char * const record_args[] = {
1975 "record",
1976 "-R",
1977 "-m", "1024",
1978 "-c", "1",
David Ahern5e2485b2013-09-28 13:13:01 -06001979 };
1980
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04001981 const char * const sc_args[] = { "-e", };
1982 unsigned int sc_args_nr = ARRAY_SIZE(sc_args);
1983 const char * const majpf_args[] = { "-e", "major-faults" };
1984 unsigned int majpf_args_nr = ARRAY_SIZE(majpf_args);
1985 const char * const minpf_args[] = { "-e", "minor-faults" };
1986 unsigned int minpf_args_nr = ARRAY_SIZE(minpf_args);
1987
David Ahern9aca7f12013-12-04 19:41:39 -07001988 /* +1 is for the event string below */
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04001989 rec_argc = ARRAY_SIZE(record_args) + sc_args_nr + 1 +
1990 majpf_args_nr + minpf_args_nr + argc;
David Ahern5e2485b2013-09-28 13:13:01 -06001991 rec_argv = calloc(rec_argc + 1, sizeof(char *));
1992
1993 if (rec_argv == NULL)
1994 return -ENOMEM;
1995
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04001996 j = 0;
David Ahern5e2485b2013-09-28 13:13:01 -06001997 for (i = 0; i < ARRAY_SIZE(record_args); i++)
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04001998 rec_argv[j++] = record_args[i];
1999
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002000 if (trace->trace_syscalls) {
2001 for (i = 0; i < sc_args_nr; i++)
2002 rec_argv[j++] = sc_args[i];
David Ahern5e2485b2013-09-28 13:13:01 -06002003
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002004 /* event string may be different for older kernels - e.g., RHEL6 */
2005 if (is_valid_tracepoint("raw_syscalls:sys_enter"))
2006 rec_argv[j++] = "raw_syscalls:sys_enter,raw_syscalls:sys_exit";
2007 else if (is_valid_tracepoint("syscalls:sys_enter"))
2008 rec_argv[j++] = "syscalls:sys_enter,syscalls:sys_exit";
2009 else {
2010 pr_err("Neither raw_syscalls nor syscalls events exist.\n");
2011 return -1;
2012 }
David Ahern9aca7f12013-12-04 19:41:39 -07002013 }
David Ahern9aca7f12013-12-04 19:41:39 -07002014
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002015 if (trace->trace_pgfaults & TRACE_PFMAJ)
2016 for (i = 0; i < majpf_args_nr; i++)
2017 rec_argv[j++] = majpf_args[i];
David Ahern5e2485b2013-09-28 13:13:01 -06002018
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002019 if (trace->trace_pgfaults & TRACE_PFMIN)
2020 for (i = 0; i < minpf_args_nr; i++)
2021 rec_argv[j++] = minpf_args[i];
2022
2023 for (i = 0; i < (unsigned int)argc; i++)
2024 rec_argv[j++] = argv[i];
2025
2026 return cmd_record(j, rec_argv, NULL);
David Ahern5e2485b2013-09-28 13:13:01 -06002027}
2028
David Ahernbf2575c2013-10-08 21:26:53 -06002029static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp);
2030
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002031static bool perf_evlist__add_vfs_getname(struct perf_evlist *evlist)
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002032{
Arnaldo Carvalho de Meloef503832013-11-07 16:41:19 -03002033 struct perf_evsel *evsel = perf_evsel__newtp("probe", "vfs_getname");
Jiri Olsa8dd2a132015-09-07 10:38:06 +02002034
2035 if (IS_ERR(evsel))
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002036 return false;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002037
2038 if (perf_evsel__field(evsel, "pathname") == NULL) {
2039 perf_evsel__delete(evsel);
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002040 return false;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002041 }
2042
Arnaldo Carvalho de Melo744a9712013-11-06 10:17:38 -03002043 evsel->handler = trace__vfs_getname;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002044 perf_evlist__add(evlist, evsel);
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002045 return true;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002046}
2047
Arnaldo Carvalho de Melo0ae537c2016-04-19 16:00:01 -03002048static struct perf_evsel *perf_evsel__new_pgfault(u64 config)
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002049{
2050 struct perf_evsel *evsel;
2051 struct perf_event_attr attr = {
2052 .type = PERF_TYPE_SOFTWARE,
2053 .mmap_data = 1,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002054 };
2055
2056 attr.config = config;
Arnaldo Carvalho de Melo05247982014-07-23 18:15:09 -03002057 attr.sample_period = 1;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002058
2059 event_attr_init(&attr);
2060
2061 evsel = perf_evsel__new(&attr);
Arnaldo Carvalho de Melo0ae537c2016-04-19 16:00:01 -03002062 if (evsel)
2063 evsel->handler = trace__pgfault;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002064
Arnaldo Carvalho de Melo0ae537c2016-04-19 16:00:01 -03002065 return evsel;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002066}
2067
Arnaldo Carvalho de Meloddbb1b12015-02-21 12:10:29 -08002068static void trace__handle_event(struct trace *trace, union perf_event *event, struct perf_sample *sample)
2069{
2070 const u32 type = event->header.type;
2071 struct perf_evsel *evsel;
2072
Arnaldo Carvalho de Meloddbb1b12015-02-21 12:10:29 -08002073 if (type != PERF_RECORD_SAMPLE) {
2074 trace__process_event(trace, trace->host, event, sample);
2075 return;
2076 }
2077
2078 evsel = perf_evlist__id2evsel(trace->evlist, sample->id);
2079 if (evsel == NULL) {
2080 fprintf(trace->output, "Unknown tp ID %" PRIu64 ", skipping...\n", sample->id);
2081 return;
2082 }
2083
Arnaldo Carvalho de Meloe6001982016-03-31 15:16:28 -03002084 trace__set_base_time(trace, evsel, sample);
2085
Arnaldo Carvalho de Meloddbb1b12015-02-21 12:10:29 -08002086 if (evsel->attr.type == PERF_TYPE_TRACEPOINT &&
2087 sample->raw_data == NULL) {
2088 fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n",
2089 perf_evsel__name(evsel), sample->tid,
2090 sample->cpu, sample->raw_size);
2091 } else {
2092 tracepoint_handler handler = evsel->handler;
2093 handler(trace, evsel, event, sample);
2094 }
2095}
2096
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03002097static int trace__add_syscall_newtp(struct trace *trace)
2098{
2099 int ret = -1;
2100 struct perf_evlist *evlist = trace->evlist;
2101 struct perf_evsel *sys_enter, *sys_exit;
2102
2103 sys_enter = perf_evsel__syscall_newtp("sys_enter", trace__sys_enter);
2104 if (sys_enter == NULL)
2105 goto out;
2106
2107 if (perf_evsel__init_sc_tp_ptr_field(sys_enter, args))
2108 goto out_delete_sys_enter;
2109
2110 sys_exit = perf_evsel__syscall_newtp("sys_exit", trace__sys_exit);
2111 if (sys_exit == NULL)
2112 goto out_delete_sys_enter;
2113
2114 if (perf_evsel__init_sc_tp_uint_field(sys_exit, ret))
2115 goto out_delete_sys_exit;
2116
2117 perf_evlist__add(evlist, sys_enter);
2118 perf_evlist__add(evlist, sys_exit);
2119
Arnaldo Carvalho de Melo2ddd5c02016-04-18 12:09:08 -03002120 if (callchain_param.enabled && !trace->kernel_syscallchains) {
Arnaldo Carvalho de Melo44621812016-04-11 15:49:11 -03002121 /*
2122 * We're interested only in the user space callchain
2123 * leading to the syscall, allow overriding that for
2124 * debugging reasons using --kernel_syscall_callchains
2125 */
2126 sys_exit->attr.exclude_callchain_kernel = 1;
2127 }
2128
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03002129 trace->syscalls.events.sys_enter = sys_enter;
2130 trace->syscalls.events.sys_exit = sys_exit;
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03002131
2132 ret = 0;
2133out:
2134 return ret;
2135
2136out_delete_sys_exit:
2137 perf_evsel__delete_priv(sys_exit);
2138out_delete_sys_enter:
2139 perf_evsel__delete_priv(sys_enter);
2140 goto out;
2141}
2142
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002143static int trace__set_ev_qualifier_filter(struct trace *trace)
2144{
2145 int err = -1;
Mathieu Poirierb15d0a42016-09-16 08:44:03 -06002146 struct perf_evsel *sys_exit;
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002147 char *filter = asprintf_expr_inout_ints("id", !trace->not_ev_qualifier,
2148 trace->ev_qualifier_ids.nr,
2149 trace->ev_qualifier_ids.entries);
2150
2151 if (filter == NULL)
2152 goto out_enomem;
2153
Mathieu Poirier3541c032016-09-16 08:44:04 -06002154 if (!perf_evsel__append_tp_filter(trace->syscalls.events.sys_enter,
2155 filter)) {
Mathieu Poirierb15d0a42016-09-16 08:44:03 -06002156 sys_exit = trace->syscalls.events.sys_exit;
Mathieu Poirier3541c032016-09-16 08:44:04 -06002157 err = perf_evsel__append_tp_filter(sys_exit, filter);
Mathieu Poirierb15d0a42016-09-16 08:44:03 -06002158 }
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002159
2160 free(filter);
2161out:
2162 return err;
2163out_enomem:
2164 errno = ENOMEM;
2165 goto out;
2166}
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03002167
Namhyung Kimf15eb532012-10-05 14:02:16 +09002168static int trace__run(struct trace *trace, int argc, const char **argv)
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002169{
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002170 struct perf_evlist *evlist = trace->evlist;
Arnaldo Carvalho de Melo0ae537c2016-04-19 16:00:01 -03002171 struct perf_evsel *evsel, *pgfault_maj = NULL, *pgfault_min = NULL;
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03002172 int err = -1, i;
2173 unsigned long before;
Namhyung Kimf15eb532012-10-05 14:02:16 +09002174 const bool forks = argc > 0;
Arnaldo Carvalho de Melo46fb3c22014-09-22 14:39:48 -03002175 bool draining = false;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002176
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03002177 trace->live = true;
2178
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03002179 if (trace->trace_syscalls && trace__add_syscall_newtp(trace))
Arnaldo Carvalho de Melo801c67b2015-01-22 10:52:55 -03002180 goto out_error_raw_syscalls;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002181
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002182 if (trace->trace_syscalls)
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002183 trace->vfs_getname = perf_evlist__add_vfs_getname(evlist);
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002184
Arnaldo Carvalho de Melo0ae537c2016-04-19 16:00:01 -03002185 if ((trace->trace_pgfaults & TRACE_PFMAJ)) {
2186 pgfault_maj = perf_evsel__new_pgfault(PERF_COUNT_SW_PAGE_FAULTS_MAJ);
2187 if (pgfault_maj == NULL)
2188 goto out_error_mem;
2189 perf_evlist__add(evlist, pgfault_maj);
Arnaldo Carvalho de Meloe2726d92015-01-22 10:34:22 -03002190 }
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002191
Arnaldo Carvalho de Melo0ae537c2016-04-19 16:00:01 -03002192 if ((trace->trace_pgfaults & TRACE_PFMIN)) {
2193 pgfault_min = perf_evsel__new_pgfault(PERF_COUNT_SW_PAGE_FAULTS_MIN);
2194 if (pgfault_min == NULL)
2195 goto out_error_mem;
2196 perf_evlist__add(evlist, pgfault_min);
2197 }
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002198
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002199 if (trace->sched &&
Arnaldo Carvalho de Melo2cc990b2015-01-22 11:13:43 -03002200 perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime",
2201 trace__sched_stat_runtime))
2202 goto out_error_sched_stat_runtime;
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002203
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002204 err = perf_evlist__create_maps(evlist, &trace->opts.target);
2205 if (err < 0) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002206 fprintf(trace->output, "Problems parsing the target to trace, check your options!\n");
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002207 goto out_delete_evlist;
2208 }
2209
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03002210 err = trace__symbols_init(trace, evlist);
2211 if (err < 0) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002212 fprintf(trace->output, "Problems initializing symbol libraries!\n");
Arnaldo Carvalho de Melo03ad9742014-01-03 15:56:06 -03002213 goto out_delete_evlist;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03002214 }
2215
Arnaldo Carvalho de Melofde54b72016-04-11 18:42:37 -03002216 perf_evlist__config(evlist, &trace->opts, NULL);
2217
Arnaldo Carvalho de Melo0c3a6ef2016-04-19 16:31:12 -03002218 if (callchain_param.enabled) {
2219 bool use_identifier = false;
2220
2221 if (trace->syscalls.events.sys_exit) {
2222 perf_evsel__config_callchain(trace->syscalls.events.sys_exit,
2223 &trace->opts, &callchain_param);
2224 use_identifier = true;
2225 }
2226
2227 if (pgfault_maj) {
2228 perf_evsel__config_callchain(pgfault_maj, &trace->opts, &callchain_param);
2229 use_identifier = true;
2230 }
2231
2232 if (pgfault_min) {
2233 perf_evsel__config_callchain(pgfault_min, &trace->opts, &callchain_param);
2234 use_identifier = true;
2235 }
2236
2237 if (use_identifier) {
2238 /*
2239 * Now we have evsels with different sample_ids, use
2240 * PERF_SAMPLE_IDENTIFIER to map from sample to evsel
2241 * from a fixed position in each ring buffer record.
2242 *
2243 * As of this the changeset introducing this comment, this
2244 * isn't strictly needed, as the fields that can come before
2245 * PERF_SAMPLE_ID are all used, but we'll probably disable
2246 * some of those for things like copying the payload of
2247 * pointer syscall arguments, and for vfs_getname we don't
2248 * need PERF_SAMPLE_ADDR and PERF_SAMPLE_IP, so do this
2249 * here as a warning we need to use PERF_SAMPLE_IDENTIFIER.
2250 */
2251 perf_evlist__set_sample_bit(evlist, IDENTIFIER);
2252 perf_evlist__reset_sample_bit(evlist, ID);
2253 }
Arnaldo Carvalho de Melofde54b72016-04-11 18:42:37 -03002254 }
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002255
Namhyung Kimf15eb532012-10-05 14:02:16 +09002256 signal(SIGCHLD, sig_handler);
2257 signal(SIGINT, sig_handler);
2258
2259 if (forks) {
Namhyung Kim6ef73ec2013-03-11 16:43:15 +09002260 err = perf_evlist__prepare_workload(evlist, &trace->opts.target,
Arnaldo Carvalho de Melo735f7e02014-01-03 14:56:49 -03002261 argv, false, NULL);
Namhyung Kimf15eb532012-10-05 14:02:16 +09002262 if (err < 0) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002263 fprintf(trace->output, "Couldn't run the workload!\n");
Arnaldo Carvalho de Melo03ad9742014-01-03 15:56:06 -03002264 goto out_delete_evlist;
Namhyung Kimf15eb532012-10-05 14:02:16 +09002265 }
2266 }
2267
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002268 err = perf_evlist__open(evlist);
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002269 if (err < 0)
2270 goto out_error_open;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002271
Wang Nanba504232016-02-26 09:31:54 +00002272 err = bpf__apply_obj_config();
2273 if (err) {
2274 char errbuf[BUFSIZ];
2275
2276 bpf__strerror_apply_obj_config(err, errbuf, sizeof(errbuf));
2277 pr_err("ERROR: Apply config to BPF failed: %s\n",
2278 errbuf);
2279 goto out_error_open;
2280 }
2281
Arnaldo Carvalho de Melo241b0572015-02-21 10:15:21 -08002282 /*
2283 * Better not use !target__has_task() here because we need to cover the
2284 * case where no threads were specified in the command line, but a
2285 * workload was, and in that case we will fill in the thread_map when
2286 * we fork the workload in perf_evlist__prepare_workload.
2287 */
Arnaldo Carvalho de Melof078c382015-02-21 11:36:52 -08002288 if (trace->filter_pids.nr > 0)
2289 err = perf_evlist__set_filter_pids(evlist, trace->filter_pids.nr, trace->filter_pids.entries);
Jiri Olsae13798c2015-06-23 00:36:02 +02002290 else if (thread_map__pid(evlist->threads, 0) == -1)
Arnaldo Carvalho de Melof078c382015-02-21 11:36:52 -08002291 err = perf_evlist__set_filter_pid(evlist, getpid());
2292
Arnaldo Carvalho de Melo94ad89b2015-07-03 17:42:03 -03002293 if (err < 0)
2294 goto out_error_mem;
2295
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002296 if (trace->ev_qualifier_ids.nr > 0) {
2297 err = trace__set_ev_qualifier_filter(trace);
2298 if (err < 0)
2299 goto out_errno;
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002300
Arnaldo Carvalho de Melo2e5e5f82015-08-03 17:12:29 -03002301 pr_debug("event qualifier tracepoint filter: %s\n",
2302 trace->syscalls.events.sys_exit->filter);
2303 }
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002304
Arnaldo Carvalho de Melo94ad89b2015-07-03 17:42:03 -03002305 err = perf_evlist__apply_filters(evlist, &evsel);
2306 if (err < 0)
2307 goto out_error_apply_filters;
Arnaldo Carvalho de Melo241b0572015-02-21 10:15:21 -08002308
Jiri Olsaf8850372013-11-28 17:57:22 +01002309 err = perf_evlist__mmap(evlist, trace->opts.mmap_pages, false);
Arnaldo Carvalho de Meloe09b18d2014-12-11 18:04:10 -03002310 if (err < 0)
2311 goto out_error_mmap;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002312
Arnaldo Carvalho de Melocb24d012015-04-22 10:04:23 -03002313 if (!target__none(&trace->opts.target))
2314 perf_evlist__enable(evlist);
2315
Namhyung Kimf15eb532012-10-05 14:02:16 +09002316 if (forks)
2317 perf_evlist__start_workload(evlist);
2318
Jiri Olsae13798c2015-06-23 00:36:02 +02002319 trace->multiple_threads = thread_map__pid(evlist->threads, 0) == -1 ||
Arnaldo Carvalho de Melo42052be2015-02-13 12:32:45 -03002320 evlist->threads->nr > 1 ||
2321 perf_evlist__first(evlist)->attr.inherit;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002322again:
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03002323 before = trace->nr_events;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002324
2325 for (i = 0; i < evlist->nr_mmaps; i++) {
2326 union perf_event *event;
2327
2328 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002329 struct perf_sample sample;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002330
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03002331 ++trace->nr_events;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002332
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002333 err = perf_evlist__parse_sample(evlist, event, &sample);
2334 if (err) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002335 fprintf(trace->output, "Can't parse sample, err = %d, skipping...\n", err);
Zhouyi Zhou8e50d382013-10-24 15:43:33 +08002336 goto next_event;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002337 }
2338
Arnaldo Carvalho de Meloddbb1b12015-02-21 12:10:29 -08002339 trace__handle_event(trace, event, &sample);
Zhouyi Zhou8e50d382013-10-24 15:43:33 +08002340next_event:
2341 perf_evlist__mmap_consume(evlist, i);
Arnaldo Carvalho de Melo20c5f102013-09-03 11:55:07 -03002342
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002343 if (interrupted)
2344 goto out_disable;
Arnaldo Carvalho de Melo02ac5422015-04-22 11:11:57 -03002345
2346 if (done && !draining) {
2347 perf_evlist__disable(evlist);
2348 draining = true;
2349 }
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002350 }
2351 }
2352
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03002353 if (trace->nr_events == before) {
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002354 int timeout = done ? 100 : -1;
Namhyung Kimf15eb532012-10-05 14:02:16 +09002355
Arnaldo Carvalho de Melo46fb3c22014-09-22 14:39:48 -03002356 if (!draining && perf_evlist__poll(evlist, timeout) > 0) {
2357 if (perf_evlist__filter_pollfd(evlist, POLLERR | POLLHUP) == 0)
2358 draining = true;
2359
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002360 goto again;
Arnaldo Carvalho de Melo46fb3c22014-09-22 14:39:48 -03002361 }
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002362 } else {
2363 goto again;
Namhyung Kimf15eb532012-10-05 14:02:16 +09002364 }
2365
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002366out_disable:
Arnaldo Carvalho de Melof3b623b2015-03-02 22:21:35 -03002367 thread__zput(trace->current);
2368
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002369 perf_evlist__disable(evlist);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002370
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002371 if (!err) {
2372 if (trace->summary)
2373 trace__fprintf_thread_summary(trace, trace->output);
2374
2375 if (trace->show_tool_stats) {
2376 fprintf(trace->output, "Stats:\n "
2377 " vfs_getname : %" PRIu64 "\n"
2378 " proc_getname: %" PRIu64 "\n",
2379 trace->stats.vfs_getname,
2380 trace->stats.proc_getname);
2381 }
2382 }
David Ahernbf2575c2013-10-08 21:26:53 -06002383
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002384out_delete_evlist:
2385 perf_evlist__delete(evlist);
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002386 trace->evlist = NULL;
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03002387 trace->live = false;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002388 return err;
Arnaldo Carvalho de Melo6ef068c2013-10-17 12:07:58 -03002389{
2390 char errbuf[BUFSIZ];
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002391
Arnaldo Carvalho de Melo2cc990b2015-01-22 11:13:43 -03002392out_error_sched_stat_runtime:
Jiri Olsa988bdb32015-09-02 09:56:35 +02002393 tracing_path__strerror_open_tp(errno, errbuf, sizeof(errbuf), "sched", "sched_stat_runtime");
Arnaldo Carvalho de Melo2cc990b2015-01-22 11:13:43 -03002394 goto out_error;
2395
Arnaldo Carvalho de Melo801c67b2015-01-22 10:52:55 -03002396out_error_raw_syscalls:
Jiri Olsa988bdb32015-09-02 09:56:35 +02002397 tracing_path__strerror_open_tp(errno, errbuf, sizeof(errbuf), "raw_syscalls", "sys_(enter|exit)");
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002398 goto out_error;
2399
Arnaldo Carvalho de Meloe09b18d2014-12-11 18:04:10 -03002400out_error_mmap:
2401 perf_evlist__strerror_mmap(evlist, errno, errbuf, sizeof(errbuf));
2402 goto out_error;
2403
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002404out_error_open:
2405 perf_evlist__strerror_open(evlist, errno, errbuf, sizeof(errbuf));
2406
2407out_error:
Arnaldo Carvalho de Melo6ef068c2013-10-17 12:07:58 -03002408 fprintf(trace->output, "%s\n", errbuf);
Ramkumar Ramachandra87f91862013-10-04 10:47:31 +05302409 goto out_delete_evlist;
Arnaldo Carvalho de Melo94ad89b2015-07-03 17:42:03 -03002410
2411out_error_apply_filters:
2412 fprintf(trace->output,
2413 "Failed to set filter \"%s\" on event %s with %d (%s)\n",
2414 evsel->filter, perf_evsel__name(evsel), errno,
Arnaldo Carvalho de Meloc8b5f2c2016-07-06 11:56:20 -03002415 str_error_r(errno, errbuf, sizeof(errbuf)));
Arnaldo Carvalho de Melo94ad89b2015-07-03 17:42:03 -03002416 goto out_delete_evlist;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002417}
Arnaldo Carvalho de Melo5ed08da2015-01-22 11:08:04 -03002418out_error_mem:
2419 fprintf(trace->output, "Not enough memory to run!\n");
2420 goto out_delete_evlist;
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002421
2422out_errno:
2423 fprintf(trace->output, "errno=%d,%s\n", errno, strerror(errno));
2424 goto out_delete_evlist;
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002425}
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002426
David Ahern6810fc92013-08-28 22:29:52 -06002427static int trace__replay(struct trace *trace)
2428{
2429 const struct perf_evsel_str_handler handlers[] = {
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002430 { "probe:vfs_getname", trace__vfs_getname, },
David Ahern6810fc92013-08-28 22:29:52 -06002431 };
Jiri Olsaf5fc1412013-10-15 16:27:32 +02002432 struct perf_data_file file = {
2433 .path = input_name,
2434 .mode = PERF_DATA_MODE_READ,
Yunlong Songe366a6d2015-04-02 21:47:18 +08002435 .force = trace->force,
Jiri Olsaf5fc1412013-10-15 16:27:32 +02002436 };
David Ahern6810fc92013-08-28 22:29:52 -06002437 struct perf_session *session;
Namhyung Kim003824e2013-11-12 15:25:00 +09002438 struct perf_evsel *evsel;
David Ahern6810fc92013-08-28 22:29:52 -06002439 int err = -1;
2440
2441 trace->tool.sample = trace__process_sample;
2442 trace->tool.mmap = perf_event__process_mmap;
David Ahern384c6712013-09-22 19:44:58 -06002443 trace->tool.mmap2 = perf_event__process_mmap2;
David Ahern6810fc92013-08-28 22:29:52 -06002444 trace->tool.comm = perf_event__process_comm;
2445 trace->tool.exit = perf_event__process_exit;
2446 trace->tool.fork = perf_event__process_fork;
2447 trace->tool.attr = perf_event__process_attr;
2448 trace->tool.tracing_data = perf_event__process_tracing_data;
2449 trace->tool.build_id = perf_event__process_build_id;
2450
Jiri Olsa0a8cb852014-07-06 14:18:21 +02002451 trace->tool.ordered_events = true;
David Ahern6810fc92013-08-28 22:29:52 -06002452 trace->tool.ordering_requires_timestamps = true;
2453
2454 /* add tid to output */
2455 trace->multiple_threads = true;
2456
Jiri Olsaf5fc1412013-10-15 16:27:32 +02002457 session = perf_session__new(&file, false, &trace->tool);
David Ahern6810fc92013-08-28 22:29:52 -06002458 if (session == NULL)
Taeung Song52e028342014-09-24 10:33:37 +09002459 return -1;
David Ahern6810fc92013-08-28 22:29:52 -06002460
Namhyung Kim0a7e6d12014-08-12 15:40:45 +09002461 if (symbol__init(&session->header.env) < 0)
Namhyung Kimcb2ffae2014-08-12 15:40:44 +09002462 goto out;
2463
David Ahern8fb598e2013-09-28 13:13:00 -06002464 trace->host = &session->machines.host;
2465
David Ahern6810fc92013-08-28 22:29:52 -06002466 err = perf_session__set_tracepoints_handlers(session, handlers);
2467 if (err)
2468 goto out;
2469
Namhyung Kim003824e2013-11-12 15:25:00 +09002470 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2471 "raw_syscalls:sys_enter");
David Ahern9aca7f12013-12-04 19:41:39 -07002472 /* older kernels have syscalls tp versus raw_syscalls */
2473 if (evsel == NULL)
2474 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2475 "syscalls:sys_enter");
David Ahern6810fc92013-08-28 22:29:52 -06002476
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002477 if (evsel &&
2478 (perf_evsel__init_syscall_tp(evsel, trace__sys_enter) < 0 ||
2479 perf_evsel__init_sc_tp_ptr_field(evsel, args))) {
Namhyung Kim003824e2013-11-12 15:25:00 +09002480 pr_err("Error during initialize raw_syscalls:sys_enter event\n");
2481 goto out;
2482 }
2483
2484 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2485 "raw_syscalls:sys_exit");
David Ahern9aca7f12013-12-04 19:41:39 -07002486 if (evsel == NULL)
2487 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2488 "syscalls:sys_exit");
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002489 if (evsel &&
2490 (perf_evsel__init_syscall_tp(evsel, trace__sys_exit) < 0 ||
2491 perf_evsel__init_sc_tp_uint_field(evsel, ret))) {
Namhyung Kim003824e2013-11-12 15:25:00 +09002492 pr_err("Error during initialize raw_syscalls:sys_exit event\n");
David Ahern6810fc92013-08-28 22:29:52 -06002493 goto out;
2494 }
2495
Arnaldo Carvalho de Meloe5cadb92016-06-23 11:26:15 -03002496 evlist__for_each_entry(session->evlist, evsel) {
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002497 if (evsel->attr.type == PERF_TYPE_SOFTWARE &&
2498 (evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ||
2499 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MIN ||
2500 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS))
2501 evsel->handler = trace__pgfault;
2502 }
2503
David Ahernbdc89662013-08-28 22:29:53 -06002504 err = parse_target_str(trace);
2505 if (err != 0)
2506 goto out;
2507
David Ahern6810fc92013-08-28 22:29:52 -06002508 setup_pager();
2509
Arnaldo Carvalho de Melob7b61cb2015-03-03 11:58:45 -03002510 err = perf_session__process_events(session);
David Ahern6810fc92013-08-28 22:29:52 -06002511 if (err)
2512 pr_err("Failed to process events, error %d", err);
2513
David Ahernbf2575c2013-10-08 21:26:53 -06002514 else if (trace->summary)
2515 trace__fprintf_thread_summary(trace, trace->output);
2516
David Ahern6810fc92013-08-28 22:29:52 -06002517out:
2518 perf_session__delete(session);
2519
2520 return err;
2521}
2522
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002523static size_t trace__fprintf_threads_header(FILE *fp)
2524{
2525 size_t printed;
2526
Pekka Enberg99ff7152013-11-12 16:42:14 +02002527 printed = fprintf(fp, "\n Summary of events:\n\n");
David Ahernbf2575c2013-10-08 21:26:53 -06002528
2529 return printed;
2530}
2531
Arnaldo Carvalho de Melob535d522016-05-04 16:06:26 -03002532DEFINE_RESORT_RB(syscall_stats, a->msecs > b->msecs,
2533 struct stats *stats;
2534 double msecs;
2535 int syscall;
2536)
2537{
2538 struct int_node *source = rb_entry(nd, struct int_node, rb_node);
2539 struct stats *stats = source->priv;
2540
2541 entry->syscall = source->i;
2542 entry->stats = stats;
2543 entry->msecs = stats ? (u64)stats->n * (avg_stats(stats) / NSEC_PER_MSEC) : 0;
2544}
2545
David Ahernbf2575c2013-10-08 21:26:53 -06002546static size_t thread__dump_stats(struct thread_trace *ttrace,
2547 struct trace *trace, FILE *fp)
2548{
David Ahernbf2575c2013-10-08 21:26:53 -06002549 size_t printed = 0;
2550 struct syscall *sc;
Arnaldo Carvalho de Melob535d522016-05-04 16:06:26 -03002551 struct rb_node *nd;
2552 DECLARE_RESORT_RB_INTLIST(syscall_stats, ttrace->syscall_stats);
David Ahernbf2575c2013-10-08 21:26:53 -06002553
Arnaldo Carvalho de Melob535d522016-05-04 16:06:26 -03002554 if (syscall_stats == NULL)
David Ahernbf2575c2013-10-08 21:26:53 -06002555 return 0;
2556
2557 printed += fprintf(fp, "\n");
2558
Milian Wolff834fd462015-08-06 11:24:29 +02002559 printed += fprintf(fp, " syscall calls total min avg max stddev\n");
2560 printed += fprintf(fp, " (msec) (msec) (msec) (msec) (%%)\n");
2561 printed += fprintf(fp, " --------------- -------- --------- --------- --------- --------- ------\n");
Pekka Enberg99ff7152013-11-12 16:42:14 +02002562
Arnaldo Carvalho de Melo98a91832016-06-23 11:34:10 -03002563 resort_rb__for_each_entry(nd, syscall_stats) {
Arnaldo Carvalho de Melob535d522016-05-04 16:06:26 -03002564 struct stats *stats = syscall_stats_entry->stats;
David Ahernbf2575c2013-10-08 21:26:53 -06002565 if (stats) {
2566 double min = (double)(stats->min) / NSEC_PER_MSEC;
2567 double max = (double)(stats->max) / NSEC_PER_MSEC;
2568 double avg = avg_stats(stats);
2569 double pct;
2570 u64 n = (u64) stats->n;
2571
2572 pct = avg ? 100.0 * stddev_stats(stats)/avg : 0.0;
2573 avg /= NSEC_PER_MSEC;
2574
Arnaldo Carvalho de Melob535d522016-05-04 16:06:26 -03002575 sc = &trace->syscalls.table[syscall_stats_entry->syscall];
Pekka Enberg99ff7152013-11-12 16:42:14 +02002576 printed += fprintf(fp, " %-15s", sc->name);
Milian Wolff834fd462015-08-06 11:24:29 +02002577 printed += fprintf(fp, " %8" PRIu64 " %9.3f %9.3f %9.3f",
Arnaldo Carvalho de Melob535d522016-05-04 16:06:26 -03002578 n, syscall_stats_entry->msecs, min, avg);
Pekka Enberg27a778b2013-11-13 14:21:48 +02002579 printed += fprintf(fp, " %9.3f %9.2f%%\n", max, pct);
David Ahernbf2575c2013-10-08 21:26:53 -06002580 }
David Ahernbf2575c2013-10-08 21:26:53 -06002581 }
2582
Arnaldo Carvalho de Melob535d522016-05-04 16:06:26 -03002583 resort_rb__delete(syscall_stats);
David Ahernbf2575c2013-10-08 21:26:53 -06002584 printed += fprintf(fp, "\n\n");
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002585
2586 return printed;
2587}
2588
Arnaldo Carvalho de Melo96c14452016-05-04 12:47:16 -03002589static size_t trace__fprintf_thread(FILE *fp, struct thread *thread, struct trace *trace)
David Ahern896cbb52013-09-28 13:12:59 -06002590{
Arnaldo Carvalho de Melo96c14452016-05-04 12:47:16 -03002591 size_t printed = 0;
Namhyung Kim89dceb22014-10-06 09:46:03 +09002592 struct thread_trace *ttrace = thread__priv(thread);
David Ahern896cbb52013-09-28 13:12:59 -06002593 double ratio;
2594
2595 if (ttrace == NULL)
2596 return 0;
2597
2598 ratio = (double)ttrace->nr_events / trace->nr_events * 100.0;
2599
Pekka Enberg15e65c62013-11-14 18:43:30 +02002600 printed += fprintf(fp, " %s (%d), ", thread__comm_str(thread), thread->tid);
Pekka Enberg99ff7152013-11-12 16:42:14 +02002601 printed += fprintf(fp, "%lu events, ", ttrace->nr_events);
Pekka Enberg15e65c62013-11-14 18:43:30 +02002602 printed += fprintf(fp, "%.1f%%", ratio);
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04002603 if (ttrace->pfmaj)
2604 printed += fprintf(fp, ", %lu majfaults", ttrace->pfmaj);
2605 if (ttrace->pfmin)
2606 printed += fprintf(fp, ", %lu minfaults", ttrace->pfmin);
Arnaldo Carvalho de Melo03548eb2016-05-05 15:46:50 -03002607 if (trace->sched)
2608 printed += fprintf(fp, ", %.3f msec\n", ttrace->runtime_ms);
2609 else if (fputc('\n', fp) != EOF)
2610 ++printed;
2611
David Ahernbf2575c2013-10-08 21:26:53 -06002612 printed += thread__dump_stats(ttrace, trace, fp);
David Ahern896cbb52013-09-28 13:12:59 -06002613
Arnaldo Carvalho de Melo96c14452016-05-04 12:47:16 -03002614 return printed;
2615}
David Ahern896cbb52013-09-28 13:12:59 -06002616
Arnaldo Carvalho de Melo96c14452016-05-04 12:47:16 -03002617static unsigned long thread__nr_events(struct thread_trace *ttrace)
2618{
2619 return ttrace ? ttrace->nr_events : 0;
2620}
2621
2622DEFINE_RESORT_RB(threads, (thread__nr_events(a->thread->priv) < thread__nr_events(b->thread->priv)),
2623 struct thread *thread;
2624)
2625{
2626 entry->thread = rb_entry(nd, struct thread, rb_node);
David Ahern896cbb52013-09-28 13:12:59 -06002627}
2628
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002629static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp)
2630{
Arnaldo Carvalho de Melo96c14452016-05-04 12:47:16 -03002631 DECLARE_RESORT_RB_MACHINE_THREADS(threads, trace->host);
2632 size_t printed = trace__fprintf_threads_header(fp);
2633 struct rb_node *nd;
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002634
Arnaldo Carvalho de Melo96c14452016-05-04 12:47:16 -03002635 if (threads == NULL) {
2636 fprintf(fp, "%s", "Error sorting output by nr_events!\n");
2637 return 0;
2638 }
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002639
Arnaldo Carvalho de Melo98a91832016-06-23 11:34:10 -03002640 resort_rb__for_each_entry(nd, threads)
Arnaldo Carvalho de Melo96c14452016-05-04 12:47:16 -03002641 printed += trace__fprintf_thread(fp, threads_entry->thread, trace);
2642
2643 resort_rb__delete(threads);
2644
2645 return printed;
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002646}
2647
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03002648static int trace__set_duration(const struct option *opt, const char *str,
2649 int unset __maybe_unused)
2650{
2651 struct trace *trace = opt->value;
2652
2653 trace->duration_filter = atof(str);
2654 return 0;
2655}
2656
Arnaldo Carvalho de Melof078c382015-02-21 11:36:52 -08002657static int trace__set_filter_pids(const struct option *opt, const char *str,
2658 int unset __maybe_unused)
2659{
2660 int ret = -1;
2661 size_t i;
2662 struct trace *trace = opt->value;
2663 /*
2664 * FIXME: introduce a intarray class, plain parse csv and create a
2665 * { int nr, int entries[] } struct...
2666 */
2667 struct intlist *list = intlist__new(str);
2668
2669 if (list == NULL)
2670 return -1;
2671
2672 i = trace->filter_pids.nr = intlist__nr_entries(list) + 1;
2673 trace->filter_pids.entries = calloc(i, sizeof(pid_t));
2674
2675 if (trace->filter_pids.entries == NULL)
2676 goto out;
2677
2678 trace->filter_pids.entries[0] = getpid();
2679
2680 for (i = 1; i < trace->filter_pids.nr; ++i)
2681 trace->filter_pids.entries[i] = intlist__entry(list, i - 1)->i;
2682
2683 intlist__delete(list);
2684 ret = 0;
2685out:
2686 return ret;
2687}
2688
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002689static int trace__open_output(struct trace *trace, const char *filename)
2690{
2691 struct stat st;
2692
2693 if (!stat(filename, &st) && st.st_size) {
2694 char oldname[PATH_MAX];
2695
2696 scnprintf(oldname, sizeof(oldname), "%s.old", filename);
2697 unlink(oldname);
2698 rename(filename, oldname);
2699 }
2700
2701 trace->output = fopen(filename, "w");
2702
2703 return trace->output == NULL ? -errno : 0;
2704}
2705
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002706static int parse_pagefaults(const struct option *opt, const char *str,
2707 int unset __maybe_unused)
2708{
2709 int *trace_pgfaults = opt->value;
2710
2711 if (strcmp(str, "all") == 0)
2712 *trace_pgfaults |= TRACE_PFMAJ | TRACE_PFMIN;
2713 else if (strcmp(str, "maj") == 0)
2714 *trace_pgfaults |= TRACE_PFMAJ;
2715 else if (strcmp(str, "min") == 0)
2716 *trace_pgfaults |= TRACE_PFMIN;
2717 else
2718 return -1;
2719
2720 return 0;
2721}
2722
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002723static void evlist__set_evsel_handler(struct perf_evlist *evlist, void *handler)
2724{
2725 struct perf_evsel *evsel;
2726
Arnaldo Carvalho de Meloe5cadb92016-06-23 11:26:15 -03002727 evlist__for_each_entry(evlist, evsel)
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002728 evsel->handler = handler;
2729}
2730
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002731int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
2732{
Yunlong Song6fdd9cb2015-03-18 21:35:57 +08002733 const char *trace_usage[] = {
Namhyung Kimf15eb532012-10-05 14:02:16 +09002734 "perf trace [<options>] [<command>]",
2735 "perf trace [<options>] -- <command> [<options>]",
David Ahern5e2485b2013-09-28 13:13:01 -06002736 "perf trace record [<options>] [<command>]",
2737 "perf trace record [<options>] -- <command> [<options>]",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002738 NULL
2739 };
2740 struct trace trace = {
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002741 .syscalls = {
2742 . max = -1,
2743 },
2744 .opts = {
2745 .target = {
2746 .uid = UINT_MAX,
2747 .uses_mmap = true,
2748 },
2749 .user_freq = UINT_MAX,
2750 .user_interval = ULLONG_MAX,
Arnaldo Carvalho de Melo509051e2014-01-14 17:52:14 -03002751 .no_buffering = true,
Arnaldo Carvalho de Melo38d54472014-12-12 17:28:32 -03002752 .mmap_pages = UINT_MAX,
Kan Liang9d9cad72015-06-17 09:51:11 -04002753 .proc_map_timeout = 500,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002754 },
Milian Wolff007d66a2015-08-05 16:52:23 -03002755 .output = stderr,
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -03002756 .show_comm = true,
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002757 .trace_syscalls = true,
Arnaldo Carvalho de Melo44621812016-04-11 15:49:11 -03002758 .kernel_syscallchains = false,
Arnaldo Carvalho de Melo05614992016-04-15 16:41:19 -03002759 .max_stack = UINT_MAX,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002760 };
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002761 const char *output_name = NULL;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03002762 const char *ev_qualifier_str = NULL;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002763 const struct option trace_options[] = {
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002764 OPT_CALLBACK(0, "event", &trace.evlist, "event",
2765 "event selector. use 'perf list' to list available events",
2766 parse_events_option),
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -03002767 OPT_BOOLEAN(0, "comm", &trace.show_comm,
2768 "show the thread COMM next to its id"),
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002769 OPT_BOOLEAN(0, "tool_stats", &trace.show_tool_stats, "show tool stats"),
Arnaldo Carvalho de Melod303e852015-04-23 12:02:07 -03002770 OPT_STRING('e', "expr", &ev_qualifier_str, "expr", "list of syscalls to trace"),
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002771 OPT_STRING('o', "output", &output_name, "file", "output file name"),
David Ahern6810fc92013-08-28 22:29:52 -06002772 OPT_STRING('i', "input", &input_name, "file", "Analyze events in file"),
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002773 OPT_STRING('p', "pid", &trace.opts.target.pid, "pid",
2774 "trace events on existing process id"),
David Ahernac9be8e2013-08-20 11:15:45 -06002775 OPT_STRING('t', "tid", &trace.opts.target.tid, "tid",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002776 "trace events on existing thread id"),
Arnaldo Carvalho de Melofa0e4ff2015-04-23 11:59:20 -03002777 OPT_CALLBACK(0, "filter-pids", &trace, "CSV list of pids",
2778 "pids to filter (by the kernel)", trace__set_filter_pids),
David Ahernac9be8e2013-08-20 11:15:45 -06002779 OPT_BOOLEAN('a', "all-cpus", &trace.opts.target.system_wide,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002780 "system-wide collection from all CPUs"),
David Ahernac9be8e2013-08-20 11:15:45 -06002781 OPT_STRING('C', "cpu", &trace.opts.target.cpu_list, "cpu",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002782 "list of cpus to monitor"),
David Ahern6810fc92013-08-28 22:29:52 -06002783 OPT_BOOLEAN(0, "no-inherit", &trace.opts.no_inherit,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002784 "child tasks do not inherit counters"),
Jiri Olsa994a1f72013-09-01 12:36:12 +02002785 OPT_CALLBACK('m', "mmap-pages", &trace.opts.mmap_pages, "pages",
2786 "number of mmap data pages",
2787 perf_evlist__parse_mmap_pages),
David Ahernac9be8e2013-08-20 11:15:45 -06002788 OPT_STRING('u', "uid", &trace.opts.target.uid_str, "user",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002789 "user to profile"),
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03002790 OPT_CALLBACK(0, "duration", &trace, "float",
2791 "show only events with duration > N.M ms",
2792 trace__set_duration),
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002793 OPT_BOOLEAN(0, "sched", &trace.sched, "show blocking scheduler events"),
Arnaldo Carvalho de Melo7c304ee02013-08-22 16:49:54 -03002794 OPT_INCR('v', "verbose", &verbose, "be more verbose"),
David Ahern4bb09192013-09-04 12:37:43 -06002795 OPT_BOOLEAN('T', "time", &trace.full_time,
2796 "Show full timestamp, not time relative to first start"),
David Ahernfd2eaba2013-11-12 09:31:15 -07002797 OPT_BOOLEAN('s', "summary", &trace.summary_only,
2798 "Show only syscall summary with statistics"),
2799 OPT_BOOLEAN('S', "with-summary", &trace.summary,
2800 "Show all syscalls and summary with statistics"),
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002801 OPT_CALLBACK_DEFAULT('F', "pf", &trace.trace_pgfaults, "all|maj|min",
2802 "Trace pagefaults", parse_pagefaults, "maj"),
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002803 OPT_BOOLEAN(0, "syscalls", &trace.trace_syscalls, "Trace syscalls"),
Yunlong Songe366a6d2015-04-02 21:47:18 +08002804 OPT_BOOLEAN('f', "force", &trace.force, "don't complain, do it"),
Milian Wolff566a0882016-04-08 13:34:15 +02002805 OPT_CALLBACK(0, "call-graph", &trace.opts,
2806 "record_mode[,record_size]", record_callchain_help,
2807 &record_parse_callchain_opt),
Arnaldo Carvalho de Melo44621812016-04-11 15:49:11 -03002808 OPT_BOOLEAN(0, "kernel-syscall-graph", &trace.kernel_syscallchains,
2809 "Show the kernel callchains on the syscall exit path"),
Arnaldo Carvalho de Melo5cf9c842016-04-15 11:10:31 -03002810 OPT_UINTEGER(0, "min-stack", &trace.min_stack,
2811 "Set the minimum stack depth when parsing the callchain, "
2812 "anything below the specified depth will be ignored."),
Arnaldo Carvalho de Meloc6d4a492016-04-14 18:29:08 -03002813 OPT_UINTEGER(0, "max-stack", &trace.max_stack,
2814 "Set the maximum stack depth when parsing the callchain, "
2815 "anything beyond the specified depth will be ignored. "
Arnaldo Carvalho de Melo4cb93442016-04-27 10:16:24 -03002816 "Default: kernel.perf_event_max_stack or " __stringify(PERF_MAX_STACK_DEPTH)),
Kan Liang9d9cad72015-06-17 09:51:11 -04002817 OPT_UINTEGER(0, "proc-map-timeout", &trace.opts.proc_map_timeout,
2818 "per thread proc mmap processing timeout in ms"),
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002819 OPT_END()
2820 };
Arnaldo Carvalho de Meloccd62a82016-04-16 09:36:32 -03002821 bool __maybe_unused max_stack_user_set = true;
Arnaldo Carvalho de Melof3e459d2016-04-15 17:52:34 -03002822 bool mmap_pages_user_set = true;
Yunlong Song6fdd9cb2015-03-18 21:35:57 +08002823 const char * const trace_subcommands[] = { "record", NULL };
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002824 int err;
Namhyung Kim32caf0d2012-10-05 14:02:13 +09002825 char bf[BUFSIZ];
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002826
Arnaldo Carvalho de Melo4d08cb82015-02-24 15:35:55 -03002827 signal(SIGSEGV, sighandler_dump_stack);
2828 signal(SIGFPE, sighandler_dump_stack);
2829
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002830 trace.evlist = perf_evlist__new();
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03002831 trace.sctbl = syscalltbl__new();
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002832
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03002833 if (trace.evlist == NULL || trace.sctbl == NULL) {
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002834 pr_err("Not enough memory to run!\n");
He Kuangff8f6952015-05-11 12:28:36 +00002835 err = -ENOMEM;
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002836 goto out;
2837 }
2838
Yunlong Song6fdd9cb2015-03-18 21:35:57 +08002839 argc = parse_options_subcommand(argc, argv, trace_options, trace_subcommands,
2840 trace_usage, PARSE_OPT_STOP_AT_NON_OPTION);
David Ahernfd2eaba2013-11-12 09:31:15 -07002841
Wang Nand7888572016-04-08 15:07:24 +00002842 err = bpf__setup_stdout(trace.evlist);
2843 if (err) {
2844 bpf__strerror_setup_stdout(trace.evlist, err, bf, sizeof(bf));
2845 pr_err("ERROR: Setup BPF stdout failed: %s\n", bf);
2846 goto out;
2847 }
2848
Arnaldo Carvalho de Melo59247e32016-04-12 16:05:02 -03002849 err = -1;
2850
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002851 if (trace.trace_pgfaults) {
2852 trace.opts.sample_address = true;
2853 trace.opts.sample_time = true;
2854 }
2855
Arnaldo Carvalho de Melof3e459d2016-04-15 17:52:34 -03002856 if (trace.opts.mmap_pages == UINT_MAX)
2857 mmap_pages_user_set = false;
2858
Arnaldo Carvalho de Melo05614992016-04-15 16:41:19 -03002859 if (trace.max_stack == UINT_MAX) {
Arnaldo Carvalho de Melofe176082016-05-19 11:34:06 -03002860 trace.max_stack = input_name ? PERF_MAX_STACK_DEPTH : sysctl_perf_event_max_stack;
Arnaldo Carvalho de Melo05614992016-04-15 16:41:19 -03002861 max_stack_user_set = false;
2862 }
2863
2864#ifdef HAVE_DWARF_UNWIND_SUPPORT
Arnaldo Carvalho de Melocaa36ed2016-05-19 19:00:27 -03002865 if ((trace.min_stack || max_stack_user_set) && !callchain_param.enabled && trace.trace_syscalls)
Arnaldo Carvalho de Melo05614992016-04-15 16:41:19 -03002866 record_opts__parse_callchain(&trace.opts, &callchain_param, "dwarf", false);
2867#endif
2868
Arnaldo Carvalho de Melo2ddd5c02016-04-18 12:09:08 -03002869 if (callchain_param.enabled) {
Arnaldo Carvalho de Melof3e459d2016-04-15 17:52:34 -03002870 if (!mmap_pages_user_set && geteuid() == 0)
2871 trace.opts.mmap_pages = perf_event_mlock_kb_in_pages() * 4;
2872
Milian Wolff566a0882016-04-08 13:34:15 +02002873 symbol_conf.use_callchain = true;
Arnaldo Carvalho de Melof3e459d2016-04-15 17:52:34 -03002874 }
Milian Wolff566a0882016-04-08 13:34:15 +02002875
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002876 if (trace.evlist->nr_entries > 0)
2877 evlist__set_evsel_handler(trace.evlist, trace__event_handler);
2878
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002879 if ((argc >= 1) && (strcmp(argv[0], "record") == 0))
2880 return trace__record(&trace, argc-1, &argv[1]);
2881
2882 /* summary_only implies summary option, but don't overwrite summary if set */
2883 if (trace.summary_only)
2884 trace.summary = trace.summary_only;
2885
Arnaldo Carvalho de Melo726f3232015-02-06 10:16:45 +01002886 if (!trace.trace_syscalls && !trace.trace_pgfaults &&
2887 trace.evlist->nr_entries == 0 /* Was --events used? */) {
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002888 pr_err("Please specify something to trace.\n");
2889 return -1;
2890 }
2891
Arnaldo Carvalho de Melo59247e32016-04-12 16:05:02 -03002892 if (!trace.trace_syscalls && ev_qualifier_str) {
2893 pr_err("The -e option can't be used with --no-syscalls.\n");
2894 goto out;
2895 }
2896
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002897 if (output_name != NULL) {
2898 err = trace__open_output(&trace, output_name);
2899 if (err < 0) {
2900 perror("failed to create output file");
2901 goto out;
2902 }
2903 }
2904
Arnaldo Carvalho de Melofd0db102016-04-04 13:32:20 -03002905 trace.open_id = syscalltbl__id(trace.sctbl, "open");
2906
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03002907 if (ev_qualifier_str != NULL) {
Arnaldo Carvalho de Melob059efd2013-08-21 12:56:21 -03002908 const char *s = ev_qualifier_str;
Arnaldo Carvalho de Melo005438a2015-07-20 12:02:09 -03002909 struct strlist_config slist_config = {
2910 .dirname = system_path(STRACE_GROUPS_DIR),
2911 };
Arnaldo Carvalho de Melob059efd2013-08-21 12:56:21 -03002912
2913 trace.not_ev_qualifier = *s == '!';
2914 if (trace.not_ev_qualifier)
2915 ++s;
Arnaldo Carvalho de Melo005438a2015-07-20 12:02:09 -03002916 trace.ev_qualifier = strlist__new(s, &slist_config);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03002917 if (trace.ev_qualifier == NULL) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002918 fputs("Not enough memory to parse event qualifier",
2919 trace.output);
2920 err = -ENOMEM;
2921 goto out_close;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03002922 }
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03002923
2924 err = trace__validate_ev_qualifier(&trace);
2925 if (err)
2926 goto out_close;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03002927 }
2928
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03002929 err = target__validate(&trace.opts.target);
Namhyung Kim32caf0d2012-10-05 14:02:13 +09002930 if (err) {
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03002931 target__strerror(&trace.opts.target, err, bf, sizeof(bf));
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002932 fprintf(trace.output, "%s", bf);
2933 goto out_close;
Namhyung Kim32caf0d2012-10-05 14:02:13 +09002934 }
2935
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03002936 err = target__parse_uid(&trace.opts.target);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002937 if (err) {
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03002938 target__strerror(&trace.opts.target, err, bf, sizeof(bf));
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002939 fprintf(trace.output, "%s", bf);
2940 goto out_close;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002941 }
2942
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03002943 if (!argc && target__none(&trace.opts.target))
Namhyung Kimee761202012-10-05 14:02:14 +09002944 trace.opts.target.system_wide = true;
2945
David Ahern6810fc92013-08-28 22:29:52 -06002946 if (input_name)
2947 err = trace__replay(&trace);
2948 else
2949 err = trace__run(&trace, argc, argv);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002950
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002951out_close:
2952 if (output_name != NULL)
2953 fclose(trace.output);
2954out:
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002955 return err;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002956}