blob: 5c494a8c8942492bebc0a05c3798df848031e71f [file] [log] [blame]
Robert Richter4e319022013-06-11 17:29:18 +02001#include <traceevent/event-parse.h>
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002#include "builtin.h"
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03003#include "util/color.h"
Arnaldo Carvalho de Melo7c304ee02013-08-22 16:49:54 -03004#include "util/debug.h"
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03005#include "util/evlist.h"
Arnaldo Carvalho de Melo005438a2015-07-20 12:02:09 -03006#include "util/exec_cmd.h"
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03007#include "util/machine.h"
David Ahern6810fc92013-08-28 22:29:52 -06008#include "util/session.h"
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03009#include "util/thread.h"
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -030010#include "util/parse-options.h"
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -030011#include "util/strlist.h"
David Ahernbdc89662013-08-28 22:29:53 -060012#include "util/intlist.h"
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -030013#include "util/thread_map.h"
David Ahernbf2575c2013-10-08 21:26:53 -060014#include "util/stat.h"
Jiri Olsa97978b32013-12-03 14:09:24 +010015#include "trace-event.h"
David Ahern9aca7f12013-12-04 19:41:39 -070016#include "util/parse-events.h"
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -030017
18#include <libaudit.h>
19#include <stdlib.h>
Arnaldo Carvalho de Meloae685382013-08-20 17:44:42 -030020#include <sys/mman.h>
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -030021#include <linux/futex.h>
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -030022
Ingo Molnar456857b2013-09-12 15:29:00 +020023/* For older distros: */
24#ifndef MAP_STACK
25# define MAP_STACK 0x20000
26#endif
27
28#ifndef MADV_HWPOISON
29# define MADV_HWPOISON 100
30#endif
31
32#ifndef MADV_MERGEABLE
33# define MADV_MERGEABLE 12
34#endif
35
36#ifndef MADV_UNMERGEABLE
37# define MADV_UNMERGEABLE 13
38#endif
39
Ben Hutchings79d26a62014-02-06 01:00:35 +000040#ifndef EFD_SEMAPHORE
41# define EFD_SEMAPHORE 1
42#endif
43
Arnaldo Carvalho de Meloc188e7a2015-05-14 17:39:03 -030044#ifndef EFD_NONBLOCK
45# define EFD_NONBLOCK 00004000
46#endif
47
48#ifndef EFD_CLOEXEC
49# define EFD_CLOEXEC 02000000
50#endif
51
52#ifndef O_CLOEXEC
53# define O_CLOEXEC 02000000
54#endif
55
56#ifndef SOCK_DCCP
57# define SOCK_DCCP 6
58#endif
59
60#ifndef SOCK_CLOEXEC
61# define SOCK_CLOEXEC 02000000
62#endif
63
64#ifndef SOCK_NONBLOCK
65# define SOCK_NONBLOCK 00004000
66#endif
67
68#ifndef MSG_CMSG_CLOEXEC
69# define MSG_CMSG_CLOEXEC 0x40000000
70#endif
71
Arnaldo Carvalho de Meloa1c25522015-06-11 22:47:54 -030072#ifndef PERF_FLAG_FD_NO_GROUP
73# define PERF_FLAG_FD_NO_GROUP (1UL << 0)
74#endif
75
76#ifndef PERF_FLAG_FD_OUTPUT
77# define PERF_FLAG_FD_OUTPUT (1UL << 1)
78#endif
79
80#ifndef PERF_FLAG_PID_CGROUP
81# define PERF_FLAG_PID_CGROUP (1UL << 2) /* pid=cgroup id, per-cpu mode only */
82#endif
83
84#ifndef PERF_FLAG_FD_CLOEXEC
85# define PERF_FLAG_FD_CLOEXEC (1UL << 3) /* O_CLOEXEC */
86#endif
87
88
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -030089struct tp_field {
90 int offset;
91 union {
92 u64 (*integer)(struct tp_field *field, struct perf_sample *sample);
93 void *(*pointer)(struct tp_field *field, struct perf_sample *sample);
94 };
95};
96
97#define TP_UINT_FIELD(bits) \
98static u64 tp_field__u##bits(struct tp_field *field, struct perf_sample *sample) \
99{ \
David Ahern55d43bc2015-02-19 15:00:22 -0500100 u##bits value; \
101 memcpy(&value, sample->raw_data + field->offset, sizeof(value)); \
102 return value; \
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300103}
104
105TP_UINT_FIELD(8);
106TP_UINT_FIELD(16);
107TP_UINT_FIELD(32);
108TP_UINT_FIELD(64);
109
110#define TP_UINT_FIELD__SWAPPED(bits) \
111static u64 tp_field__swapped_u##bits(struct tp_field *field, struct perf_sample *sample) \
112{ \
David Ahern55d43bc2015-02-19 15:00:22 -0500113 u##bits value; \
114 memcpy(&value, sample->raw_data + field->offset, sizeof(value)); \
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300115 return bswap_##bits(value);\
116}
117
118TP_UINT_FIELD__SWAPPED(16);
119TP_UINT_FIELD__SWAPPED(32);
120TP_UINT_FIELD__SWAPPED(64);
121
122static int tp_field__init_uint(struct tp_field *field,
123 struct format_field *format_field,
124 bool needs_swap)
125{
126 field->offset = format_field->offset;
127
128 switch (format_field->size) {
129 case 1:
130 field->integer = tp_field__u8;
131 break;
132 case 2:
133 field->integer = needs_swap ? tp_field__swapped_u16 : tp_field__u16;
134 break;
135 case 4:
136 field->integer = needs_swap ? tp_field__swapped_u32 : tp_field__u32;
137 break;
138 case 8:
139 field->integer = needs_swap ? tp_field__swapped_u64 : tp_field__u64;
140 break;
141 default:
142 return -1;
143 }
144
145 return 0;
146}
147
148static void *tp_field__ptr(struct tp_field *field, struct perf_sample *sample)
149{
150 return sample->raw_data + field->offset;
151}
152
153static int tp_field__init_ptr(struct tp_field *field, struct format_field *format_field)
154{
155 field->offset = format_field->offset;
156 field->pointer = tp_field__ptr;
157 return 0;
158}
159
160struct syscall_tp {
161 struct tp_field id;
162 union {
163 struct tp_field args, ret;
164 };
165};
166
167static int perf_evsel__init_tp_uint_field(struct perf_evsel *evsel,
168 struct tp_field *field,
169 const char *name)
170{
171 struct format_field *format_field = perf_evsel__field(evsel, name);
172
173 if (format_field == NULL)
174 return -1;
175
176 return tp_field__init_uint(field, format_field, evsel->needs_swap);
177}
178
179#define perf_evsel__init_sc_tp_uint_field(evsel, name) \
180 ({ struct syscall_tp *sc = evsel->priv;\
181 perf_evsel__init_tp_uint_field(evsel, &sc->name, #name); })
182
183static int perf_evsel__init_tp_ptr_field(struct perf_evsel *evsel,
184 struct tp_field *field,
185 const char *name)
186{
187 struct format_field *format_field = perf_evsel__field(evsel, name);
188
189 if (format_field == NULL)
190 return -1;
191
192 return tp_field__init_ptr(field, format_field);
193}
194
195#define perf_evsel__init_sc_tp_ptr_field(evsel, name) \
196 ({ struct syscall_tp *sc = evsel->priv;\
197 perf_evsel__init_tp_ptr_field(evsel, &sc->name, #name); })
198
199static void perf_evsel__delete_priv(struct perf_evsel *evsel)
200{
Arnaldo Carvalho de Melo04662522013-12-26 17:41:15 -0300201 zfree(&evsel->priv);
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300202 perf_evsel__delete(evsel);
203}
204
Namhyung Kim96695d42013-11-12 08:51:45 -0300205static int perf_evsel__init_syscall_tp(struct perf_evsel *evsel, void *handler)
206{
207 evsel->priv = malloc(sizeof(struct syscall_tp));
208 if (evsel->priv != NULL) {
209 if (perf_evsel__init_sc_tp_uint_field(evsel, id))
210 goto out_delete;
211
212 evsel->handler = handler;
213 return 0;
214 }
215
216 return -ENOMEM;
217
218out_delete:
Arnaldo Carvalho de Melo04662522013-12-26 17:41:15 -0300219 zfree(&evsel->priv);
Namhyung Kim96695d42013-11-12 08:51:45 -0300220 return -ENOENT;
221}
222
Arnaldo Carvalho de Meloef503832013-11-07 16:41:19 -0300223static struct perf_evsel *perf_evsel__syscall_newtp(const char *direction, void *handler)
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300224{
Arnaldo Carvalho de Meloef503832013-11-07 16:41:19 -0300225 struct perf_evsel *evsel = perf_evsel__newtp("raw_syscalls", direction);
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300226
David Ahern9aca7f12013-12-04 19:41:39 -0700227 /* older kernel (e.g., RHEL6) use syscalls:{enter,exit} */
228 if (evsel == NULL)
229 evsel = perf_evsel__newtp("syscalls", direction);
230
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300231 if (evsel) {
Namhyung Kim96695d42013-11-12 08:51:45 -0300232 if (perf_evsel__init_syscall_tp(evsel, handler))
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300233 goto out_delete;
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -0300234 }
235
236 return evsel;
237
238out_delete:
239 perf_evsel__delete_priv(evsel);
240 return NULL;
241}
242
243#define perf_evsel__sc_tp_uint(evsel, name, sample) \
244 ({ struct syscall_tp *fields = evsel->priv; \
245 fields->name.integer(&fields->name, sample); })
246
247#define perf_evsel__sc_tp_ptr(evsel, name, sample) \
248 ({ struct syscall_tp *fields = evsel->priv; \
249 fields->name.pointer(&fields->name, sample); })
250
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300251struct syscall_arg {
252 unsigned long val;
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300253 struct thread *thread;
254 struct trace *trace;
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300255 void *parm;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300256 u8 idx;
257 u8 mask;
258};
259
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300260struct strarray {
Arnaldo Carvalho de Melo03e3adc2013-10-08 16:00:21 -0300261 int offset;
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300262 int nr_entries;
263 const char **entries;
264};
265
266#define DEFINE_STRARRAY(array) struct strarray strarray__##array = { \
267 .nr_entries = ARRAY_SIZE(array), \
268 .entries = array, \
269}
270
Arnaldo Carvalho de Melo03e3adc2013-10-08 16:00:21 -0300271#define DEFINE_STRARRAY_OFFSET(array, off) struct strarray strarray__##array = { \
272 .offset = off, \
273 .nr_entries = ARRAY_SIZE(array), \
274 .entries = array, \
275}
276
Arnaldo Carvalho de Melo975b7c22013-10-08 17:17:43 -0300277static size_t __syscall_arg__scnprintf_strarray(char *bf, size_t size,
278 const char *intfmt,
279 struct syscall_arg *arg)
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300280{
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300281 struct strarray *sa = arg->parm;
Arnaldo Carvalho de Melo03e3adc2013-10-08 16:00:21 -0300282 int idx = arg->val - sa->offset;
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300283
284 if (idx < 0 || idx >= sa->nr_entries)
Arnaldo Carvalho de Melo975b7c22013-10-08 17:17:43 -0300285 return scnprintf(bf, size, intfmt, arg->val);
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300286
287 return scnprintf(bf, size, "%s", sa->entries[idx]);
288}
289
Arnaldo Carvalho de Melo975b7c22013-10-08 17:17:43 -0300290static size_t syscall_arg__scnprintf_strarray(char *bf, size_t size,
291 struct syscall_arg *arg)
292{
293 return __syscall_arg__scnprintf_strarray(bf, size, "%d", arg);
294}
295
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300296#define SCA_STRARRAY syscall_arg__scnprintf_strarray
297
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -0300298#if defined(__i386__) || defined(__x86_64__)
299/*
300 * FIXME: Make this available to all arches as soon as the ioctl beautifier
301 * gets rewritten to support all arches.
302 */
Arnaldo Carvalho de Melo78645cf2013-10-08 17:43:20 -0300303static size_t syscall_arg__scnprintf_strhexarray(char *bf, size_t size,
304 struct syscall_arg *arg)
305{
306 return __syscall_arg__scnprintf_strarray(bf, size, "%#x", arg);
307}
308
309#define SCA_STRHEXARRAY syscall_arg__scnprintf_strhexarray
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -0300310#endif /* defined(__i386__) || defined(__x86_64__) */
Arnaldo Carvalho de Melo78645cf2013-10-08 17:43:20 -0300311
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300312static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
313 struct syscall_arg *arg);
314
315#define SCA_FD syscall_arg__scnprintf_fd
316
317static size_t syscall_arg__scnprintf_fd_at(char *bf, size_t size,
318 struct syscall_arg *arg)
319{
320 int fd = arg->val;
321
322 if (fd == AT_FDCWD)
323 return scnprintf(bf, size, "CWD");
324
325 return syscall_arg__scnprintf_fd(bf, size, arg);
326}
327
328#define SCA_FDAT syscall_arg__scnprintf_fd_at
329
330static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
331 struct syscall_arg *arg);
332
333#define SCA_CLOSE_FD syscall_arg__scnprintf_close_fd
334
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -0300335static size_t syscall_arg__scnprintf_hex(char *bf, size_t size,
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300336 struct syscall_arg *arg)
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -0300337{
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300338 return scnprintf(bf, size, "%#lx", arg->val);
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -0300339}
340
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -0300341#define SCA_HEX syscall_arg__scnprintf_hex
342
Arnaldo Carvalho de Meloa1c25522015-06-11 22:47:54 -0300343static size_t syscall_arg__scnprintf_int(char *bf, size_t size,
344 struct syscall_arg *arg)
345{
346 return scnprintf(bf, size, "%d", arg->val);
347}
348
349#define SCA_INT syscall_arg__scnprintf_int
350
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -0300351static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size,
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300352 struct syscall_arg *arg)
Arnaldo Carvalho de Meloae685382013-08-20 17:44:42 -0300353{
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300354 int printed = 0, prot = arg->val;
Arnaldo Carvalho de Meloae685382013-08-20 17:44:42 -0300355
356 if (prot == PROT_NONE)
357 return scnprintf(bf, size, "NONE");
358#define P_MMAP_PROT(n) \
359 if (prot & PROT_##n) { \
360 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
361 prot &= ~PROT_##n; \
362 }
363
364 P_MMAP_PROT(EXEC);
365 P_MMAP_PROT(READ);
366 P_MMAP_PROT(WRITE);
367#ifdef PROT_SEM
368 P_MMAP_PROT(SEM);
369#endif
370 P_MMAP_PROT(GROWSDOWN);
371 P_MMAP_PROT(GROWSUP);
372#undef P_MMAP_PROT
373
374 if (prot)
375 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", prot);
376
377 return printed;
378}
379
380#define SCA_MMAP_PROT syscall_arg__scnprintf_mmap_prot
381
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -0300382static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size,
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300383 struct syscall_arg *arg)
Arnaldo Carvalho de Melo941557e2013-08-23 10:48:33 -0300384{
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300385 int printed = 0, flags = arg->val;
Arnaldo Carvalho de Melo941557e2013-08-23 10:48:33 -0300386
387#define P_MMAP_FLAG(n) \
388 if (flags & MAP_##n) { \
389 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
390 flags &= ~MAP_##n; \
391 }
392
393 P_MMAP_FLAG(SHARED);
394 P_MMAP_FLAG(PRIVATE);
Kyle McMartin41817812013-09-05 10:29:47 -0400395#ifdef MAP_32BIT
Arnaldo Carvalho de Melo941557e2013-08-23 10:48:33 -0300396 P_MMAP_FLAG(32BIT);
Kyle McMartin41817812013-09-05 10:29:47 -0400397#endif
Arnaldo Carvalho de Melo941557e2013-08-23 10:48:33 -0300398 P_MMAP_FLAG(ANONYMOUS);
399 P_MMAP_FLAG(DENYWRITE);
400 P_MMAP_FLAG(EXECUTABLE);
401 P_MMAP_FLAG(FILE);
402 P_MMAP_FLAG(FIXED);
403 P_MMAP_FLAG(GROWSDOWN);
David Ahernf2935f32013-08-27 10:50:40 -0600404#ifdef MAP_HUGETLB
Arnaldo Carvalho de Melo941557e2013-08-23 10:48:33 -0300405 P_MMAP_FLAG(HUGETLB);
David Ahernf2935f32013-08-27 10:50:40 -0600406#endif
Arnaldo Carvalho de Melo941557e2013-08-23 10:48:33 -0300407 P_MMAP_FLAG(LOCKED);
408 P_MMAP_FLAG(NONBLOCK);
409 P_MMAP_FLAG(NORESERVE);
410 P_MMAP_FLAG(POPULATE);
411 P_MMAP_FLAG(STACK);
412#ifdef MAP_UNINITIALIZED
413 P_MMAP_FLAG(UNINITIALIZED);
414#endif
415#undef P_MMAP_FLAG
416
417 if (flags)
418 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
419
420 return printed;
421}
422
423#define SCA_MMAP_FLAGS syscall_arg__scnprintf_mmap_flags
424
Alex Snast86998dd2014-08-13 18:42:40 +0300425static size_t syscall_arg__scnprintf_mremap_flags(char *bf, size_t size,
426 struct syscall_arg *arg)
427{
428 int printed = 0, flags = arg->val;
429
430#define P_MREMAP_FLAG(n) \
431 if (flags & MREMAP_##n) { \
432 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
433 flags &= ~MREMAP_##n; \
434 }
435
436 P_MREMAP_FLAG(MAYMOVE);
437#ifdef MREMAP_FIXED
438 P_MREMAP_FLAG(FIXED);
439#endif
440#undef P_MREMAP_FLAG
441
442 if (flags)
443 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
444
445 return printed;
446}
447
448#define SCA_MREMAP_FLAGS syscall_arg__scnprintf_mremap_flags
449
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -0300450static size_t syscall_arg__scnprintf_madvise_behavior(char *bf, size_t size,
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300451 struct syscall_arg *arg)
Arnaldo Carvalho de Melo9e9716d2013-08-23 10:06:41 -0300452{
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300453 int behavior = arg->val;
Arnaldo Carvalho de Melo9e9716d2013-08-23 10:06:41 -0300454
455 switch (behavior) {
456#define P_MADV_BHV(n) case MADV_##n: return scnprintf(bf, size, #n)
457 P_MADV_BHV(NORMAL);
458 P_MADV_BHV(RANDOM);
459 P_MADV_BHV(SEQUENTIAL);
460 P_MADV_BHV(WILLNEED);
461 P_MADV_BHV(DONTNEED);
462 P_MADV_BHV(REMOVE);
463 P_MADV_BHV(DONTFORK);
464 P_MADV_BHV(DOFORK);
465 P_MADV_BHV(HWPOISON);
466#ifdef MADV_SOFT_OFFLINE
467 P_MADV_BHV(SOFT_OFFLINE);
468#endif
469 P_MADV_BHV(MERGEABLE);
470 P_MADV_BHV(UNMERGEABLE);
David Ahernf2935f32013-08-27 10:50:40 -0600471#ifdef MADV_HUGEPAGE
Arnaldo Carvalho de Melo9e9716d2013-08-23 10:06:41 -0300472 P_MADV_BHV(HUGEPAGE);
David Ahernf2935f32013-08-27 10:50:40 -0600473#endif
474#ifdef MADV_NOHUGEPAGE
Arnaldo Carvalho de Melo9e9716d2013-08-23 10:06:41 -0300475 P_MADV_BHV(NOHUGEPAGE);
David Ahernf2935f32013-08-27 10:50:40 -0600476#endif
Arnaldo Carvalho de Melo9e9716d2013-08-23 10:06:41 -0300477#ifdef MADV_DONTDUMP
478 P_MADV_BHV(DONTDUMP);
479#endif
480#ifdef MADV_DODUMP
481 P_MADV_BHV(DODUMP);
482#endif
483#undef P_MADV_PHV
484 default: break;
485 }
486
487 return scnprintf(bf, size, "%#x", behavior);
488}
489
490#define SCA_MADV_BHV syscall_arg__scnprintf_madvise_behavior
491
Arnaldo Carvalho de Melo5cea6ff2013-09-20 11:49:50 -0300492static size_t syscall_arg__scnprintf_flock(char *bf, size_t size,
493 struct syscall_arg *arg)
494{
495 int printed = 0, op = arg->val;
496
497 if (op == 0)
498 return scnprintf(bf, size, "NONE");
499#define P_CMD(cmd) \
500 if ((op & LOCK_##cmd) == LOCK_##cmd) { \
501 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #cmd); \
502 op &= ~LOCK_##cmd; \
503 }
504
505 P_CMD(SH);
506 P_CMD(EX);
507 P_CMD(NB);
508 P_CMD(UN);
509 P_CMD(MAND);
510 P_CMD(RW);
511 P_CMD(READ);
512 P_CMD(WRITE);
513#undef P_OP
514
515 if (op)
516 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", op);
517
518 return printed;
519}
520
521#define SCA_FLOCK syscall_arg__scnprintf_flock
522
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300523static size_t syscall_arg__scnprintf_futex_op(char *bf, size_t size, struct syscall_arg *arg)
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -0300524{
525 enum syscall_futex_args {
526 SCF_UADDR = (1 << 0),
527 SCF_OP = (1 << 1),
528 SCF_VAL = (1 << 2),
529 SCF_TIMEOUT = (1 << 3),
530 SCF_UADDR2 = (1 << 4),
531 SCF_VAL3 = (1 << 5),
532 };
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300533 int op = arg->val;
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -0300534 int cmd = op & FUTEX_CMD_MASK;
535 size_t printed = 0;
536
537 switch (cmd) {
538#define P_FUTEX_OP(n) case FUTEX_##n: printed = scnprintf(bf, size, #n);
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300539 P_FUTEX_OP(WAIT); arg->mask |= SCF_VAL3|SCF_UADDR2; break;
540 P_FUTEX_OP(WAKE); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
541 P_FUTEX_OP(FD); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
542 P_FUTEX_OP(REQUEUE); arg->mask |= SCF_VAL3|SCF_TIMEOUT; break;
543 P_FUTEX_OP(CMP_REQUEUE); arg->mask |= SCF_TIMEOUT; break;
544 P_FUTEX_OP(CMP_REQUEUE_PI); arg->mask |= SCF_TIMEOUT; break;
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -0300545 P_FUTEX_OP(WAKE_OP); break;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300546 P_FUTEX_OP(LOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
547 P_FUTEX_OP(UNLOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
548 P_FUTEX_OP(TRYLOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2; break;
549 P_FUTEX_OP(WAIT_BITSET); arg->mask |= SCF_UADDR2; break;
550 P_FUTEX_OP(WAKE_BITSET); arg->mask |= SCF_UADDR2; break;
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -0300551 P_FUTEX_OP(WAIT_REQUEUE_PI); break;
552 default: printed = scnprintf(bf, size, "%#x", cmd); break;
553 }
554
555 if (op & FUTEX_PRIVATE_FLAG)
556 printed += scnprintf(bf + printed, size - printed, "|PRIV");
557
558 if (op & FUTEX_CLOCK_REALTIME)
559 printed += scnprintf(bf + printed, size - printed, "|CLKRT");
560
561 return printed;
562}
563
Arnaldo Carvalho de Meloefe6b882013-09-03 16:15:12 -0300564#define SCA_FUTEX_OP syscall_arg__scnprintf_futex_op
565
Arnaldo Carvalho de Melo03e3adc2013-10-08 16:00:21 -0300566static const char *epoll_ctl_ops[] = { "ADD", "DEL", "MOD", };
567static DEFINE_STRARRAY_OFFSET(epoll_ctl_ops, 1);
Arnaldo Carvalho de Meloeac032c2013-09-20 11:27:32 -0300568
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300569static const char *itimers[] = { "REAL", "VIRTUAL", "PROF", };
570static DEFINE_STRARRAY(itimers);
571
Arnaldo Carvalho de Meloefe6b882013-09-03 16:15:12 -0300572static const char *whences[] = { "SET", "CUR", "END",
573#ifdef SEEK_DATA
574"DATA",
575#endif
576#ifdef SEEK_HOLE
577"HOLE",
578#endif
579};
580static DEFINE_STRARRAY(whences);
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -0300581
Arnaldo Carvalho de Melo80f587d2013-09-03 16:28:58 -0300582static const char *fcntl_cmds[] = {
583 "DUPFD", "GETFD", "SETFD", "GETFL", "SETFL", "GETLK", "SETLK",
584 "SETLKW", "SETOWN", "GETOWN", "SETSIG", "GETSIG", "F_GETLK64",
585 "F_SETLK64", "F_SETLKW64", "F_SETOWN_EX", "F_GETOWN_EX",
586 "F_GETOWNER_UIDS",
587};
588static DEFINE_STRARRAY(fcntl_cmds);
589
Arnaldo Carvalho de Meloc045bf02013-09-04 11:52:33 -0300590static const char *rlimit_resources[] = {
591 "CPU", "FSIZE", "DATA", "STACK", "CORE", "RSS", "NPROC", "NOFILE",
592 "MEMLOCK", "AS", "LOCKS", "SIGPENDING", "MSGQUEUE", "NICE", "RTPRIO",
593 "RTTIME",
594};
595static DEFINE_STRARRAY(rlimit_resources);
596
Arnaldo Carvalho de Meloeb5b1b12013-09-03 16:37:46 -0300597static const char *sighow[] = { "BLOCK", "UNBLOCK", "SETMASK", };
598static DEFINE_STRARRAY(sighow);
599
David Ahern4f8c1b72013-09-22 19:45:00 -0600600static const char *clockid[] = {
601 "REALTIME", "MONOTONIC", "PROCESS_CPUTIME_ID", "THREAD_CPUTIME_ID",
Arnaldo Carvalho de Melo28ebb872015-08-11 10:38:38 -0300602 "MONOTONIC_RAW", "REALTIME_COARSE", "MONOTONIC_COARSE", "BOOTTIME",
603 "REALTIME_ALARM", "BOOTTIME_ALARM", "SGI_CYCLE", "TAI"
David Ahern4f8c1b72013-09-22 19:45:00 -0600604};
605static DEFINE_STRARRAY(clockid);
606
Arnaldo Carvalho de Meloe10bce82013-09-04 10:27:41 -0300607static const char *socket_families[] = {
608 "UNSPEC", "LOCAL", "INET", "AX25", "IPX", "APPLETALK", "NETROM",
609 "BRIDGE", "ATMPVC", "X25", "INET6", "ROSE", "DECnet", "NETBEUI",
610 "SECURITY", "KEY", "NETLINK", "PACKET", "ASH", "ECONET", "ATMSVC",
611 "RDS", "SNA", "IRDA", "PPPOX", "WANPIPE", "LLC", "IB", "CAN", "TIPC",
612 "BLUETOOTH", "IUCV", "RXRPC", "ISDN", "PHONET", "IEEE802154", "CAIF",
613 "ALG", "NFC", "VSOCK",
614};
615static DEFINE_STRARRAY(socket_families);
616
Arnaldo Carvalho de Meloa28b24b2013-09-04 11:00:44 -0300617#ifndef SOCK_TYPE_MASK
618#define SOCK_TYPE_MASK 0xf
619#endif
620
621static size_t syscall_arg__scnprintf_socket_type(char *bf, size_t size,
622 struct syscall_arg *arg)
623{
624 size_t printed;
625 int type = arg->val,
626 flags = type & ~SOCK_TYPE_MASK;
627
628 type &= SOCK_TYPE_MASK;
629 /*
630 * Can't use a strarray, MIPS may override for ABI reasons.
631 */
632 switch (type) {
633#define P_SK_TYPE(n) case SOCK_##n: printed = scnprintf(bf, size, #n); break;
634 P_SK_TYPE(STREAM);
635 P_SK_TYPE(DGRAM);
636 P_SK_TYPE(RAW);
637 P_SK_TYPE(RDM);
638 P_SK_TYPE(SEQPACKET);
639 P_SK_TYPE(DCCP);
640 P_SK_TYPE(PACKET);
641#undef P_SK_TYPE
642 default:
643 printed = scnprintf(bf, size, "%#x", type);
644 }
645
646#define P_SK_FLAG(n) \
647 if (flags & SOCK_##n) { \
648 printed += scnprintf(bf + printed, size - printed, "|%s", #n); \
649 flags &= ~SOCK_##n; \
650 }
651
652 P_SK_FLAG(CLOEXEC);
653 P_SK_FLAG(NONBLOCK);
654#undef P_SK_FLAG
655
656 if (flags)
657 printed += scnprintf(bf + printed, size - printed, "|%#x", flags);
658
659 return printed;
660}
661
662#define SCA_SK_TYPE syscall_arg__scnprintf_socket_type
663
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -0300664#ifndef MSG_PROBE
665#define MSG_PROBE 0x10
666#endif
David Ahernb6e8f8f2013-09-22 19:44:56 -0600667#ifndef MSG_WAITFORONE
668#define MSG_WAITFORONE 0x10000
669#endif
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -0300670#ifndef MSG_SENDPAGE_NOTLAST
671#define MSG_SENDPAGE_NOTLAST 0x20000
672#endif
673#ifndef MSG_FASTOPEN
674#define MSG_FASTOPEN 0x20000000
675#endif
676
677static size_t syscall_arg__scnprintf_msg_flags(char *bf, size_t size,
678 struct syscall_arg *arg)
679{
680 int printed = 0, flags = arg->val;
681
682 if (flags == 0)
683 return scnprintf(bf, size, "NONE");
684#define P_MSG_FLAG(n) \
685 if (flags & MSG_##n) { \
686 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
687 flags &= ~MSG_##n; \
688 }
689
690 P_MSG_FLAG(OOB);
691 P_MSG_FLAG(PEEK);
692 P_MSG_FLAG(DONTROUTE);
693 P_MSG_FLAG(TRYHARD);
694 P_MSG_FLAG(CTRUNC);
695 P_MSG_FLAG(PROBE);
696 P_MSG_FLAG(TRUNC);
697 P_MSG_FLAG(DONTWAIT);
698 P_MSG_FLAG(EOR);
699 P_MSG_FLAG(WAITALL);
700 P_MSG_FLAG(FIN);
701 P_MSG_FLAG(SYN);
702 P_MSG_FLAG(CONFIRM);
703 P_MSG_FLAG(RST);
704 P_MSG_FLAG(ERRQUEUE);
705 P_MSG_FLAG(NOSIGNAL);
706 P_MSG_FLAG(MORE);
707 P_MSG_FLAG(WAITFORONE);
708 P_MSG_FLAG(SENDPAGE_NOTLAST);
709 P_MSG_FLAG(FASTOPEN);
710 P_MSG_FLAG(CMSG_CLOEXEC);
711#undef P_MSG_FLAG
712
713 if (flags)
714 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
715
716 return printed;
717}
718
719#define SCA_MSG_FLAGS syscall_arg__scnprintf_msg_flags
720
Arnaldo Carvalho de Melo51108992013-09-04 11:42:27 -0300721static size_t syscall_arg__scnprintf_access_mode(char *bf, size_t size,
722 struct syscall_arg *arg)
723{
724 size_t printed = 0;
725 int mode = arg->val;
726
727 if (mode == F_OK) /* 0 */
728 return scnprintf(bf, size, "F");
729#define P_MODE(n) \
730 if (mode & n##_OK) { \
731 printed += scnprintf(bf + printed, size - printed, "%s", #n); \
732 mode &= ~n##_OK; \
733 }
734
735 P_MODE(R);
736 P_MODE(W);
737 P_MODE(X);
738#undef P_MODE
739
740 if (mode)
741 printed += scnprintf(bf + printed, size - printed, "|%#x", mode);
742
743 return printed;
744}
745
746#define SCA_ACCMODE syscall_arg__scnprintf_access_mode
747
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -0300748static size_t syscall_arg__scnprintf_filename(char *bf, size_t size,
749 struct syscall_arg *arg);
750
751#define SCA_FILENAME syscall_arg__scnprintf_filename
752
Arnaldo Carvalho de Melobe65a892013-09-02 16:22:31 -0300753static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300754 struct syscall_arg *arg)
Arnaldo Carvalho de Melobe65a892013-09-02 16:22:31 -0300755{
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300756 int printed = 0, flags = arg->val;
Arnaldo Carvalho de Melobe65a892013-09-02 16:22:31 -0300757
758 if (!(flags & O_CREAT))
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300759 arg->mask |= 1 << (arg->idx + 1); /* Mask the mode parm */
Arnaldo Carvalho de Melobe65a892013-09-02 16:22:31 -0300760
761 if (flags == 0)
762 return scnprintf(bf, size, "RDONLY");
763#define P_FLAG(n) \
764 if (flags & O_##n) { \
765 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
766 flags &= ~O_##n; \
767 }
768
769 P_FLAG(APPEND);
770 P_FLAG(ASYNC);
771 P_FLAG(CLOEXEC);
772 P_FLAG(CREAT);
773 P_FLAG(DIRECT);
774 P_FLAG(DIRECTORY);
775 P_FLAG(EXCL);
776 P_FLAG(LARGEFILE);
777 P_FLAG(NOATIME);
778 P_FLAG(NOCTTY);
779#ifdef O_NONBLOCK
780 P_FLAG(NONBLOCK);
781#elif O_NDELAY
782 P_FLAG(NDELAY);
783#endif
784#ifdef O_PATH
785 P_FLAG(PATH);
786#endif
787 P_FLAG(RDWR);
788#ifdef O_DSYNC
789 if ((flags & O_SYNC) == O_SYNC)
790 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", "SYNC");
791 else {
792 P_FLAG(DSYNC);
793 }
794#else
795 P_FLAG(SYNC);
796#endif
797 P_FLAG(TRUNC);
798 P_FLAG(WRONLY);
799#undef P_FLAG
800
801 if (flags)
802 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
803
804 return printed;
805}
806
807#define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags
808
Arnaldo Carvalho de Meloa1c25522015-06-11 22:47:54 -0300809static size_t syscall_arg__scnprintf_perf_flags(char *bf, size_t size,
810 struct syscall_arg *arg)
811{
812 int printed = 0, flags = arg->val;
813
814 if (flags == 0)
815 return 0;
816
817#define P_FLAG(n) \
818 if (flags & PERF_FLAG_##n) { \
819 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
820 flags &= ~PERF_FLAG_##n; \
821 }
822
823 P_FLAG(FD_NO_GROUP);
824 P_FLAG(FD_OUTPUT);
825 P_FLAG(PID_CGROUP);
826 P_FLAG(FD_CLOEXEC);
827#undef P_FLAG
828
829 if (flags)
830 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
831
832 return printed;
833}
834
835#define SCA_PERF_FLAGS syscall_arg__scnprintf_perf_flags
836
Arnaldo Carvalho de Melo49af9e92013-09-12 12:18:56 -0300837static size_t syscall_arg__scnprintf_eventfd_flags(char *bf, size_t size,
838 struct syscall_arg *arg)
839{
840 int printed = 0, flags = arg->val;
841
842 if (flags == 0)
843 return scnprintf(bf, size, "NONE");
844#define P_FLAG(n) \
845 if (flags & EFD_##n) { \
846 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
847 flags &= ~EFD_##n; \
848 }
849
850 P_FLAG(SEMAPHORE);
851 P_FLAG(CLOEXEC);
852 P_FLAG(NONBLOCK);
853#undef P_FLAG
854
855 if (flags)
856 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
857
858 return printed;
859}
860
861#define SCA_EFD_FLAGS syscall_arg__scnprintf_eventfd_flags
862
Arnaldo Carvalho de Melo46cce192013-09-23 12:52:04 -0300863static size_t syscall_arg__scnprintf_pipe_flags(char *bf, size_t size,
864 struct syscall_arg *arg)
865{
866 int printed = 0, flags = arg->val;
867
868#define P_FLAG(n) \
869 if (flags & O_##n) { \
870 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
871 flags &= ~O_##n; \
872 }
873
874 P_FLAG(CLOEXEC);
875 P_FLAG(NONBLOCK);
876#undef P_FLAG
877
878 if (flags)
879 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
880
881 return printed;
882}
883
884#define SCA_PIPE_FLAGS syscall_arg__scnprintf_pipe_flags
885
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -0300886static size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscall_arg *arg)
887{
888 int sig = arg->val;
889
890 switch (sig) {
891#define P_SIGNUM(n) case SIG##n: return scnprintf(bf, size, #n)
892 P_SIGNUM(HUP);
893 P_SIGNUM(INT);
894 P_SIGNUM(QUIT);
895 P_SIGNUM(ILL);
896 P_SIGNUM(TRAP);
897 P_SIGNUM(ABRT);
898 P_SIGNUM(BUS);
899 P_SIGNUM(FPE);
900 P_SIGNUM(KILL);
901 P_SIGNUM(USR1);
902 P_SIGNUM(SEGV);
903 P_SIGNUM(USR2);
904 P_SIGNUM(PIPE);
905 P_SIGNUM(ALRM);
906 P_SIGNUM(TERM);
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -0300907 P_SIGNUM(CHLD);
908 P_SIGNUM(CONT);
909 P_SIGNUM(STOP);
910 P_SIGNUM(TSTP);
911 P_SIGNUM(TTIN);
912 P_SIGNUM(TTOU);
913 P_SIGNUM(URG);
914 P_SIGNUM(XCPU);
915 P_SIGNUM(XFSZ);
916 P_SIGNUM(VTALRM);
917 P_SIGNUM(PROF);
918 P_SIGNUM(WINCH);
919 P_SIGNUM(IO);
920 P_SIGNUM(PWR);
921 P_SIGNUM(SYS);
Ben Hutchings02c5bb42014-02-06 01:00:41 +0000922#ifdef SIGEMT
923 P_SIGNUM(EMT);
924#endif
925#ifdef SIGSTKFLT
926 P_SIGNUM(STKFLT);
927#endif
928#ifdef SIGSWI
929 P_SIGNUM(SWI);
930#endif
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -0300931 default: break;
932 }
933
934 return scnprintf(bf, size, "%#x", sig);
935}
936
937#define SCA_SIGNUM syscall_arg__scnprintf_signum
938
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -0300939#if defined(__i386__) || defined(__x86_64__)
940/*
941 * FIXME: Make this available to all arches.
942 */
Arnaldo Carvalho de Melo78645cf2013-10-08 17:43:20 -0300943#define TCGETS 0x5401
944
945static const char *tioctls[] = {
946 "TCGETS", "TCSETS", "TCSETSW", "TCSETSF", "TCGETA", "TCSETA", "TCSETAW",
947 "TCSETAF", "TCSBRK", "TCXONC", "TCFLSH", "TIOCEXCL", "TIOCNXCL",
948 "TIOCSCTTY", "TIOCGPGRP", "TIOCSPGRP", "TIOCOUTQ", "TIOCSTI",
949 "TIOCGWINSZ", "TIOCSWINSZ", "TIOCMGET", "TIOCMBIS", "TIOCMBIC",
950 "TIOCMSET", "TIOCGSOFTCAR", "TIOCSSOFTCAR", "FIONREAD", "TIOCLINUX",
951 "TIOCCONS", "TIOCGSERIAL", "TIOCSSERIAL", "TIOCPKT", "FIONBIO",
952 "TIOCNOTTY", "TIOCSETD", "TIOCGETD", "TCSBRKP", [0x27] = "TIOCSBRK",
953 "TIOCCBRK", "TIOCGSID", "TCGETS2", "TCSETS2", "TCSETSW2", "TCSETSF2",
954 "TIOCGRS485", "TIOCSRS485", "TIOCGPTN", "TIOCSPTLCK",
955 "TIOCGDEV||TCGETX", "TCSETX", "TCSETXF", "TCSETXW", "TIOCSIG",
956 "TIOCVHANGUP", "TIOCGPKT", "TIOCGPTLCK", "TIOCGEXCL",
957 [0x50] = "FIONCLEX", "FIOCLEX", "FIOASYNC", "TIOCSERCONFIG",
958 "TIOCSERGWILD", "TIOCSERSWILD", "TIOCGLCKTRMIOS", "TIOCSLCKTRMIOS",
959 "TIOCSERGSTRUCT", "TIOCSERGETLSR", "TIOCSERGETMULTI", "TIOCSERSETMULTI",
960 "TIOCMIWAIT", "TIOCGICOUNT", [0x60] = "FIOQSIZE",
961};
962
963static DEFINE_STRARRAY_OFFSET(tioctls, 0x5401);
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -0300964#endif /* defined(__i386__) || defined(__x86_64__) */
Arnaldo Carvalho de Melo78645cf2013-10-08 17:43:20 -0300965
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -0300966#define STRARRAY(arg, name, array) \
967 .arg_scnprintf = { [arg] = SCA_STRARRAY, }, \
968 .arg_parm = { [arg] = &strarray__##array, }
969
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300970static struct syscall_fmt {
971 const char *name;
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -0300972 const char *alias;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -0300973 size_t (*arg_scnprintf[6])(char *bf, size_t size, struct syscall_arg *arg);
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -0300974 void *arg_parm[6];
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300975 bool errmsg;
976 bool timeout;
Arnaldo Carvalho de Melo04b34722013-08-26 11:36:30 -0300977 bool hexret;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -0300978} syscall_fmts[] = {
Arnaldo Carvalho de Melo51108992013-09-04 11:42:27 -0300979 { .name = "access", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300980 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */
981 [1] = SCA_ACCMODE, /* mode */ }, },
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -0300982 { .name = "arch_prctl", .errmsg = true, .alias = "prctl", },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -0300983 { .name = "brk", .hexret = true,
984 .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300985 { .name = "chdir", .errmsg = true,
986 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
987 { .name = "chmod", .errmsg = true,
988 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
989 { .name = "chroot", .errmsg = true,
990 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
David Ahern4f8c1b72013-09-22 19:45:00 -0600991 { .name = "clock_gettime", .errmsg = true, STRARRAY(0, clk_id, clockid), },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300992 { .name = "close", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300993 .arg_scnprintf = { [0] = SCA_CLOSE_FD, /* fd */ }, },
Arnaldo Carvalho de Meloa14bb862013-07-30 16:38:23 -0300994 { .name = "connect", .errmsg = true, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -0300995 { .name = "creat", .errmsg = true,
996 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300997 { .name = "dup", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300998 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -0300999 { .name = "dup2", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001000 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001001 { .name = "dup3", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001002 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -03001003 { .name = "epoll_ctl", .errmsg = true, STRARRAY(1, op, epoll_ctl_ops), },
Arnaldo Carvalho de Melo49af9e92013-09-12 12:18:56 -03001004 { .name = "eventfd2", .errmsg = true,
1005 .arg_scnprintf = { [1] = SCA_EFD_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001006 { .name = "faccessat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001007 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
1008 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001009 { .name = "fadvise64", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001010 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001011 { .name = "fallocate", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001012 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001013 { .name = "fchdir", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001014 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001015 { .name = "fchmod", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001016 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001017 { .name = "fchmodat", .errmsg = true,
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -03001018 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */
1019 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001020 { .name = "fchown", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001021 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001022 { .name = "fchownat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001023 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */
1024 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001025 { .name = "fcntl", .errmsg = true,
1026 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1027 [1] = SCA_STRARRAY, /* cmd */ },
1028 .arg_parm = { [1] = &strarray__fcntl_cmds, /* cmd */ }, },
1029 { .name = "fdatasync", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001030 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo5cea6ff2013-09-20 11:49:50 -03001031 { .name = "flock", .errmsg = true,
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001032 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1033 [1] = SCA_FLOCK, /* cmd */ }, },
1034 { .name = "fsetxattr", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001035 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001036 { .name = "fstat", .errmsg = true, .alias = "newfstat",
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001037 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001038 { .name = "fstatat", .errmsg = true, .alias = "newfstatat",
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001039 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
1040 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001041 { .name = "fstatfs", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001042 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001043 { .name = "fsync", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001044 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001045 { .name = "ftruncate", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001046 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melof9da0b02013-09-02 13:46:44 -03001047 { .name = "futex", .errmsg = true,
1048 .arg_scnprintf = { [1] = SCA_FUTEX_OP, /* op */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001049 { .name = "futimesat", .errmsg = true,
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -03001050 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */
1051 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001052 { .name = "getdents", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001053 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001054 { .name = "getdents64", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001055 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -03001056 { .name = "getitimer", .errmsg = true, STRARRAY(0, which, itimers), },
1057 { .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001058 { .name = "getxattr", .errmsg = true,
1059 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
1060 { .name = "inotify_add_watch", .errmsg = true,
1061 .arg_scnprintf = { [1] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -03001062 { .name = "ioctl", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001063 .arg_scnprintf = { [0] = SCA_FD, /* fd */
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -03001064#if defined(__i386__) || defined(__x86_64__)
1065/*
1066 * FIXME: Make this available to all arches.
1067 */
Arnaldo Carvalho de Melo78645cf2013-10-08 17:43:20 -03001068 [1] = SCA_STRHEXARRAY, /* cmd */
1069 [2] = SCA_HEX, /* arg */ },
1070 .arg_parm = { [1] = &strarray__tioctls, /* cmd */ }, },
Arnaldo Carvalho de Melo844ae5b2014-02-10 14:09:48 -03001071#else
1072 [2] = SCA_HEX, /* arg */ }, },
1073#endif
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -03001074 { .name = "kill", .errmsg = true,
1075 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001076 { .name = "lchown", .errmsg = true,
1077 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
1078 { .name = "lgetxattr", .errmsg = true,
1079 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001080 { .name = "linkat", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001081 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001082 { .name = "listxattr", .errmsg = true,
1083 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -03001084 { .name = "llistxattr", .errmsg = true,
1085 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
1086 { .name = "lremovexattr", .errmsg = true,
1087 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001088 { .name = "lseek", .errmsg = true,
1089 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1090 [2] = SCA_STRARRAY, /* whence */ },
1091 .arg_parm = { [2] = &strarray__whences, /* whence */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001092 { .name = "lsetxattr", .errmsg = true,
1093 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -03001094 { .name = "lstat", .errmsg = true, .alias = "newlstat",
1095 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001096 { .name = "lsxattr", .errmsg = true,
1097 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo9e9716d2013-08-23 10:06:41 -03001098 { .name = "madvise", .errmsg = true,
1099 .arg_scnprintf = { [0] = SCA_HEX, /* start */
1100 [2] = SCA_MADV_BHV, /* behavior */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001101 { .name = "mkdir", .errmsg = true,
1102 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001103 { .name = "mkdirat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001104 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */
1105 [1] = SCA_FILENAME, /* pathname */ }, },
1106 { .name = "mknod", .errmsg = true,
1107 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001108 { .name = "mknodat", .errmsg = true,
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -03001109 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */
1110 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo3d903aa2013-09-24 00:09:38 -03001111 { .name = "mlock", .errmsg = true,
1112 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
1113 { .name = "mlockall", .errmsg = true,
1114 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -03001115 { .name = "mmap", .hexret = true,
Arnaldo Carvalho de Meloae685382013-08-20 17:44:42 -03001116 .arg_scnprintf = { [0] = SCA_HEX, /* addr */
Arnaldo Carvalho de Melo941557e2013-08-23 10:48:33 -03001117 [2] = SCA_MMAP_PROT, /* prot */
Namhyung Kim73faab32013-11-12 15:24:59 +09001118 [3] = SCA_MMAP_FLAGS, /* flags */
1119 [4] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -03001120 { .name = "mprotect", .errmsg = true,
Arnaldo Carvalho de Meloae685382013-08-20 17:44:42 -03001121 .arg_scnprintf = { [0] = SCA_HEX, /* start */
1122 [2] = SCA_MMAP_PROT, /* prot */ }, },
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -03001123 { .name = "mq_unlink", .errmsg = true,
1124 .arg_scnprintf = { [0] = SCA_FILENAME, /* u_name */ }, },
Arnaldo Carvalho de Meloae685382013-08-20 17:44:42 -03001125 { .name = "mremap", .hexret = true,
1126 .arg_scnprintf = { [0] = SCA_HEX, /* addr */
Alex Snast86998dd2014-08-13 18:42:40 +03001127 [3] = SCA_MREMAP_FLAGS, /* flags */
Arnaldo Carvalho de Meloae685382013-08-20 17:44:42 -03001128 [4] = SCA_HEX, /* new_addr */ }, },
Arnaldo Carvalho de Melo3d903aa2013-09-24 00:09:38 -03001129 { .name = "munlock", .errmsg = true,
1130 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -03001131 { .name = "munmap", .errmsg = true,
1132 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001133 { .name = "name_to_handle_at", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001134 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001135 { .name = "newfstatat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001136 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
1137 [1] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melobe65a892013-09-02 16:22:31 -03001138 { .name = "open", .errmsg = true,
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001139 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */
1140 [1] = SCA_OPEN_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo31cd3852013-09-02 16:40:40 -03001141 { .name = "open_by_handle_at", .errmsg = true,
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001142 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
1143 [2] = SCA_OPEN_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo31cd3852013-09-02 16:40:40 -03001144 { .name = "openat", .errmsg = true,
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001145 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001146 [1] = SCA_FILENAME, /* filename */
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001147 [2] = SCA_OPEN_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Meloa1c25522015-06-11 22:47:54 -03001148 { .name = "perf_event_open", .errmsg = true,
1149 .arg_scnprintf = { [1] = SCA_INT, /* pid */
1150 [2] = SCA_INT, /* cpu */
1151 [3] = SCA_FD, /* group_fd */
1152 [4] = SCA_PERF_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo46cce192013-09-23 12:52:04 -03001153 { .name = "pipe2", .errmsg = true,
1154 .arg_scnprintf = { [1] = SCA_PIPE_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -03001155 { .name = "poll", .errmsg = true, .timeout = true, },
1156 { .name = "ppoll", .errmsg = true, .timeout = true, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001157 { .name = "pread", .errmsg = true, .alias = "pread64",
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001158 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001159 { .name = "preadv", .errmsg = true, .alias = "pread",
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001160 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -03001161 { .name = "prlimit64", .errmsg = true, STRARRAY(1, resource, rlimit_resources), },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001162 { .name = "pwrite", .errmsg = true, .alias = "pwrite64",
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001163 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001164 { .name = "pwritev", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001165 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001166 { .name = "read", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001167 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001168 { .name = "readlink", .errmsg = true,
1169 .arg_scnprintf = { [0] = SCA_FILENAME, /* path */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001170 { .name = "readlinkat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001171 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
1172 [1] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001173 { .name = "readv", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001174 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -03001175 { .name = "recvfrom", .errmsg = true,
1176 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
1177 { .name = "recvmmsg", .errmsg = true,
1178 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
1179 { .name = "recvmsg", .errmsg = true,
1180 .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001181 { .name = "removexattr", .errmsg = true,
1182 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001183 { .name = "renameat", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001184 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001185 { .name = "rmdir", .errmsg = true,
1186 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -03001187 { .name = "rt_sigaction", .errmsg = true,
1188 .arg_scnprintf = { [0] = SCA_SIGNUM, /* sig */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -03001189 { .name = "rt_sigprocmask", .errmsg = true, STRARRAY(0, how, sighow), },
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -03001190 { .name = "rt_sigqueueinfo", .errmsg = true,
1191 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
1192 { .name = "rt_tgsigqueueinfo", .errmsg = true,
1193 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -03001194 { .name = "select", .errmsg = true, .timeout = true, },
Arnaldo Carvalho de Melob2cc99fd2013-09-12 11:54:48 -03001195 { .name = "sendmmsg", .errmsg = true,
1196 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
1197 { .name = "sendmsg", .errmsg = true,
1198 .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, },
1199 { .name = "sendto", .errmsg = true,
1200 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
Arnaldo Carvalho de Melo453350d2013-09-20 12:13:37 -03001201 { .name = "setitimer", .errmsg = true, STRARRAY(0, which, itimers), },
1202 { .name = "setrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001203 { .name = "setxattr", .errmsg = true,
1204 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001205 { .name = "shutdown", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001206 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Meloe10bce82013-09-04 10:27:41 -03001207 { .name = "socket", .errmsg = true,
Arnaldo Carvalho de Meloa28b24b2013-09-04 11:00:44 -03001208 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
1209 [1] = SCA_SK_TYPE, /* type */ },
Arnaldo Carvalho de Meloe10bce82013-09-04 10:27:41 -03001210 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, },
Arnaldo Carvalho de Melo07120aa2013-09-20 12:24:20 -03001211 { .name = "socketpair", .errmsg = true,
1212 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
1213 [1] = SCA_SK_TYPE, /* type */ },
1214 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, },
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -03001215 { .name = "stat", .errmsg = true, .alias = "newstat",
1216 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001217 { .name = "statfs", .errmsg = true,
1218 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
1219 { .name = "swapoff", .errmsg = true,
1220 .arg_scnprintf = { [0] = SCA_FILENAME, /* specialfile */ }, },
1221 { .name = "swapon", .errmsg = true,
1222 .arg_scnprintf = { [0] = SCA_FILENAME, /* specialfile */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001223 { .name = "symlinkat", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001224 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
Arnaldo Carvalho de Melo8bad5b02013-09-03 17:17:15 -03001225 { .name = "tgkill", .errmsg = true,
1226 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
1227 { .name = "tkill", .errmsg = true,
1228 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001229 { .name = "truncate", .errmsg = true,
1230 .arg_scnprintf = { [0] = SCA_FILENAME, /* path */ }, },
Arnaldo Carvalho de Meloe5959682013-08-26 12:21:41 -03001231 { .name = "uname", .errmsg = true, .alias = "newuname", },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001232 { .name = "unlinkat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001233 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
1234 [1] = SCA_FILENAME, /* pathname */ }, },
1235 { .name = "utime", .errmsg = true,
1236 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001237 { .name = "utimensat", .errmsg = true,
Arnaldo Carvalho de Melo34221112015-08-04 23:31:25 -03001238 .arg_scnprintf = { [0] = SCA_FDAT, /* dirfd */
1239 [1] = SCA_FILENAME, /* filename */ }, },
1240 { .name = "utimes", .errmsg = true,
1241 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
Arnaldo Carvalho de Melo090389b62015-08-10 19:20:52 -03001242 { .name = "vmsplice", .errmsg = true,
1243 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001244 { .name = "write", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001245 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001246 { .name = "writev", .errmsg = true,
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001247 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001248};
1249
1250static int syscall_fmt__cmp(const void *name, const void *fmtp)
1251{
1252 const struct syscall_fmt *fmt = fmtp;
1253 return strcmp(name, fmt->name);
1254}
1255
1256static struct syscall_fmt *syscall_fmt__find(const char *name)
1257{
1258 const int nmemb = ARRAY_SIZE(syscall_fmts);
1259 return bsearch(name, syscall_fmts, nmemb, sizeof(struct syscall_fmt), syscall_fmt__cmp);
1260}
1261
1262struct syscall {
1263 struct event_format *tp_format;
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001264 int nr_args;
1265 struct format_field *args;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001266 const char *name;
Arnaldo Carvalho de Melo5089f202014-06-17 14:29:24 -03001267 bool is_exit;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001268 struct syscall_fmt *fmt;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001269 size_t (**arg_scnprintf)(char *bf, size_t size, struct syscall_arg *arg);
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -03001270 void **arg_parm;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001271};
1272
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001273static size_t fprintf_duration(unsigned long t, FILE *fp)
1274{
1275 double duration = (double)t / NSEC_PER_MSEC;
1276 size_t printed = fprintf(fp, "(");
1277
1278 if (duration >= 1.0)
1279 printed += color_fprintf(fp, PERF_COLOR_RED, "%6.3f ms", duration);
1280 else if (duration >= 0.01)
1281 printed += color_fprintf(fp, PERF_COLOR_YELLOW, "%6.3f ms", duration);
1282 else
1283 printed += color_fprintf(fp, PERF_COLOR_NORMAL, "%6.3f ms", duration);
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001284 return printed + fprintf(fp, "): ");
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001285}
1286
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001287/**
1288 * filename.ptr: The filename char pointer that will be vfs_getname'd
1289 * filename.entry_str_pos: Where to insert the string translated from
1290 * filename.ptr by the vfs_getname tracepoint/kprobe.
1291 */
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001292struct thread_trace {
1293 u64 entry_time;
1294 u64 exit_time;
1295 bool entry_pending;
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03001296 unsigned long nr_events;
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04001297 unsigned long pfmaj, pfmin;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001298 char *entry_str;
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001299 double runtime_ms;
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001300 struct {
1301 unsigned long ptr;
1302 int entry_str_pos;
1303 } filename;
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001304 struct {
1305 int max;
1306 char **table;
1307 } paths;
David Ahernbf2575c2013-10-08 21:26:53 -06001308
1309 struct intlist *syscall_stats;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001310};
1311
1312static struct thread_trace *thread_trace__new(void)
1313{
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001314 struct thread_trace *ttrace = zalloc(sizeof(struct thread_trace));
1315
1316 if (ttrace)
1317 ttrace->paths.max = -1;
1318
David Ahernbf2575c2013-10-08 21:26:53 -06001319 ttrace->syscall_stats = intlist__new(NULL);
1320
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001321 return ttrace;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001322}
1323
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001324static struct thread_trace *thread__trace(struct thread *thread, FILE *fp)
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001325{
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03001326 struct thread_trace *ttrace;
1327
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001328 if (thread == NULL)
1329 goto fail;
1330
Namhyung Kim89dceb22014-10-06 09:46:03 +09001331 if (thread__priv(thread) == NULL)
1332 thread__set_priv(thread, thread_trace__new());
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -03001333
Namhyung Kim89dceb22014-10-06 09:46:03 +09001334 if (thread__priv(thread) == NULL)
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001335 goto fail;
1336
Namhyung Kim89dceb22014-10-06 09:46:03 +09001337 ttrace = thread__priv(thread);
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03001338 ++ttrace->nr_events;
1339
1340 return ttrace;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001341fail:
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001342 color_fprintf(fp, PERF_COLOR_RED,
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001343 "WARNING: not enough memory, dropping samples!\n");
1344 return NULL;
1345}
1346
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04001347#define TRACE_PFMAJ (1 << 0)
1348#define TRACE_PFMIN (1 << 1)
1349
Arnaldo Carvalho de Meloe4d44e82015-08-04 22:17:29 -03001350static const size_t trace__entry_str_size = 2048;
1351
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001352struct trace {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001353 struct perf_tool tool;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001354 struct {
1355 int machine;
1356 int open_id;
1357 } audit;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001358 struct {
1359 int max;
1360 struct syscall *table;
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03001361 struct {
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001362 struct perf_evsel *sys_enter,
1363 *sys_exit;
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03001364 } events;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001365 } syscalls;
Arnaldo Carvalho de Melob4006792013-12-19 14:43:45 -03001366 struct record_opts opts;
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03001367 struct perf_evlist *evlist;
David Ahern8fb598e2013-09-28 13:13:00 -06001368 struct machine *host;
Arnaldo Carvalho de Meloe5966632015-02-13 13:22:21 -03001369 struct thread *current;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001370 u64 base_time;
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001371 FILE *output;
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03001372 unsigned long nr_events;
Arnaldo Carvalho de Melob059efd2013-08-21 12:56:21 -03001373 struct strlist *ev_qualifier;
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001374 struct {
1375 size_t nr;
1376 int *entries;
1377 } ev_qualifier_ids;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001378 const char *last_vfs_getname;
David Ahernbdc89662013-08-28 22:29:53 -06001379 struct intlist *tid_list;
1380 struct intlist *pid_list;
Arnaldo Carvalho de Melof078c382015-02-21 11:36:52 -08001381 struct {
1382 size_t nr;
1383 pid_t *entries;
1384 } filter_pids;
Arnaldo Carvalho de Melo98eafce2014-01-06 15:43:02 -03001385 double duration_filter;
1386 double runtime_ms;
1387 struct {
1388 u64 vfs_getname,
1389 proc_getname;
1390 } stats;
1391 bool not_ev_qualifier;
1392 bool live;
1393 bool full_time;
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03001394 bool sched;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001395 bool multiple_threads;
David Ahernbf2575c2013-10-08 21:26:53 -06001396 bool summary;
David Ahernfd2eaba2013-11-12 09:31:15 -07001397 bool summary_only;
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -03001398 bool show_comm;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001399 bool show_tool_stats;
Stanislav Fomicheve281a962014-06-26 20:14:28 +04001400 bool trace_syscalls;
Yunlong Songe366a6d2015-04-02 21:47:18 +08001401 bool force;
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03001402 bool vfs_getname;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04001403 int trace_pgfaults;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001404};
1405
Arnaldo Carvalho de Melo97119f32013-09-27 17:34:10 -03001406static int trace__set_fd_pathname(struct thread *thread, int fd, const char *pathname)
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001407{
Namhyung Kim89dceb22014-10-06 09:46:03 +09001408 struct thread_trace *ttrace = thread__priv(thread);
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001409
1410 if (fd > ttrace->paths.max) {
1411 char **npath = realloc(ttrace->paths.table, (fd + 1) * sizeof(char *));
1412
1413 if (npath == NULL)
1414 return -1;
1415
1416 if (ttrace->paths.max != -1) {
1417 memset(npath + ttrace->paths.max + 1, 0,
1418 (fd - ttrace->paths.max) * sizeof(char *));
1419 } else {
1420 memset(npath, 0, (fd + 1) * sizeof(char *));
1421 }
1422
1423 ttrace->paths.table = npath;
1424 ttrace->paths.max = fd;
1425 }
1426
1427 ttrace->paths.table[fd] = strdup(pathname);
1428
1429 return ttrace->paths.table[fd] != NULL ? 0 : -1;
1430}
1431
Arnaldo Carvalho de Melo97119f32013-09-27 17:34:10 -03001432static int thread__read_fd_path(struct thread *thread, int fd)
1433{
1434 char linkname[PATH_MAX], pathname[PATH_MAX];
1435 struct stat st;
1436 int ret;
1437
1438 if (thread->pid_ == thread->tid) {
1439 scnprintf(linkname, sizeof(linkname),
1440 "/proc/%d/fd/%d", thread->pid_, fd);
1441 } else {
1442 scnprintf(linkname, sizeof(linkname),
1443 "/proc/%d/task/%d/fd/%d", thread->pid_, thread->tid, fd);
1444 }
1445
1446 if (lstat(linkname, &st) < 0 || st.st_size + 1 > (off_t)sizeof(pathname))
1447 return -1;
1448
1449 ret = readlink(linkname, pathname, sizeof(pathname));
1450
1451 if (ret < 0 || ret > st.st_size)
1452 return -1;
1453
1454 pathname[ret] = '\0';
1455 return trace__set_fd_pathname(thread, fd, pathname);
1456}
1457
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001458static const char *thread__fd_path(struct thread *thread, int fd,
1459 struct trace *trace)
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001460{
Namhyung Kim89dceb22014-10-06 09:46:03 +09001461 struct thread_trace *ttrace = thread__priv(thread);
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001462
1463 if (ttrace == NULL)
1464 return NULL;
1465
1466 if (fd < 0)
1467 return NULL;
1468
Arnaldo Carvalho de Melocdcd1e62014-06-10 16:00:18 -03001469 if ((fd > ttrace->paths.max || ttrace->paths.table[fd] == NULL)) {
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001470 if (!trace->live)
1471 return NULL;
1472 ++trace->stats.proc_getname;
Arnaldo Carvalho de Melocdcd1e62014-06-10 16:00:18 -03001473 if (thread__read_fd_path(thread, fd))
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001474 return NULL;
1475 }
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001476
1477 return ttrace->paths.table[fd];
1478}
1479
1480static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
1481 struct syscall_arg *arg)
1482{
1483 int fd = arg->val;
1484 size_t printed = scnprintf(bf, size, "%d", fd);
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001485 const char *path = thread__fd_path(arg->thread, fd, arg->trace);
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001486
1487 if (path)
1488 printed += scnprintf(bf + printed, size - printed, "<%s>", path);
1489
1490 return printed;
1491}
1492
1493static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
1494 struct syscall_arg *arg)
1495{
1496 int fd = arg->val;
1497 size_t printed = syscall_arg__scnprintf_fd(bf, size, arg);
Namhyung Kim89dceb22014-10-06 09:46:03 +09001498 struct thread_trace *ttrace = thread__priv(arg->thread);
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001499
Arnaldo Carvalho de Melo04662522013-12-26 17:41:15 -03001500 if (ttrace && fd >= 0 && fd <= ttrace->paths.max)
1501 zfree(&ttrace->paths.table[fd]);
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001502
1503 return printed;
1504}
1505
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03001506static void thread__set_filename_pos(struct thread *thread, const char *bf,
1507 unsigned long ptr)
1508{
1509 struct thread_trace *ttrace = thread__priv(thread);
1510
1511 ttrace->filename.ptr = ptr;
1512 ttrace->filename.entry_str_pos = bf - ttrace->entry_str;
1513}
1514
1515static size_t syscall_arg__scnprintf_filename(char *bf, size_t size,
1516 struct syscall_arg *arg)
1517{
1518 unsigned long ptr = arg->val;
1519
1520 if (!arg->trace->vfs_getname)
1521 return scnprintf(bf, size, "%#x", ptr);
1522
1523 thread__set_filename_pos(arg->thread, bf, ptr);
1524 return 0;
1525}
1526
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001527static bool trace__filter_duration(struct trace *trace, double t)
1528{
1529 return t < (trace->duration_filter * NSEC_PER_MSEC);
1530}
1531
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001532static size_t trace__fprintf_tstamp(struct trace *trace, u64 tstamp, FILE *fp)
1533{
1534 double ts = (double)(tstamp - trace->base_time) / NSEC_PER_MSEC;
1535
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001536 return fprintf(fp, "%10.3f ", ts);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001537}
1538
Namhyung Kimf15eb532012-10-05 14:02:16 +09001539static bool done = false;
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03001540static bool interrupted = false;
Namhyung Kimf15eb532012-10-05 14:02:16 +09001541
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03001542static void sig_handler(int sig)
Namhyung Kimf15eb532012-10-05 14:02:16 +09001543{
1544 done = true;
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03001545 interrupted = sig == SIGINT;
Namhyung Kimf15eb532012-10-05 14:02:16 +09001546}
1547
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001548static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thread,
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001549 u64 duration, u64 tstamp, FILE *fp)
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001550{
1551 size_t printed = trace__fprintf_tstamp(trace, tstamp, fp);
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001552 printed += fprintf_duration(duration, fp);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001553
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -03001554 if (trace->multiple_threads) {
1555 if (trace->show_comm)
Frederic Weisbecker1902efe2013-09-11 16:56:44 +02001556 printed += fprintf(fp, "%.14s/", thread__comm_str(thread));
Adrian Hunter38051232013-07-04 16:20:31 +03001557 printed += fprintf(fp, "%d ", thread->tid);
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -03001558 }
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001559
1560 return printed;
1561}
1562
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001563static int trace__process_event(struct trace *trace, struct machine *machine,
Frederic Weisbecker162f0be2013-09-11 16:18:24 +02001564 union perf_event *event, struct perf_sample *sample)
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001565{
1566 int ret = 0;
1567
1568 switch (event->header.type) {
1569 case PERF_RECORD_LOST:
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001570 color_fprintf(trace->output, PERF_COLOR_RED,
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001571 "LOST %" PRIu64 " events!\n", event->lost.lost);
Frederic Weisbecker162f0be2013-09-11 16:18:24 +02001572 ret = machine__process_lost_event(machine, event, sample);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001573 default:
Frederic Weisbecker162f0be2013-09-11 16:18:24 +02001574 ret = machine__process_event(machine, event, sample);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001575 break;
1576 }
1577
1578 return ret;
1579}
1580
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001581static int trace__tool_process(struct perf_tool *tool,
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001582 union perf_event *event,
Frederic Weisbecker162f0be2013-09-11 16:18:24 +02001583 struct perf_sample *sample,
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001584 struct machine *machine)
1585{
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001586 struct trace *trace = container_of(tool, struct trace, tool);
Frederic Weisbecker162f0be2013-09-11 16:18:24 +02001587 return trace__process_event(trace, machine, event, sample);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001588}
1589
1590static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
1591{
Namhyung Kim0a7e6d12014-08-12 15:40:45 +09001592 int err = symbol__init(NULL);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001593
1594 if (err)
1595 return err;
1596
David Ahern8fb598e2013-09-28 13:13:00 -06001597 trace->host = machine__new_host();
1598 if (trace->host == NULL)
1599 return -ENOMEM;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001600
Arnaldo Carvalho de Melo959c2192015-07-24 12:13:05 -03001601 if (trace_event__register_resolver(trace->host, machine__resolve_kernel_addr) < 0)
Arnaldo Carvalho de Melo706c3da2015-07-22 16:16:16 -03001602 return -errno;
1603
Arnaldo Carvalho de Meloa33fbd52013-11-11 11:36:12 -03001604 err = __machine__synthesize_threads(trace->host, &trace->tool, &trace->opts.target,
Kan Liang9d9cad72015-06-17 09:51:11 -04001605 evlist->threads, trace__tool_process, false,
1606 trace->opts.proc_map_timeout);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001607 if (err)
1608 symbol__exit();
1609
1610 return err;
1611}
1612
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001613static int syscall__set_arg_fmts(struct syscall *sc)
1614{
1615 struct format_field *field;
1616 int idx = 0;
1617
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001618 sc->arg_scnprintf = calloc(sc->nr_args, sizeof(void *));
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001619 if (sc->arg_scnprintf == NULL)
1620 return -1;
1621
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -03001622 if (sc->fmt)
1623 sc->arg_parm = sc->fmt->arg_parm;
1624
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001625 for (field = sc->args; field; field = field->next) {
Arnaldo Carvalho de Melobeccb2b2013-08-26 12:29:38 -03001626 if (sc->fmt && sc->fmt->arg_scnprintf[idx])
1627 sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx];
1628 else if (field->flags & FIELD_IS_POINTER)
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001629 sc->arg_scnprintf[idx] = syscall_arg__scnprintf_hex;
1630 ++idx;
1631 }
1632
1633 return 0;
1634}
1635
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001636static int trace__read_syscall_info(struct trace *trace, int id)
1637{
1638 char tp_name[128];
1639 struct syscall *sc;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001640 const char *name = audit_syscall_to_name(id, trace->audit.machine);
Arnaldo Carvalho de Melo3a531262012-10-20 12:39:03 -03001641
1642 if (name == NULL)
1643 return -1;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001644
1645 if (id > trace->syscalls.max) {
1646 struct syscall *nsyscalls = realloc(trace->syscalls.table, (id + 1) * sizeof(*sc));
1647
1648 if (nsyscalls == NULL)
1649 return -1;
1650
1651 if (trace->syscalls.max != -1) {
1652 memset(nsyscalls + trace->syscalls.max + 1, 0,
1653 (id - trace->syscalls.max) * sizeof(*sc));
1654 } else {
1655 memset(nsyscalls, 0, (id + 1) * sizeof(*sc));
1656 }
1657
1658 trace->syscalls.table = nsyscalls;
1659 trace->syscalls.max = id;
1660 }
1661
1662 sc = trace->syscalls.table + id;
Arnaldo Carvalho de Melo3a531262012-10-20 12:39:03 -03001663 sc->name = name;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001664
Arnaldo Carvalho de Melo3a531262012-10-20 12:39:03 -03001665 sc->fmt = syscall_fmt__find(sc->name);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001666
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -03001667 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name);
Jiri Olsa97978b32013-12-03 14:09:24 +01001668 sc->tp_format = trace_event__tp_format("syscalls", tp_name);
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -03001669
1670 if (sc->tp_format == NULL && sc->fmt && sc->fmt->alias) {
1671 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->fmt->alias);
Jiri Olsa97978b32013-12-03 14:09:24 +01001672 sc->tp_format = trace_event__tp_format("syscalls", tp_name);
Arnaldo Carvalho de Meloaec19302012-09-27 13:16:00 -03001673 }
1674
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001675 if (sc->tp_format == NULL)
1676 return -1;
1677
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001678 sc->args = sc->tp_format->format.fields;
1679 sc->nr_args = sc->tp_format->format.nr_fields;
1680 /* drop nr field - not relevant here; does not exist on older kernels */
1681 if (sc->args && strcmp(sc->args->name, "nr") == 0) {
1682 sc->args = sc->args->next;
1683 --sc->nr_args;
1684 }
1685
Arnaldo Carvalho de Melo5089f202014-06-17 14:29:24 -03001686 sc->is_exit = !strcmp(name, "exit_group") || !strcmp(name, "exit");
1687
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001688 return syscall__set_arg_fmts(sc);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001689}
1690
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001691static int trace__validate_ev_qualifier(struct trace *trace)
1692{
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001693 int err = 0, i;
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001694 struct str_node *pos;
1695
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001696 trace->ev_qualifier_ids.nr = strlist__nr_entries(trace->ev_qualifier);
1697 trace->ev_qualifier_ids.entries = malloc(trace->ev_qualifier_ids.nr *
1698 sizeof(trace->ev_qualifier_ids.entries[0]));
1699
1700 if (trace->ev_qualifier_ids.entries == NULL) {
1701 fputs("Error:\tNot enough memory for allocating events qualifier ids\n",
1702 trace->output);
1703 err = -EINVAL;
1704 goto out;
1705 }
1706
1707 i = 0;
1708
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001709 strlist__for_each(pos, trace->ev_qualifier) {
1710 const char *sc = pos->s;
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001711 int id = audit_name_to_syscall(sc, trace->audit.machine);
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001712
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001713 if (id < 0) {
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001714 if (err == 0) {
1715 fputs("Error:\tInvalid syscall ", trace->output);
1716 err = -EINVAL;
1717 } else {
1718 fputs(", ", trace->output);
1719 }
1720
1721 fputs(sc, trace->output);
1722 }
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001723
1724 trace->ev_qualifier_ids.entries[i++] = id;
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001725 }
1726
1727 if (err < 0) {
1728 fputs("\nHint:\ttry 'perf list syscalls:sys_enter_*'"
1729 "\nHint:\tand: 'man syscalls'\n", trace->output);
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001730 zfree(&trace->ev_qualifier_ids.entries);
1731 trace->ev_qualifier_ids.nr = 0;
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001732 }
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03001733out:
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03001734 return err;
1735}
1736
David Ahern55d43bc2015-02-19 15:00:22 -05001737/*
1738 * args is to be interpreted as a series of longs but we need to handle
1739 * 8-byte unaligned accesses. args points to raw_data within the event
1740 * and raw_data is guaranteed to be 8-byte unaligned because it is
1741 * preceded by raw_size which is a u32. So we need to copy args to a temp
1742 * variable to read it. Most notably this avoids extended load instructions
1743 * on unaligned addresses
1744 */
1745
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001746static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
David Ahern55d43bc2015-02-19 15:00:22 -05001747 unsigned char *args, struct trace *trace,
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001748 struct thread *thread)
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001749{
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001750 size_t printed = 0;
David Ahern55d43bc2015-02-19 15:00:22 -05001751 unsigned char *p;
1752 unsigned long val;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001753
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001754 if (sc->args != NULL) {
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001755 struct format_field *field;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001756 u8 bit = 1;
1757 struct syscall_arg arg = {
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001758 .idx = 0,
1759 .mask = 0,
1760 .trace = trace,
1761 .thread = thread,
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001762 };
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001763
Arnaldo Carvalho de Melof208bd82015-03-20 17:46:53 -03001764 for (field = sc->args; field;
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001765 field = field->next, ++arg.idx, bit <<= 1) {
1766 if (arg.mask & bit)
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -03001767 continue;
David Ahern55d43bc2015-02-19 15:00:22 -05001768
1769 /* special care for unaligned accesses */
1770 p = args + sizeof(unsigned long) * arg.idx;
1771 memcpy(&val, p, sizeof(val));
1772
Arnaldo Carvalho de Melo4aa58232013-09-20 12:19:41 -03001773 /*
1774 * Suppress this argument if its value is zero and
1775 * and we don't have a string associated in an
1776 * strarray for it.
1777 */
David Ahern55d43bc2015-02-19 15:00:22 -05001778 if (val == 0 &&
Arnaldo Carvalho de Melo4aa58232013-09-20 12:19:41 -03001779 !(sc->arg_scnprintf &&
1780 sc->arg_scnprintf[arg.idx] == SCA_STRARRAY &&
1781 sc->arg_parm[arg.idx]))
Arnaldo Carvalho de Melo22ae5cf12013-09-12 11:27:34 -03001782 continue;
1783
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001784 printed += scnprintf(bf + printed, size - printed,
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001785 "%s%s: ", printed ? ", " : "", field->name);
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001786 if (sc->arg_scnprintf && sc->arg_scnprintf[arg.idx]) {
David Ahern55d43bc2015-02-19 15:00:22 -05001787 arg.val = val;
Arnaldo Carvalho de Melo1f115cb2013-09-03 15:50:28 -03001788 if (sc->arg_parm)
1789 arg.parm = sc->arg_parm[arg.idx];
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001790 printed += sc->arg_scnprintf[arg.idx](bf + printed,
1791 size - printed, &arg);
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -03001792 } else {
Arnaldo Carvalho de Melo13d4ff32013-08-23 18:14:48 -03001793 printed += scnprintf(bf + printed, size - printed,
David Ahern55d43bc2015-02-19 15:00:22 -05001794 "%ld", val);
Arnaldo Carvalho de Melo6e7eeb52013-09-02 10:39:21 -03001795 }
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001796 }
1797 } else {
Arnaldo Carvalho de Melo01533e92013-09-03 12:20:12 -03001798 int i = 0;
1799
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001800 while (i < 6) {
David Ahern55d43bc2015-02-19 15:00:22 -05001801 /* special care for unaligned accesses */
1802 p = args + sizeof(unsigned long) * i;
1803 memcpy(&val, p, sizeof(val));
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001804 printed += scnprintf(bf + printed, size - printed,
1805 "%sarg%d: %ld",
David Ahern55d43bc2015-02-19 15:00:22 -05001806 printed ? ", " : "", i, val);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03001807 ++i;
1808 }
1809 }
1810
1811 return printed;
1812}
1813
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001814typedef int (*tracepoint_handler)(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04001815 union perf_event *event,
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001816 struct perf_sample *sample);
1817
1818static struct syscall *trace__syscall_info(struct trace *trace,
David Ahernbf2575c2013-10-08 21:26:53 -06001819 struct perf_evsel *evsel, int id)
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001820{
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001821
1822 if (id < 0) {
Arnaldo Carvalho de Meloadaa18b2013-08-22 17:55:25 -03001823
1824 /*
1825 * XXX: Noticed on x86_64, reproduced as far back as 3.0.36, haven't tried
1826 * before that, leaving at a higher verbosity level till that is
1827 * explained. Reproduced with plain ftrace with:
1828 *
1829 * echo 1 > /t/events/raw_syscalls/sys_exit/enable
1830 * grep "NR -1 " /t/trace_pipe
1831 *
1832 * After generating some load on the machine.
1833 */
1834 if (verbose > 1) {
1835 static u64 n;
1836 fprintf(trace->output, "Invalid syscall %d id, skipping (%s, %" PRIu64 ") ...\n",
1837 id, perf_evsel__name(evsel), ++n);
1838 }
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001839 return NULL;
1840 }
1841
1842 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL) &&
1843 trace__read_syscall_info(trace, id))
1844 goto out_cant_read;
1845
1846 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL))
1847 goto out_cant_read;
1848
1849 return &trace->syscalls.table[id];
1850
1851out_cant_read:
Arnaldo Carvalho de Melo7c304ee02013-08-22 16:49:54 -03001852 if (verbose) {
1853 fprintf(trace->output, "Problems reading syscall %d", id);
1854 if (id <= trace->syscalls.max && trace->syscalls.table[id].name != NULL)
1855 fprintf(trace->output, "(%s)", trace->syscalls.table[id].name);
1856 fputs(" information\n", trace->output);
1857 }
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001858 return NULL;
1859}
1860
David Ahernbf2575c2013-10-08 21:26:53 -06001861static void thread__update_stats(struct thread_trace *ttrace,
1862 int id, struct perf_sample *sample)
1863{
1864 struct int_node *inode;
1865 struct stats *stats;
1866 u64 duration = 0;
1867
1868 inode = intlist__findnew(ttrace->syscall_stats, id);
1869 if (inode == NULL)
1870 return;
1871
1872 stats = inode->priv;
1873 if (stats == NULL) {
1874 stats = malloc(sizeof(struct stats));
1875 if (stats == NULL)
1876 return;
1877 init_stats(stats);
1878 inode->priv = stats;
1879 }
1880
1881 if (ttrace->entry_time && sample->time > ttrace->entry_time)
1882 duration = sample->time - ttrace->entry_time;
1883
1884 update_stats(stats, duration);
1885}
1886
Arnaldo Carvalho de Meloe5966632015-02-13 13:22:21 -03001887static int trace__printf_interrupted_entry(struct trace *trace, struct perf_sample *sample)
1888{
1889 struct thread_trace *ttrace;
1890 u64 duration;
1891 size_t printed;
1892
1893 if (trace->current == NULL)
1894 return 0;
1895
1896 ttrace = thread__priv(trace->current);
1897
1898 if (!ttrace->entry_pending)
1899 return 0;
1900
1901 duration = sample->time - ttrace->entry_time;
1902
1903 printed = trace__fprintf_entry_head(trace, trace->current, duration, sample->time, trace->output);
1904 printed += fprintf(trace->output, "%-70s) ...\n", ttrace->entry_str);
1905 ttrace->entry_pending = false;
1906
1907 return printed;
1908}
1909
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001910static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04001911 union perf_event *event __maybe_unused,
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001912 struct perf_sample *sample)
1913{
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001914 char *msg;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001915 void *args;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001916 size_t printed = 0;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001917 struct thread *thread;
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001918 int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
David Ahernbf2575c2013-10-08 21:26:53 -06001919 struct syscall *sc = trace__syscall_info(trace, evsel, id);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001920 struct thread_trace *ttrace;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001921
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001922 if (sc == NULL)
1923 return -1;
1924
David Ahern8fb598e2013-09-28 13:13:00 -06001925 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001926 ttrace = thread__trace(thread, trace->output);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001927 if (ttrace == NULL)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001928 goto out_put;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001929
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -03001930 args = perf_evsel__sc_tp_ptr(evsel, args, sample);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001931
1932 if (ttrace->entry_str == NULL) {
Arnaldo Carvalho de Meloe4d44e82015-08-04 22:17:29 -03001933 ttrace->entry_str = malloc(trace__entry_str_size);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001934 if (!ttrace->entry_str)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001935 goto out_put;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001936 }
1937
David Ahern13f22a22015-03-19 12:23:03 -06001938 if (!trace->summary_only)
Arnaldo Carvalho de Melo6ebad5c2015-03-25 18:01:15 -03001939 trace__printf_interrupted_entry(trace, sample);
Arnaldo Carvalho de Meloe5966632015-02-13 13:22:21 -03001940
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001941 ttrace->entry_time = sample->time;
1942 msg = ttrace->entry_str;
Arnaldo Carvalho de Meloe4d44e82015-08-04 22:17:29 -03001943 printed += scnprintf(msg + printed, trace__entry_str_size - printed, "%s(", sc->name);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001944
Arnaldo Carvalho de Meloe4d44e82015-08-04 22:17:29 -03001945 printed += syscall__scnprintf_args(sc, msg + printed, trace__entry_str_size - printed,
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03001946 args, trace, thread);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001947
Arnaldo Carvalho de Melo5089f202014-06-17 14:29:24 -03001948 if (sc->is_exit) {
David Ahernfd2eaba2013-11-12 09:31:15 -07001949 if (!trace->duration_filter && !trace->summary_only) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001950 trace__fprintf_entry_head(trace, thread, 1, sample->time, trace->output);
1951 fprintf(trace->output, "%-70s\n", ttrace->entry_str);
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001952 }
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001953 } else
1954 ttrace->entry_pending = true;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001955
Arnaldo Carvalho de Melof3b623b2015-03-02 22:21:35 -03001956 if (trace->current != thread) {
1957 thread__put(trace->current);
1958 trace->current = thread__get(thread);
1959 }
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001960 err = 0;
1961out_put:
1962 thread__put(thread);
1963 return err;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001964}
1965
1966static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04001967 union perf_event *event __maybe_unused,
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001968 struct perf_sample *sample)
1969{
Chang Hyun Park2c82c3a2014-09-26 21:54:01 +09001970 long ret;
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001971 u64 duration = 0;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001972 struct thread *thread;
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001973 int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
David Ahernbf2575c2013-10-08 21:26:53 -06001974 struct syscall *sc = trace__syscall_info(trace, evsel, id);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001975 struct thread_trace *ttrace;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001976
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001977 if (sc == NULL)
1978 return -1;
1979
David Ahern8fb598e2013-09-28 13:13:00 -06001980 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03001981 ttrace = thread__trace(thread, trace->output);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03001982 if (ttrace == NULL)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001983 goto out_put;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001984
David Ahernbf2575c2013-10-08 21:26:53 -06001985 if (trace->summary)
1986 thread__update_stats(ttrace, id, sample);
1987
Arnaldo Carvalho de Melo77170982013-11-06 16:35:57 -03001988 ret = perf_evsel__sc_tp_uint(evsel, ret, sample);
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03001989
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03001990 if (id == trace->audit.open_id && ret >= 0 && trace->last_vfs_getname) {
1991 trace__set_fd_pathname(thread, ret, trace->last_vfs_getname);
1992 trace->last_vfs_getname = NULL;
1993 ++trace->stats.vfs_getname;
1994 }
1995
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03001996 ttrace->exit_time = sample->time;
1997
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03001998 if (ttrace->entry_time) {
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02001999 duration = sample->time - ttrace->entry_time;
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03002000 if (trace__filter_duration(trace, duration))
2001 goto out;
2002 } else if (trace->duration_filter)
2003 goto out;
Arnaldo Carvalho de Melo60c907a2012-10-24 17:24:47 -02002004
David Ahernfd2eaba2013-11-12 09:31:15 -07002005 if (trace->summary_only)
2006 goto out;
2007
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002008 trace__fprintf_entry_head(trace, thread, duration, sample->time, trace->output);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03002009
2010 if (ttrace->entry_pending) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002011 fprintf(trace->output, "%-70s", ttrace->entry_str);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03002012 } else {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002013 fprintf(trace->output, " ... [");
2014 color_fprintf(trace->output, PERF_COLOR_YELLOW, "continued");
2015 fprintf(trace->output, "]: %s()", sc->name);
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03002016 }
2017
Arnaldo Carvalho de Meloda3c9a42013-08-26 11:28:34 -03002018 if (sc->fmt == NULL) {
2019signed_print:
Chang Hyun Park2c82c3a2014-09-26 21:54:01 +09002020 fprintf(trace->output, ") = %ld", ret);
Arnaldo Carvalho de Meloda3c9a42013-08-26 11:28:34 -03002021 } else if (ret < 0 && sc->fmt->errmsg) {
Masami Hiramatsu942a91e2014-08-14 02:22:41 +00002022 char bf[STRERR_BUFSIZE];
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03002023 const char *emsg = strerror_r(-ret, bf, sizeof(bf)),
2024 *e = audit_errno_to_name(-ret);
2025
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002026 fprintf(trace->output, ") = -1 %s %s", e, emsg);
Arnaldo Carvalho de Meloda3c9a42013-08-26 11:28:34 -03002027 } else if (ret == 0 && sc->fmt->timeout)
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002028 fprintf(trace->output, ") = 0 Timeout");
Arnaldo Carvalho de Melo04b34722013-08-26 11:36:30 -03002029 else if (sc->fmt->hexret)
Chang Hyun Park2c82c3a2014-09-26 21:54:01 +09002030 fprintf(trace->output, ") = %#lx", ret);
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03002031 else
Arnaldo Carvalho de Meloda3c9a42013-08-26 11:28:34 -03002032 goto signed_print;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03002033
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002034 fputc('\n', trace->output);
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03002035out:
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03002036 ttrace->entry_pending = false;
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002037 err = 0;
2038out_put:
2039 thread__put(thread);
2040 return err;
Arnaldo Carvalho de Meloba3d7de2012-09-28 17:58:36 -03002041}
2042
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002043static int trace__vfs_getname(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04002044 union perf_event *event __maybe_unused,
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002045 struct perf_sample *sample)
2046{
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03002047 struct thread *thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
2048 struct thread_trace *ttrace;
2049 size_t filename_len, entry_str_len, to_move;
2050 ssize_t remaining_space;
2051 char *pos;
2052 const char *filename;
2053
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002054 trace->last_vfs_getname = perf_evsel__rawptr(evsel, sample, "pathname");
Arnaldo Carvalho de Melof9945922015-08-04 22:30:09 -03002055
2056 if (!thread)
2057 goto out;
2058
2059 ttrace = thread__priv(thread);
2060 if (!ttrace)
2061 goto out;
2062
2063 if (!ttrace->filename.ptr)
2064 goto out;
2065
2066 entry_str_len = strlen(ttrace->entry_str);
2067 remaining_space = trace__entry_str_size - entry_str_len - 1; /* \0 */
2068 if (remaining_space <= 0)
2069 goto out;
2070
2071 filename = trace->last_vfs_getname;
2072 filename_len = strlen(filename);
2073 if (filename_len > (size_t)remaining_space) {
2074 filename += filename_len - remaining_space;
2075 filename_len = remaining_space;
2076 }
2077
2078 to_move = entry_str_len - ttrace->filename.entry_str_pos + 1; /* \0 */
2079 pos = ttrace->entry_str + ttrace->filename.entry_str_pos;
2080 memmove(pos + filename_len, pos, to_move);
2081 memcpy(pos, filename, filename_len);
2082
2083 ttrace->filename.ptr = 0;
2084 ttrace->filename.entry_str_pos = 0;
2085out:
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002086 return 0;
2087}
2088
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002089static int trace__sched_stat_runtime(struct trace *trace, struct perf_evsel *evsel,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04002090 union perf_event *event __maybe_unused,
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002091 struct perf_sample *sample)
2092{
2093 u64 runtime = perf_evsel__intval(evsel, sample, "runtime");
2094 double runtime_ms = (double)runtime / NSEC_PER_MSEC;
David Ahern8fb598e2013-09-28 13:13:00 -06002095 struct thread *thread = machine__findnew_thread(trace->host,
Adrian Hunter314add62013-08-27 11:23:03 +03002096 sample->pid,
2097 sample->tid);
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002098 struct thread_trace *ttrace = thread__trace(thread, trace->output);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002099
2100 if (ttrace == NULL)
2101 goto out_dump;
2102
2103 ttrace->runtime_ms += runtime_ms;
2104 trace->runtime_ms += runtime_ms;
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002105 thread__put(thread);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002106 return 0;
2107
2108out_dump:
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002109 fprintf(trace->output, "%s: comm=%s,pid=%u,runtime=%" PRIu64 ",vruntime=%" PRIu64 ")\n",
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002110 evsel->name,
2111 perf_evsel__strval(evsel, sample, "comm"),
2112 (pid_t)perf_evsel__intval(evsel, sample, "pid"),
2113 runtime,
2114 perf_evsel__intval(evsel, sample, "vruntime"));
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002115 thread__put(thread);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002116 return 0;
2117}
2118
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002119static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
2120 union perf_event *event __maybe_unused,
2121 struct perf_sample *sample)
2122{
2123 trace__printf_interrupted_entry(trace, sample);
2124 trace__fprintf_tstamp(trace, sample->time, trace->output);
Arnaldo Carvalho de Melo08089212015-02-19 21:51:50 -08002125
2126 if (trace->trace_syscalls)
2127 fprintf(trace->output, "( ): ");
2128
2129 fprintf(trace->output, "%s:", evsel->name);
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002130
2131 if (evsel->tp_format) {
2132 event_format__fprintf(evsel->tp_format, sample->cpu,
2133 sample->raw_data, sample->raw_size,
2134 trace->output);
2135 }
2136
2137 fprintf(trace->output, ")\n");
2138 return 0;
2139}
2140
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002141static void print_location(FILE *f, struct perf_sample *sample,
2142 struct addr_location *al,
2143 bool print_dso, bool print_sym)
2144{
2145
2146 if ((verbose || print_dso) && al->map)
2147 fprintf(f, "%s@", al->map->dso->long_name);
2148
2149 if ((verbose || print_sym) && al->sym)
Arnaldo Carvalho de Melo4414a3c2014-07-08 15:39:21 -03002150 fprintf(f, "%s+0x%" PRIx64, al->sym->name,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002151 al->addr - al->sym->start);
2152 else if (al->map)
Arnaldo Carvalho de Melo4414a3c2014-07-08 15:39:21 -03002153 fprintf(f, "0x%" PRIx64, al->addr);
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002154 else
Arnaldo Carvalho de Melo4414a3c2014-07-08 15:39:21 -03002155 fprintf(f, "0x%" PRIx64, sample->addr);
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002156}
2157
2158static int trace__pgfault(struct trace *trace,
2159 struct perf_evsel *evsel,
2160 union perf_event *event,
2161 struct perf_sample *sample)
2162{
2163 struct thread *thread;
2164 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
2165 struct addr_location al;
2166 char map_type = 'd';
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04002167 struct thread_trace *ttrace;
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002168 int err = -1;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002169
2170 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04002171 ttrace = thread__trace(thread, trace->output);
2172 if (ttrace == NULL)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002173 goto out_put;
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04002174
2175 if (evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ)
2176 ttrace->pfmaj++;
2177 else
2178 ttrace->pfmin++;
2179
2180 if (trace->summary_only)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002181 goto out;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002182
Arnaldo Carvalho de Melobb871a92014-10-23 12:50:25 -03002183 thread__find_addr_location(thread, cpumode, MAP__FUNCTION,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002184 sample->ip, &al);
2185
2186 trace__fprintf_entry_head(trace, thread, 0, sample->time, trace->output);
2187
2188 fprintf(trace->output, "%sfault [",
2189 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ?
2190 "maj" : "min");
2191
2192 print_location(trace->output, sample, &al, false, true);
2193
2194 fprintf(trace->output, "] => ");
2195
Arnaldo Carvalho de Melobb871a92014-10-23 12:50:25 -03002196 thread__find_addr_location(thread, cpumode, MAP__VARIABLE,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002197 sample->addr, &al);
2198
2199 if (!al.map) {
Arnaldo Carvalho de Melobb871a92014-10-23 12:50:25 -03002200 thread__find_addr_location(thread, cpumode,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002201 MAP__FUNCTION, sample->addr, &al);
2202
2203 if (al.map)
2204 map_type = 'x';
2205 else
2206 map_type = '?';
2207 }
2208
2209 print_location(trace->output, sample, &al, true, false);
2210
2211 fprintf(trace->output, " (%c%c)\n", map_type, al.level);
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002212out:
2213 err = 0;
2214out_put:
2215 thread__put(thread);
2216 return err;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002217}
2218
David Ahernbdc89662013-08-28 22:29:53 -06002219static bool skip_sample(struct trace *trace, struct perf_sample *sample)
2220{
2221 if ((trace->pid_list && intlist__find(trace->pid_list, sample->pid)) ||
2222 (trace->tid_list && intlist__find(trace->tid_list, sample->tid)))
2223 return false;
2224
2225 if (trace->pid_list || trace->tid_list)
2226 return true;
2227
2228 return false;
2229}
2230
David Ahern6810fc92013-08-28 22:29:52 -06002231static int trace__process_sample(struct perf_tool *tool,
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04002232 union perf_event *event,
David Ahern6810fc92013-08-28 22:29:52 -06002233 struct perf_sample *sample,
2234 struct perf_evsel *evsel,
2235 struct machine *machine __maybe_unused)
2236{
2237 struct trace *trace = container_of(tool, struct trace, tool);
2238 int err = 0;
2239
Arnaldo Carvalho de Melo744a9712013-11-06 10:17:38 -03002240 tracepoint_handler handler = evsel->handler;
David Ahern6810fc92013-08-28 22:29:52 -06002241
David Ahernbdc89662013-08-28 22:29:53 -06002242 if (skip_sample(trace, sample))
2243 return 0;
2244
David Ahern4bb09192013-09-04 12:37:43 -06002245 if (!trace->full_time && trace->base_time == 0)
David Ahern6810fc92013-08-28 22:29:52 -06002246 trace->base_time = sample->time;
2247
David Ahern31605652013-12-04 19:41:41 -07002248 if (handler) {
2249 ++trace->nr_events;
Stanislav Fomichev0c82adc2014-06-26 20:14:24 +04002250 handler(trace, evsel, event, sample);
David Ahern31605652013-12-04 19:41:41 -07002251 }
David Ahern6810fc92013-08-28 22:29:52 -06002252
2253 return err;
2254}
2255
David Ahernbdc89662013-08-28 22:29:53 -06002256static int parse_target_str(struct trace *trace)
2257{
2258 if (trace->opts.target.pid) {
2259 trace->pid_list = intlist__new(trace->opts.target.pid);
2260 if (trace->pid_list == NULL) {
2261 pr_err("Error parsing process id string\n");
2262 return -EINVAL;
2263 }
2264 }
2265
2266 if (trace->opts.target.tid) {
2267 trace->tid_list = intlist__new(trace->opts.target.tid);
2268 if (trace->tid_list == NULL) {
2269 pr_err("Error parsing thread id string\n");
2270 return -EINVAL;
2271 }
2272 }
2273
2274 return 0;
2275}
2276
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002277static int trace__record(struct trace *trace, int argc, const char **argv)
David Ahern5e2485b2013-09-28 13:13:01 -06002278{
2279 unsigned int rec_argc, i, j;
2280 const char **rec_argv;
2281 const char * const record_args[] = {
2282 "record",
2283 "-R",
2284 "-m", "1024",
2285 "-c", "1",
David Ahern5e2485b2013-09-28 13:13:01 -06002286 };
2287
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002288 const char * const sc_args[] = { "-e", };
2289 unsigned int sc_args_nr = ARRAY_SIZE(sc_args);
2290 const char * const majpf_args[] = { "-e", "major-faults" };
2291 unsigned int majpf_args_nr = ARRAY_SIZE(majpf_args);
2292 const char * const minpf_args[] = { "-e", "minor-faults" };
2293 unsigned int minpf_args_nr = ARRAY_SIZE(minpf_args);
2294
David Ahern9aca7f12013-12-04 19:41:39 -07002295 /* +1 is for the event string below */
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002296 rec_argc = ARRAY_SIZE(record_args) + sc_args_nr + 1 +
2297 majpf_args_nr + minpf_args_nr + argc;
David Ahern5e2485b2013-09-28 13:13:01 -06002298 rec_argv = calloc(rec_argc + 1, sizeof(char *));
2299
2300 if (rec_argv == NULL)
2301 return -ENOMEM;
2302
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002303 j = 0;
David Ahern5e2485b2013-09-28 13:13:01 -06002304 for (i = 0; i < ARRAY_SIZE(record_args); i++)
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002305 rec_argv[j++] = record_args[i];
2306
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002307 if (trace->trace_syscalls) {
2308 for (i = 0; i < sc_args_nr; i++)
2309 rec_argv[j++] = sc_args[i];
David Ahern5e2485b2013-09-28 13:13:01 -06002310
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002311 /* event string may be different for older kernels - e.g., RHEL6 */
2312 if (is_valid_tracepoint("raw_syscalls:sys_enter"))
2313 rec_argv[j++] = "raw_syscalls:sys_enter,raw_syscalls:sys_exit";
2314 else if (is_valid_tracepoint("syscalls:sys_enter"))
2315 rec_argv[j++] = "syscalls:sys_enter,syscalls:sys_exit";
2316 else {
2317 pr_err("Neither raw_syscalls nor syscalls events exist.\n");
2318 return -1;
2319 }
David Ahern9aca7f12013-12-04 19:41:39 -07002320 }
David Ahern9aca7f12013-12-04 19:41:39 -07002321
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002322 if (trace->trace_pgfaults & TRACE_PFMAJ)
2323 for (i = 0; i < majpf_args_nr; i++)
2324 rec_argv[j++] = majpf_args[i];
David Ahern5e2485b2013-09-28 13:13:01 -06002325
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002326 if (trace->trace_pgfaults & TRACE_PFMIN)
2327 for (i = 0; i < minpf_args_nr; i++)
2328 rec_argv[j++] = minpf_args[i];
2329
2330 for (i = 0; i < (unsigned int)argc; i++)
2331 rec_argv[j++] = argv[i];
2332
2333 return cmd_record(j, rec_argv, NULL);
David Ahern5e2485b2013-09-28 13:13:01 -06002334}
2335
David Ahernbf2575c2013-10-08 21:26:53 -06002336static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp);
2337
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002338static bool perf_evlist__add_vfs_getname(struct perf_evlist *evlist)
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002339{
Arnaldo Carvalho de Meloef503832013-11-07 16:41:19 -03002340 struct perf_evsel *evsel = perf_evsel__newtp("probe", "vfs_getname");
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002341 if (evsel == NULL)
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002342 return false;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002343
2344 if (perf_evsel__field(evsel, "pathname") == NULL) {
2345 perf_evsel__delete(evsel);
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002346 return false;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002347 }
2348
Arnaldo Carvalho de Melo744a9712013-11-06 10:17:38 -03002349 evsel->handler = trace__vfs_getname;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002350 perf_evlist__add(evlist, evsel);
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002351 return true;
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002352}
2353
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002354static int perf_evlist__add_pgfault(struct perf_evlist *evlist,
2355 u64 config)
2356{
2357 struct perf_evsel *evsel;
2358 struct perf_event_attr attr = {
2359 .type = PERF_TYPE_SOFTWARE,
2360 .mmap_data = 1,
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002361 };
2362
2363 attr.config = config;
Arnaldo Carvalho de Melo05247982014-07-23 18:15:09 -03002364 attr.sample_period = 1;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002365
2366 event_attr_init(&attr);
2367
2368 evsel = perf_evsel__new(&attr);
2369 if (!evsel)
2370 return -ENOMEM;
2371
2372 evsel->handler = trace__pgfault;
2373 perf_evlist__add(evlist, evsel);
2374
2375 return 0;
2376}
2377
Arnaldo Carvalho de Meloddbb1b12015-02-21 12:10:29 -08002378static void trace__handle_event(struct trace *trace, union perf_event *event, struct perf_sample *sample)
2379{
2380 const u32 type = event->header.type;
2381 struct perf_evsel *evsel;
2382
2383 if (!trace->full_time && trace->base_time == 0)
2384 trace->base_time = sample->time;
2385
2386 if (type != PERF_RECORD_SAMPLE) {
2387 trace__process_event(trace, trace->host, event, sample);
2388 return;
2389 }
2390
2391 evsel = perf_evlist__id2evsel(trace->evlist, sample->id);
2392 if (evsel == NULL) {
2393 fprintf(trace->output, "Unknown tp ID %" PRIu64 ", skipping...\n", sample->id);
2394 return;
2395 }
2396
2397 if (evsel->attr.type == PERF_TYPE_TRACEPOINT &&
2398 sample->raw_data == NULL) {
2399 fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n",
2400 perf_evsel__name(evsel), sample->tid,
2401 sample->cpu, sample->raw_size);
2402 } else {
2403 tracepoint_handler handler = evsel->handler;
2404 handler(trace, evsel, event, sample);
2405 }
2406}
2407
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03002408static int trace__add_syscall_newtp(struct trace *trace)
2409{
2410 int ret = -1;
2411 struct perf_evlist *evlist = trace->evlist;
2412 struct perf_evsel *sys_enter, *sys_exit;
2413
2414 sys_enter = perf_evsel__syscall_newtp("sys_enter", trace__sys_enter);
2415 if (sys_enter == NULL)
2416 goto out;
2417
2418 if (perf_evsel__init_sc_tp_ptr_field(sys_enter, args))
2419 goto out_delete_sys_enter;
2420
2421 sys_exit = perf_evsel__syscall_newtp("sys_exit", trace__sys_exit);
2422 if (sys_exit == NULL)
2423 goto out_delete_sys_enter;
2424
2425 if (perf_evsel__init_sc_tp_uint_field(sys_exit, ret))
2426 goto out_delete_sys_exit;
2427
2428 perf_evlist__add(evlist, sys_enter);
2429 perf_evlist__add(evlist, sys_exit);
2430
Arnaldo Carvalho de Melo8b3ce752015-07-02 18:28:11 -03002431 trace->syscalls.events.sys_enter = sys_enter;
2432 trace->syscalls.events.sys_exit = sys_exit;
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03002433
2434 ret = 0;
2435out:
2436 return ret;
2437
2438out_delete_sys_exit:
2439 perf_evsel__delete_priv(sys_exit);
2440out_delete_sys_enter:
2441 perf_evsel__delete_priv(sys_enter);
2442 goto out;
2443}
2444
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002445static int trace__set_ev_qualifier_filter(struct trace *trace)
2446{
2447 int err = -1;
2448 char *filter = asprintf_expr_inout_ints("id", !trace->not_ev_qualifier,
2449 trace->ev_qualifier_ids.nr,
2450 trace->ev_qualifier_ids.entries);
2451
2452 if (filter == NULL)
2453 goto out_enomem;
2454
2455 if (!perf_evsel__append_filter(trace->syscalls.events.sys_enter, "&&", filter))
2456 err = perf_evsel__append_filter(trace->syscalls.events.sys_exit, "&&", filter);
2457
2458 free(filter);
2459out:
2460 return err;
2461out_enomem:
2462 errno = ENOMEM;
2463 goto out;
2464}
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03002465
Namhyung Kimf15eb532012-10-05 14:02:16 +09002466static int trace__run(struct trace *trace, int argc, const char **argv)
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002467{
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002468 struct perf_evlist *evlist = trace->evlist;
Arnaldo Carvalho de Melo94ad89b2015-07-03 17:42:03 -03002469 struct perf_evsel *evsel;
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03002470 int err = -1, i;
2471 unsigned long before;
Namhyung Kimf15eb532012-10-05 14:02:16 +09002472 const bool forks = argc > 0;
Arnaldo Carvalho de Melo46fb3c22014-09-22 14:39:48 -03002473 bool draining = false;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002474
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03002475 trace->live = true;
2476
Arnaldo Carvalho de Meloc27366f2015-07-02 18:24:51 -03002477 if (trace->trace_syscalls && trace__add_syscall_newtp(trace))
Arnaldo Carvalho de Melo801c67b2015-01-22 10:52:55 -03002478 goto out_error_raw_syscalls;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002479
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002480 if (trace->trace_syscalls)
Arnaldo Carvalho de Melo08c98772015-08-04 17:01:04 -03002481 trace->vfs_getname = perf_evlist__add_vfs_getname(evlist);
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002482
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002483 if ((trace->trace_pgfaults & TRACE_PFMAJ) &&
Arnaldo Carvalho de Meloe2726d92015-01-22 10:34:22 -03002484 perf_evlist__add_pgfault(evlist, PERF_COUNT_SW_PAGE_FAULTS_MAJ)) {
Arnaldo Carvalho de Melo5ed08da2015-01-22 11:08:04 -03002485 goto out_error_mem;
Arnaldo Carvalho de Meloe2726d92015-01-22 10:34:22 -03002486 }
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002487
2488 if ((trace->trace_pgfaults & TRACE_PFMIN) &&
2489 perf_evlist__add_pgfault(evlist, PERF_COUNT_SW_PAGE_FAULTS_MIN))
Arnaldo Carvalho de Melo5ed08da2015-01-22 11:08:04 -03002490 goto out_error_mem;
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002491
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002492 if (trace->sched &&
Arnaldo Carvalho de Melo2cc990b2015-01-22 11:13:43 -03002493 perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime",
2494 trace__sched_stat_runtime))
2495 goto out_error_sched_stat_runtime;
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002496
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002497 err = perf_evlist__create_maps(evlist, &trace->opts.target);
2498 if (err < 0) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002499 fprintf(trace->output, "Problems parsing the target to trace, check your options!\n");
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002500 goto out_delete_evlist;
2501 }
2502
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03002503 err = trace__symbols_init(trace, evlist);
2504 if (err < 0) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002505 fprintf(trace->output, "Problems initializing symbol libraries!\n");
Arnaldo Carvalho de Melo03ad9742014-01-03 15:56:06 -03002506 goto out_delete_evlist;
Arnaldo Carvalho de Melo752fde42012-10-06 18:43:19 -03002507 }
2508
Arnaldo Carvalho de Melof77a9512012-12-10 16:41:31 -03002509 perf_evlist__config(evlist, &trace->opts);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002510
Namhyung Kimf15eb532012-10-05 14:02:16 +09002511 signal(SIGCHLD, sig_handler);
2512 signal(SIGINT, sig_handler);
2513
2514 if (forks) {
Namhyung Kim6ef73ec2013-03-11 16:43:15 +09002515 err = perf_evlist__prepare_workload(evlist, &trace->opts.target,
Arnaldo Carvalho de Melo735f7e02014-01-03 14:56:49 -03002516 argv, false, NULL);
Namhyung Kimf15eb532012-10-05 14:02:16 +09002517 if (err < 0) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002518 fprintf(trace->output, "Couldn't run the workload!\n");
Arnaldo Carvalho de Melo03ad9742014-01-03 15:56:06 -03002519 goto out_delete_evlist;
Namhyung Kimf15eb532012-10-05 14:02:16 +09002520 }
2521 }
2522
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002523 err = perf_evlist__open(evlist);
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002524 if (err < 0)
2525 goto out_error_open;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002526
Arnaldo Carvalho de Melo241b0572015-02-21 10:15:21 -08002527 /*
2528 * Better not use !target__has_task() here because we need to cover the
2529 * case where no threads were specified in the command line, but a
2530 * workload was, and in that case we will fill in the thread_map when
2531 * we fork the workload in perf_evlist__prepare_workload.
2532 */
Arnaldo Carvalho de Melof078c382015-02-21 11:36:52 -08002533 if (trace->filter_pids.nr > 0)
2534 err = perf_evlist__set_filter_pids(evlist, trace->filter_pids.nr, trace->filter_pids.entries);
Jiri Olsae13798c2015-06-23 00:36:02 +02002535 else if (thread_map__pid(evlist->threads, 0) == -1)
Arnaldo Carvalho de Melof078c382015-02-21 11:36:52 -08002536 err = perf_evlist__set_filter_pid(evlist, getpid());
2537
Arnaldo Carvalho de Melo94ad89b2015-07-03 17:42:03 -03002538 if (err < 0)
2539 goto out_error_mem;
2540
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002541 if (trace->ev_qualifier_ids.nr > 0) {
2542 err = trace__set_ev_qualifier_filter(trace);
2543 if (err < 0)
2544 goto out_errno;
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002545
Arnaldo Carvalho de Melo2e5e5f82015-08-03 17:12:29 -03002546 pr_debug("event qualifier tracepoint filter: %s\n",
2547 trace->syscalls.events.sys_exit->filter);
2548 }
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002549
Arnaldo Carvalho de Melo94ad89b2015-07-03 17:42:03 -03002550 err = perf_evlist__apply_filters(evlist, &evsel);
2551 if (err < 0)
2552 goto out_error_apply_filters;
Arnaldo Carvalho de Melo241b0572015-02-21 10:15:21 -08002553
Jiri Olsaf8850372013-11-28 17:57:22 +01002554 err = perf_evlist__mmap(evlist, trace->opts.mmap_pages, false);
Arnaldo Carvalho de Meloe09b18d2014-12-11 18:04:10 -03002555 if (err < 0)
2556 goto out_error_mmap;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002557
Arnaldo Carvalho de Melocb24d012015-04-22 10:04:23 -03002558 if (!target__none(&trace->opts.target))
2559 perf_evlist__enable(evlist);
2560
Namhyung Kimf15eb532012-10-05 14:02:16 +09002561 if (forks)
2562 perf_evlist__start_workload(evlist);
2563
Jiri Olsae13798c2015-06-23 00:36:02 +02002564 trace->multiple_threads = thread_map__pid(evlist->threads, 0) == -1 ||
Arnaldo Carvalho de Melo42052be2015-02-13 12:32:45 -03002565 evlist->threads->nr > 1 ||
2566 perf_evlist__first(evlist)->attr.inherit;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002567again:
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03002568 before = trace->nr_events;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002569
2570 for (i = 0; i < evlist->nr_mmaps; i++) {
2571 union perf_event *event;
2572
2573 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002574 struct perf_sample sample;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002575
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03002576 ++trace->nr_events;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002577
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002578 err = perf_evlist__parse_sample(evlist, event, &sample);
2579 if (err) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002580 fprintf(trace->output, "Can't parse sample, err = %d, skipping...\n", err);
Zhouyi Zhou8e50d382013-10-24 15:43:33 +08002581 goto next_event;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002582 }
2583
Arnaldo Carvalho de Meloddbb1b12015-02-21 12:10:29 -08002584 trace__handle_event(trace, event, &sample);
Zhouyi Zhou8e50d382013-10-24 15:43:33 +08002585next_event:
2586 perf_evlist__mmap_consume(evlist, i);
Arnaldo Carvalho de Melo20c5f102013-09-03 11:55:07 -03002587
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002588 if (interrupted)
2589 goto out_disable;
Arnaldo Carvalho de Melo02ac5422015-04-22 11:11:57 -03002590
2591 if (done && !draining) {
2592 perf_evlist__disable(evlist);
2593 draining = true;
2594 }
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002595 }
2596 }
2597
Arnaldo Carvalho de Meloefd57452012-10-17 17:09:46 -03002598 if (trace->nr_events == before) {
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002599 int timeout = done ? 100 : -1;
Namhyung Kimf15eb532012-10-05 14:02:16 +09002600
Arnaldo Carvalho de Melo46fb3c22014-09-22 14:39:48 -03002601 if (!draining && perf_evlist__poll(evlist, timeout) > 0) {
2602 if (perf_evlist__filter_pollfd(evlist, POLLERR | POLLHUP) == 0)
2603 draining = true;
2604
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002605 goto again;
Arnaldo Carvalho de Melo46fb3c22014-09-22 14:39:48 -03002606 }
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002607 } else {
2608 goto again;
Namhyung Kimf15eb532012-10-05 14:02:16 +09002609 }
2610
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002611out_disable:
Arnaldo Carvalho de Melof3b623b2015-03-02 22:21:35 -03002612 thread__zput(trace->current);
2613
Arnaldo Carvalho de Meloba209f82013-10-16 11:57:33 -03002614 perf_evlist__disable(evlist);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002615
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002616 if (!err) {
2617 if (trace->summary)
2618 trace__fprintf_thread_summary(trace, trace->output);
2619
2620 if (trace->show_tool_stats) {
2621 fprintf(trace->output, "Stats:\n "
2622 " vfs_getname : %" PRIu64 "\n"
2623 " proc_getname: %" PRIu64 "\n",
2624 trace->stats.vfs_getname,
2625 trace->stats.proc_getname);
2626 }
2627 }
David Ahernbf2575c2013-10-08 21:26:53 -06002628
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002629out_delete_evlist:
2630 perf_evlist__delete(evlist);
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002631 trace->evlist = NULL;
Arnaldo Carvalho de Melo75b757ca2013-09-24 11:04:32 -03002632 trace->live = false;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002633 return err;
Arnaldo Carvalho de Melo6ef068c2013-10-17 12:07:58 -03002634{
2635 char errbuf[BUFSIZ];
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002636
Arnaldo Carvalho de Melo2cc990b2015-01-22 11:13:43 -03002637out_error_sched_stat_runtime:
2638 debugfs__strerror_open_tp(errno, errbuf, sizeof(errbuf), "sched", "sched_stat_runtime");
2639 goto out_error;
2640
Arnaldo Carvalho de Melo801c67b2015-01-22 10:52:55 -03002641out_error_raw_syscalls:
Arnaldo Carvalho de Melo2cc990b2015-01-22 11:13:43 -03002642 debugfs__strerror_open_tp(errno, errbuf, sizeof(errbuf), "raw_syscalls", "sys_(enter|exit)");
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002643 goto out_error;
2644
Arnaldo Carvalho de Meloe09b18d2014-12-11 18:04:10 -03002645out_error_mmap:
2646 perf_evlist__strerror_mmap(evlist, errno, errbuf, sizeof(errbuf));
2647 goto out_error;
2648
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002649out_error_open:
2650 perf_evlist__strerror_open(evlist, errno, errbuf, sizeof(errbuf));
2651
2652out_error:
Arnaldo Carvalho de Melo6ef068c2013-10-17 12:07:58 -03002653 fprintf(trace->output, "%s\n", errbuf);
Ramkumar Ramachandra87f91862013-10-04 10:47:31 +05302654 goto out_delete_evlist;
Arnaldo Carvalho de Melo94ad89b2015-07-03 17:42:03 -03002655
2656out_error_apply_filters:
2657 fprintf(trace->output,
2658 "Failed to set filter \"%s\" on event %s with %d (%s)\n",
2659 evsel->filter, perf_evsel__name(evsel), errno,
2660 strerror_r(errno, errbuf, sizeof(errbuf)));
2661 goto out_delete_evlist;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002662}
Arnaldo Carvalho de Melo5ed08da2015-01-22 11:08:04 -03002663out_error_mem:
2664 fprintf(trace->output, "Not enough memory to run!\n");
2665 goto out_delete_evlist;
Arnaldo Carvalho de Melo19867b62015-07-04 12:44:59 -03002666
2667out_errno:
2668 fprintf(trace->output, "errno=%d,%s\n", errno, strerror(errno));
2669 goto out_delete_evlist;
Arnaldo Carvalho de Meloa8f23d82013-10-17 17:38:29 -03002670}
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002671
David Ahern6810fc92013-08-28 22:29:52 -06002672static int trace__replay(struct trace *trace)
2673{
2674 const struct perf_evsel_str_handler handlers[] = {
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002675 { "probe:vfs_getname", trace__vfs_getname, },
David Ahern6810fc92013-08-28 22:29:52 -06002676 };
Jiri Olsaf5fc1412013-10-15 16:27:32 +02002677 struct perf_data_file file = {
2678 .path = input_name,
2679 .mode = PERF_DATA_MODE_READ,
Yunlong Songe366a6d2015-04-02 21:47:18 +08002680 .force = trace->force,
Jiri Olsaf5fc1412013-10-15 16:27:32 +02002681 };
David Ahern6810fc92013-08-28 22:29:52 -06002682 struct perf_session *session;
Namhyung Kim003824e2013-11-12 15:25:00 +09002683 struct perf_evsel *evsel;
David Ahern6810fc92013-08-28 22:29:52 -06002684 int err = -1;
2685
2686 trace->tool.sample = trace__process_sample;
2687 trace->tool.mmap = perf_event__process_mmap;
David Ahern384c6712013-09-22 19:44:58 -06002688 trace->tool.mmap2 = perf_event__process_mmap2;
David Ahern6810fc92013-08-28 22:29:52 -06002689 trace->tool.comm = perf_event__process_comm;
2690 trace->tool.exit = perf_event__process_exit;
2691 trace->tool.fork = perf_event__process_fork;
2692 trace->tool.attr = perf_event__process_attr;
2693 trace->tool.tracing_data = perf_event__process_tracing_data;
2694 trace->tool.build_id = perf_event__process_build_id;
2695
Jiri Olsa0a8cb852014-07-06 14:18:21 +02002696 trace->tool.ordered_events = true;
David Ahern6810fc92013-08-28 22:29:52 -06002697 trace->tool.ordering_requires_timestamps = true;
2698
2699 /* add tid to output */
2700 trace->multiple_threads = true;
2701
Jiri Olsaf5fc1412013-10-15 16:27:32 +02002702 session = perf_session__new(&file, false, &trace->tool);
David Ahern6810fc92013-08-28 22:29:52 -06002703 if (session == NULL)
Taeung Song52e028342014-09-24 10:33:37 +09002704 return -1;
David Ahern6810fc92013-08-28 22:29:52 -06002705
Namhyung Kim0a7e6d12014-08-12 15:40:45 +09002706 if (symbol__init(&session->header.env) < 0)
Namhyung Kimcb2ffae2014-08-12 15:40:44 +09002707 goto out;
2708
David Ahern8fb598e2013-09-28 13:13:00 -06002709 trace->host = &session->machines.host;
2710
David Ahern6810fc92013-08-28 22:29:52 -06002711 err = perf_session__set_tracepoints_handlers(session, handlers);
2712 if (err)
2713 goto out;
2714
Namhyung Kim003824e2013-11-12 15:25:00 +09002715 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2716 "raw_syscalls:sys_enter");
David Ahern9aca7f12013-12-04 19:41:39 -07002717 /* older kernels have syscalls tp versus raw_syscalls */
2718 if (evsel == NULL)
2719 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2720 "syscalls:sys_enter");
David Ahern6810fc92013-08-28 22:29:52 -06002721
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002722 if (evsel &&
2723 (perf_evsel__init_syscall_tp(evsel, trace__sys_enter) < 0 ||
2724 perf_evsel__init_sc_tp_ptr_field(evsel, args))) {
Namhyung Kim003824e2013-11-12 15:25:00 +09002725 pr_err("Error during initialize raw_syscalls:sys_enter event\n");
2726 goto out;
2727 }
2728
2729 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2730 "raw_syscalls:sys_exit");
David Ahern9aca7f12013-12-04 19:41:39 -07002731 if (evsel == NULL)
2732 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2733 "syscalls:sys_exit");
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002734 if (evsel &&
2735 (perf_evsel__init_syscall_tp(evsel, trace__sys_exit) < 0 ||
2736 perf_evsel__init_sc_tp_uint_field(evsel, ret))) {
Namhyung Kim003824e2013-11-12 15:25:00 +09002737 pr_err("Error during initialize raw_syscalls:sys_exit event\n");
David Ahern6810fc92013-08-28 22:29:52 -06002738 goto out;
2739 }
2740
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04002741 evlist__for_each(session->evlist, evsel) {
2742 if (evsel->attr.type == PERF_TYPE_SOFTWARE &&
2743 (evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ||
2744 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MIN ||
2745 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS))
2746 evsel->handler = trace__pgfault;
2747 }
2748
David Ahernbdc89662013-08-28 22:29:53 -06002749 err = parse_target_str(trace);
2750 if (err != 0)
2751 goto out;
2752
David Ahern6810fc92013-08-28 22:29:52 -06002753 setup_pager();
2754
Arnaldo Carvalho de Melob7b61cb2015-03-03 11:58:45 -03002755 err = perf_session__process_events(session);
David Ahern6810fc92013-08-28 22:29:52 -06002756 if (err)
2757 pr_err("Failed to process events, error %d", err);
2758
David Ahernbf2575c2013-10-08 21:26:53 -06002759 else if (trace->summary)
2760 trace__fprintf_thread_summary(trace, trace->output);
2761
David Ahern6810fc92013-08-28 22:29:52 -06002762out:
2763 perf_session__delete(session);
2764
2765 return err;
2766}
2767
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002768static size_t trace__fprintf_threads_header(FILE *fp)
2769{
2770 size_t printed;
2771
Pekka Enberg99ff7152013-11-12 16:42:14 +02002772 printed = fprintf(fp, "\n Summary of events:\n\n");
David Ahernbf2575c2013-10-08 21:26:53 -06002773
2774 return printed;
2775}
2776
2777static size_t thread__dump_stats(struct thread_trace *ttrace,
2778 struct trace *trace, FILE *fp)
2779{
2780 struct stats *stats;
2781 size_t printed = 0;
2782 struct syscall *sc;
2783 struct int_node *inode = intlist__first(ttrace->syscall_stats);
2784
2785 if (inode == NULL)
2786 return 0;
2787
2788 printed += fprintf(fp, "\n");
2789
Milian Wolff834fd462015-08-06 11:24:29 +02002790 printed += fprintf(fp, " syscall calls total min avg max stddev\n");
2791 printed += fprintf(fp, " (msec) (msec) (msec) (msec) (%%)\n");
2792 printed += fprintf(fp, " --------------- -------- --------- --------- --------- --------- ------\n");
Pekka Enberg99ff7152013-11-12 16:42:14 +02002793
David Ahernbf2575c2013-10-08 21:26:53 -06002794 /* each int_node is a syscall */
2795 while (inode) {
2796 stats = inode->priv;
2797 if (stats) {
2798 double min = (double)(stats->min) / NSEC_PER_MSEC;
2799 double max = (double)(stats->max) / NSEC_PER_MSEC;
2800 double avg = avg_stats(stats);
2801 double pct;
2802 u64 n = (u64) stats->n;
2803
2804 pct = avg ? 100.0 * stddev_stats(stats)/avg : 0.0;
2805 avg /= NSEC_PER_MSEC;
2806
2807 sc = &trace->syscalls.table[inode->i];
Pekka Enberg99ff7152013-11-12 16:42:14 +02002808 printed += fprintf(fp, " %-15s", sc->name);
Milian Wolff834fd462015-08-06 11:24:29 +02002809 printed += fprintf(fp, " %8" PRIu64 " %9.3f %9.3f %9.3f",
2810 n, avg * n, min, avg);
Pekka Enberg27a778b2013-11-13 14:21:48 +02002811 printed += fprintf(fp, " %9.3f %9.2f%%\n", max, pct);
David Ahernbf2575c2013-10-08 21:26:53 -06002812 }
2813
2814 inode = intlist__next(inode);
2815 }
2816
2817 printed += fprintf(fp, "\n\n");
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002818
2819 return printed;
2820}
2821
David Ahern896cbb52013-09-28 13:12:59 -06002822/* struct used to pass data to per-thread function */
2823struct summary_data {
2824 FILE *fp;
2825 struct trace *trace;
2826 size_t printed;
2827};
2828
2829static int trace__fprintf_one_thread(struct thread *thread, void *priv)
2830{
2831 struct summary_data *data = priv;
2832 FILE *fp = data->fp;
2833 size_t printed = data->printed;
2834 struct trace *trace = data->trace;
Namhyung Kim89dceb22014-10-06 09:46:03 +09002835 struct thread_trace *ttrace = thread__priv(thread);
David Ahern896cbb52013-09-28 13:12:59 -06002836 double ratio;
2837
2838 if (ttrace == NULL)
2839 return 0;
2840
2841 ratio = (double)ttrace->nr_events / trace->nr_events * 100.0;
2842
Pekka Enberg15e65c62013-11-14 18:43:30 +02002843 printed += fprintf(fp, " %s (%d), ", thread__comm_str(thread), thread->tid);
Pekka Enberg99ff7152013-11-12 16:42:14 +02002844 printed += fprintf(fp, "%lu events, ", ttrace->nr_events);
Pekka Enberg15e65c62013-11-14 18:43:30 +02002845 printed += fprintf(fp, "%.1f%%", ratio);
Stanislav Fomicheva2ea67d2014-07-08 22:05:16 +04002846 if (ttrace->pfmaj)
2847 printed += fprintf(fp, ", %lu majfaults", ttrace->pfmaj);
2848 if (ttrace->pfmin)
2849 printed += fprintf(fp, ", %lu minfaults", ttrace->pfmin);
Pekka Enberg99ff7152013-11-12 16:42:14 +02002850 printed += fprintf(fp, ", %.3f msec\n", ttrace->runtime_ms);
David Ahernbf2575c2013-10-08 21:26:53 -06002851 printed += thread__dump_stats(ttrace, trace, fp);
David Ahern896cbb52013-09-28 13:12:59 -06002852
2853 data->printed += printed;
2854
2855 return 0;
2856}
2857
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002858static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp)
2859{
David Ahern896cbb52013-09-28 13:12:59 -06002860 struct summary_data data = {
2861 .fp = fp,
2862 .trace = trace
2863 };
2864 data.printed = trace__fprintf_threads_header(fp);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002865
David Ahern896cbb52013-09-28 13:12:59 -06002866 machine__for_each_thread(trace->host, trace__fprintf_one_thread, &data);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002867
David Ahern896cbb52013-09-28 13:12:59 -06002868 return data.printed;
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03002869}
2870
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03002871static int trace__set_duration(const struct option *opt, const char *str,
2872 int unset __maybe_unused)
2873{
2874 struct trace *trace = opt->value;
2875
2876 trace->duration_filter = atof(str);
2877 return 0;
2878}
2879
Arnaldo Carvalho de Melof078c382015-02-21 11:36:52 -08002880static int trace__set_filter_pids(const struct option *opt, const char *str,
2881 int unset __maybe_unused)
2882{
2883 int ret = -1;
2884 size_t i;
2885 struct trace *trace = opt->value;
2886 /*
2887 * FIXME: introduce a intarray class, plain parse csv and create a
2888 * { int nr, int entries[] } struct...
2889 */
2890 struct intlist *list = intlist__new(str);
2891
2892 if (list == NULL)
2893 return -1;
2894
2895 i = trace->filter_pids.nr = intlist__nr_entries(list) + 1;
2896 trace->filter_pids.entries = calloc(i, sizeof(pid_t));
2897
2898 if (trace->filter_pids.entries == NULL)
2899 goto out;
2900
2901 trace->filter_pids.entries[0] = getpid();
2902
2903 for (i = 1; i < trace->filter_pids.nr; ++i)
2904 trace->filter_pids.entries[i] = intlist__entry(list, i - 1)->i;
2905
2906 intlist__delete(list);
2907 ret = 0;
2908out:
2909 return ret;
2910}
2911
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002912static int trace__open_output(struct trace *trace, const char *filename)
2913{
2914 struct stat st;
2915
2916 if (!stat(filename, &st) && st.st_size) {
2917 char oldname[PATH_MAX];
2918
2919 scnprintf(oldname, sizeof(oldname), "%s.old", filename);
2920 unlink(oldname);
2921 rename(filename, oldname);
2922 }
2923
2924 trace->output = fopen(filename, "w");
2925
2926 return trace->output == NULL ? -errno : 0;
2927}
2928
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04002929static int parse_pagefaults(const struct option *opt, const char *str,
2930 int unset __maybe_unused)
2931{
2932 int *trace_pgfaults = opt->value;
2933
2934 if (strcmp(str, "all") == 0)
2935 *trace_pgfaults |= TRACE_PFMAJ | TRACE_PFMIN;
2936 else if (strcmp(str, "maj") == 0)
2937 *trace_pgfaults |= TRACE_PFMAJ;
2938 else if (strcmp(str, "min") == 0)
2939 *trace_pgfaults |= TRACE_PFMIN;
2940 else
2941 return -1;
2942
2943 return 0;
2944}
2945
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002946static void evlist__set_evsel_handler(struct perf_evlist *evlist, void *handler)
2947{
2948 struct perf_evsel *evsel;
2949
2950 evlist__for_each(evlist, evsel)
2951 evsel->handler = handler;
2952}
2953
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002954int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
2955{
Yunlong Song6fdd9cb2015-03-18 21:35:57 +08002956 const char *trace_usage[] = {
Namhyung Kimf15eb532012-10-05 14:02:16 +09002957 "perf trace [<options>] [<command>]",
2958 "perf trace [<options>] -- <command> [<options>]",
David Ahern5e2485b2013-09-28 13:13:01 -06002959 "perf trace record [<options>] [<command>]",
2960 "perf trace record [<options>] -- <command> [<options>]",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002961 NULL
2962 };
2963 struct trace trace = {
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002964 .audit = {
2965 .machine = audit_detect_machine(),
2966 .open_id = audit_name_to_syscall("open", trace.audit.machine),
2967 },
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002968 .syscalls = {
2969 . max = -1,
2970 },
2971 .opts = {
2972 .target = {
2973 .uid = UINT_MAX,
2974 .uses_mmap = true,
2975 },
2976 .user_freq = UINT_MAX,
2977 .user_interval = ULLONG_MAX,
Arnaldo Carvalho de Melo509051e2014-01-14 17:52:14 -03002978 .no_buffering = true,
Arnaldo Carvalho de Melo38d54472014-12-12 17:28:32 -03002979 .mmap_pages = UINT_MAX,
Kan Liang9d9cad72015-06-17 09:51:11 -04002980 .proc_map_timeout = 500,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002981 },
Milian Wolff007d66a2015-08-05 16:52:23 -03002982 .output = stderr,
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -03002983 .show_comm = true,
Stanislav Fomicheve281a962014-06-26 20:14:28 +04002984 .trace_syscalls = true,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002985 };
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002986 const char *output_name = NULL;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03002987 const char *ev_qualifier_str = NULL;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002988 const struct option trace_options[] = {
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03002989 OPT_CALLBACK(0, "event", &trace.evlist, "event",
2990 "event selector. use 'perf list' to list available events",
2991 parse_events_option),
Arnaldo Carvalho de Melo50c95cb2013-09-12 12:35:21 -03002992 OPT_BOOLEAN(0, "comm", &trace.show_comm,
2993 "show the thread COMM next to its id"),
Arnaldo Carvalho de Meloc5227392013-09-27 18:06:19 -03002994 OPT_BOOLEAN(0, "tool_stats", &trace.show_tool_stats, "show tool stats"),
Arnaldo Carvalho de Melod303e852015-04-23 12:02:07 -03002995 OPT_STRING('e', "expr", &ev_qualifier_str, "expr", "list of syscalls to trace"),
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03002996 OPT_STRING('o', "output", &output_name, "file", "output file name"),
David Ahern6810fc92013-08-28 22:29:52 -06002997 OPT_STRING('i', "input", &input_name, "file", "Analyze events in file"),
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03002998 OPT_STRING('p', "pid", &trace.opts.target.pid, "pid",
2999 "trace events on existing process id"),
David Ahernac9be8e2013-08-20 11:15:45 -06003000 OPT_STRING('t', "tid", &trace.opts.target.tid, "tid",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003001 "trace events on existing thread id"),
Arnaldo Carvalho de Melofa0e4ff2015-04-23 11:59:20 -03003002 OPT_CALLBACK(0, "filter-pids", &trace, "CSV list of pids",
3003 "pids to filter (by the kernel)", trace__set_filter_pids),
David Ahernac9be8e2013-08-20 11:15:45 -06003004 OPT_BOOLEAN('a', "all-cpus", &trace.opts.target.system_wide,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003005 "system-wide collection from all CPUs"),
David Ahernac9be8e2013-08-20 11:15:45 -06003006 OPT_STRING('C', "cpu", &trace.opts.target.cpu_list, "cpu",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003007 "list of cpus to monitor"),
David Ahern6810fc92013-08-28 22:29:52 -06003008 OPT_BOOLEAN(0, "no-inherit", &trace.opts.no_inherit,
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003009 "child tasks do not inherit counters"),
Jiri Olsa994a1f72013-09-01 12:36:12 +02003010 OPT_CALLBACK('m', "mmap-pages", &trace.opts.mmap_pages, "pages",
3011 "number of mmap data pages",
3012 perf_evlist__parse_mmap_pages),
David Ahernac9be8e2013-08-20 11:15:45 -06003013 OPT_STRING('u', "uid", &trace.opts.target.uid_str, "user",
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003014 "user to profile"),
Arnaldo Carvalho de Meloae9ed032012-10-08 09:56:00 -03003015 OPT_CALLBACK(0, "duration", &trace, "float",
3016 "show only events with duration > N.M ms",
3017 trace__set_duration),
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03003018 OPT_BOOLEAN(0, "sched", &trace.sched, "show blocking scheduler events"),
Arnaldo Carvalho de Melo7c304ee02013-08-22 16:49:54 -03003019 OPT_INCR('v', "verbose", &verbose, "be more verbose"),
David Ahern4bb09192013-09-04 12:37:43 -06003020 OPT_BOOLEAN('T', "time", &trace.full_time,
3021 "Show full timestamp, not time relative to first start"),
David Ahernfd2eaba2013-11-12 09:31:15 -07003022 OPT_BOOLEAN('s', "summary", &trace.summary_only,
3023 "Show only syscall summary with statistics"),
3024 OPT_BOOLEAN('S', "with-summary", &trace.summary,
3025 "Show all syscalls and summary with statistics"),
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04003026 OPT_CALLBACK_DEFAULT('F', "pf", &trace.trace_pgfaults, "all|maj|min",
3027 "Trace pagefaults", parse_pagefaults, "maj"),
Stanislav Fomicheve281a962014-06-26 20:14:28 +04003028 OPT_BOOLEAN(0, "syscalls", &trace.trace_syscalls, "Trace syscalls"),
Yunlong Songe366a6d2015-04-02 21:47:18 +08003029 OPT_BOOLEAN('f', "force", &trace.force, "don't complain, do it"),
Kan Liang9d9cad72015-06-17 09:51:11 -04003030 OPT_UINTEGER(0, "proc-map-timeout", &trace.opts.proc_map_timeout,
3031 "per thread proc mmap processing timeout in ms"),
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003032 OPT_END()
3033 };
Yunlong Song6fdd9cb2015-03-18 21:35:57 +08003034 const char * const trace_subcommands[] = { "record", NULL };
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003035 int err;
Namhyung Kim32caf0d2012-10-05 14:02:13 +09003036 char bf[BUFSIZ];
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003037
Arnaldo Carvalho de Melo4d08cb82015-02-24 15:35:55 -03003038 signal(SIGSEGV, sighandler_dump_stack);
3039 signal(SIGFPE, sighandler_dump_stack);
3040
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003041 trace.evlist = perf_evlist__new();
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003042
3043 if (trace.evlist == NULL) {
3044 pr_err("Not enough memory to run!\n");
He Kuangff8f6952015-05-11 12:28:36 +00003045 err = -ENOMEM;
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003046 goto out;
3047 }
3048
Yunlong Song6fdd9cb2015-03-18 21:35:57 +08003049 argc = parse_options_subcommand(argc, argv, trace_options, trace_subcommands,
3050 trace_usage, PARSE_OPT_STOP_AT_NON_OPTION);
David Ahernfd2eaba2013-11-12 09:31:15 -07003051
Stanislav Fomichev598d02c2014-06-26 20:14:25 +04003052 if (trace.trace_pgfaults) {
3053 trace.opts.sample_address = true;
3054 trace.opts.sample_time = true;
3055 }
3056
Arnaldo Carvalho de Melo14a052d2015-02-03 12:58:57 -03003057 if (trace.evlist->nr_entries > 0)
3058 evlist__set_evsel_handler(trace.evlist, trace__event_handler);
3059
Stanislav Fomichev1e28fe02014-06-26 20:14:26 +04003060 if ((argc >= 1) && (strcmp(argv[0], "record") == 0))
3061 return trace__record(&trace, argc-1, &argv[1]);
3062
3063 /* summary_only implies summary option, but don't overwrite summary if set */
3064 if (trace.summary_only)
3065 trace.summary = trace.summary_only;
3066
Arnaldo Carvalho de Melo726f3232015-02-06 10:16:45 +01003067 if (!trace.trace_syscalls && !trace.trace_pgfaults &&
3068 trace.evlist->nr_entries == 0 /* Was --events used? */) {
Stanislav Fomicheve281a962014-06-26 20:14:28 +04003069 pr_err("Please specify something to trace.\n");
3070 return -1;
3071 }
3072
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003073 if (output_name != NULL) {
3074 err = trace__open_output(&trace, output_name);
3075 if (err < 0) {
3076 perror("failed to create output file");
3077 goto out;
3078 }
3079 }
3080
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03003081 if (ev_qualifier_str != NULL) {
Arnaldo Carvalho de Melob059efd2013-08-21 12:56:21 -03003082 const char *s = ev_qualifier_str;
Arnaldo Carvalho de Melo005438a2015-07-20 12:02:09 -03003083 struct strlist_config slist_config = {
3084 .dirname = system_path(STRACE_GROUPS_DIR),
3085 };
Arnaldo Carvalho de Melob059efd2013-08-21 12:56:21 -03003086
3087 trace.not_ev_qualifier = *s == '!';
3088 if (trace.not_ev_qualifier)
3089 ++s;
Arnaldo Carvalho de Melo005438a2015-07-20 12:02:09 -03003090 trace.ev_qualifier = strlist__new(s, &slist_config);
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03003091 if (trace.ev_qualifier == NULL) {
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003092 fputs("Not enough memory to parse event qualifier",
3093 trace.output);
3094 err = -ENOMEM;
3095 goto out_close;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03003096 }
Arnaldo Carvalho de Melod0cc4392015-06-25 19:32:33 -03003097
3098 err = trace__validate_ev_qualifier(&trace);
3099 if (err)
3100 goto out_close;
Arnaldo Carvalho de Melo2ae3a312013-08-09 12:28:31 -03003101 }
3102
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003103 err = target__validate(&trace.opts.target);
Namhyung Kim32caf0d2012-10-05 14:02:13 +09003104 if (err) {
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003105 target__strerror(&trace.opts.target, err, bf, sizeof(bf));
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003106 fprintf(trace.output, "%s", bf);
3107 goto out_close;
Namhyung Kim32caf0d2012-10-05 14:02:13 +09003108 }
3109
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003110 err = target__parse_uid(&trace.opts.target);
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003111 if (err) {
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003112 target__strerror(&trace.opts.target, err, bf, sizeof(bf));
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003113 fprintf(trace.output, "%s", bf);
3114 goto out_close;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003115 }
3116
Arnaldo Carvalho de Melo602ad872013-11-12 16:46:16 -03003117 if (!argc && target__none(&trace.opts.target))
Namhyung Kimee761202012-10-05 14:02:14 +09003118 trace.opts.target.system_wide = true;
3119
David Ahern6810fc92013-08-28 22:29:52 -06003120 if (input_name)
3121 err = trace__replay(&trace);
3122 else
3123 err = trace__run(&trace, argc, argv);
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03003124
Arnaldo Carvalho de Meloc24ff992013-08-19 12:01:10 -03003125out_close:
3126 if (output_name != NULL)
3127 fclose(trace.output);
3128out:
Arnaldo Carvalho de Melo1302d882012-10-17 17:13:12 -03003129 return err;
Arnaldo Carvalho de Melo514f1c62012-09-26 20:05:56 -03003130}