~ubuntu-branches/debian/experimental/linux-tools/experimental

« back to all changes in this revision

Viewing changes to tools/perf/builtin-trace.c

  • Committer: Package Import Robot
  • Author(s): Ben Hutchings
  • Date: 2014-02-02 16:57:49 UTC
  • mfrom: (1.1.10) (0.1.21 sid)
  • Revision ID: package-import@ubuntu.com-20140202165749-tw94o9t1t0a8txk6
Tags: 3.13-1~exp2
Merge changes from sid up to 3.12.6-3

Show diffs side-by-side

added added

removed removed

Lines of Context:
10
10
#include "util/strlist.h"
11
11
#include "util/intlist.h"
12
12
#include "util/thread_map.h"
 
13
#include "util/stat.h"
13
14
 
14
15
#include <libaudit.h>
15
16
#include <stdlib.h>
 
17
#include <sys/eventfd.h>
16
18
#include <sys/mman.h>
17
19
#include <linux/futex.h>
18
20
 
33
35
# define MADV_UNMERGEABLE       13
34
36
#endif
35
37
 
 
38
struct tp_field {
 
39
        int offset;
 
40
        union {
 
41
                u64 (*integer)(struct tp_field *field, struct perf_sample *sample);
 
42
                void *(*pointer)(struct tp_field *field, struct perf_sample *sample);
 
43
        };
 
44
};
 
45
 
 
46
#define TP_UINT_FIELD(bits) \
 
47
static u64 tp_field__u##bits(struct tp_field *field, struct perf_sample *sample) \
 
48
{ \
 
49
        return *(u##bits *)(sample->raw_data + field->offset); \
 
50
}
 
51
 
 
52
TP_UINT_FIELD(8);
 
53
TP_UINT_FIELD(16);
 
54
TP_UINT_FIELD(32);
 
55
TP_UINT_FIELD(64);
 
56
 
 
57
#define TP_UINT_FIELD__SWAPPED(bits) \
 
58
static u64 tp_field__swapped_u##bits(struct tp_field *field, struct perf_sample *sample) \
 
59
{ \
 
60
        u##bits value = *(u##bits *)(sample->raw_data + field->offset); \
 
61
        return bswap_##bits(value);\
 
62
}
 
63
 
 
64
TP_UINT_FIELD__SWAPPED(16);
 
65
TP_UINT_FIELD__SWAPPED(32);
 
66
TP_UINT_FIELD__SWAPPED(64);
 
67
 
 
68
static int tp_field__init_uint(struct tp_field *field,
 
69
                               struct format_field *format_field,
 
70
                               bool needs_swap)
 
71
{
 
72
        field->offset = format_field->offset;
 
73
 
 
74
        switch (format_field->size) {
 
75
        case 1:
 
76
                field->integer = tp_field__u8;
 
77
                break;
 
78
        case 2:
 
79
                field->integer = needs_swap ? tp_field__swapped_u16 : tp_field__u16;
 
80
                break;
 
81
        case 4:
 
82
                field->integer = needs_swap ? tp_field__swapped_u32 : tp_field__u32;
 
83
                break;
 
84
        case 8:
 
85
                field->integer = needs_swap ? tp_field__swapped_u64 : tp_field__u64;
 
86
                break;
 
87
        default:
 
88
                return -1;
 
89
        }
 
90
 
 
91
        return 0;
 
92
}
 
93
 
 
94
static void *tp_field__ptr(struct tp_field *field, struct perf_sample *sample)
 
95
{
 
96
        return sample->raw_data + field->offset;
 
97
}
 
98
 
 
99
static int tp_field__init_ptr(struct tp_field *field, struct format_field *format_field)
 
100
{
 
101
        field->offset = format_field->offset;
 
102
        field->pointer = tp_field__ptr;
 
103
        return 0;
 
104
}
 
105
 
 
106
struct syscall_tp {
 
107
        struct tp_field id;
 
108
        union {
 
109
                struct tp_field args, ret;
 
110
        };
 
111
};
 
112
 
 
113
static int perf_evsel__init_tp_uint_field(struct perf_evsel *evsel,
 
114
                                          struct tp_field *field,
 
115
                                          const char *name)
 
116
{
 
117
        struct format_field *format_field = perf_evsel__field(evsel, name);
 
118
 
 
119
        if (format_field == NULL)
 
120
                return -1;
 
121
 
 
122
        return tp_field__init_uint(field, format_field, evsel->needs_swap);
 
123
}
 
124
 
 
125
#define perf_evsel__init_sc_tp_uint_field(evsel, name) \
 
126
        ({ struct syscall_tp *sc = evsel->priv;\
 
127
           perf_evsel__init_tp_uint_field(evsel, &sc->name, #name); })
 
128
 
 
129
static int perf_evsel__init_tp_ptr_field(struct perf_evsel *evsel,
 
130
                                         struct tp_field *field,
 
131
                                         const char *name)
 
132
{
 
133
        struct format_field *format_field = perf_evsel__field(evsel, name);
 
134
 
 
135
        if (format_field == NULL)
 
136
                return -1;
 
137
 
 
138
        return tp_field__init_ptr(field, format_field);
 
139
}
 
140
 
 
141
#define perf_evsel__init_sc_tp_ptr_field(evsel, name) \
 
142
        ({ struct syscall_tp *sc = evsel->priv;\
 
143
           perf_evsel__init_tp_ptr_field(evsel, &sc->name, #name); })
 
144
 
 
145
static void perf_evsel__delete_priv(struct perf_evsel *evsel)
 
146
{
 
147
        free(evsel->priv);
 
148
        evsel->priv = NULL;
 
149
        perf_evsel__delete(evsel);
 
150
}
 
151
 
 
152
static int perf_evsel__init_syscall_tp(struct perf_evsel *evsel, void *handler)
 
153
{
 
154
        evsel->priv = malloc(sizeof(struct syscall_tp));
 
155
        if (evsel->priv != NULL) {
 
156
                if (perf_evsel__init_sc_tp_uint_field(evsel, id))
 
157
                        goto out_delete;
 
158
 
 
159
                evsel->handler = handler;
 
160
                return 0;
 
161
        }
 
162
 
 
163
        return -ENOMEM;
 
164
 
 
165
out_delete:
 
166
        free(evsel->priv);
 
167
        evsel->priv = NULL;
 
168
        return -ENOENT;
 
169
}
 
170
 
 
171
static struct perf_evsel *perf_evsel__syscall_newtp(const char *direction, void *handler)
 
172
{
 
173
        struct perf_evsel *evsel = perf_evsel__newtp("raw_syscalls", direction);
 
174
 
 
175
        if (evsel) {
 
176
                if (perf_evsel__init_syscall_tp(evsel, handler))
 
177
                        goto out_delete;
 
178
        }
 
179
 
 
180
        return evsel;
 
181
 
 
182
out_delete:
 
183
        perf_evsel__delete_priv(evsel);
 
184
        return NULL;
 
185
}
 
186
 
 
187
#define perf_evsel__sc_tp_uint(evsel, name, sample) \
 
188
        ({ struct syscall_tp *fields = evsel->priv; \
 
189
           fields->name.integer(&fields->name, sample); })
 
190
 
 
191
#define perf_evsel__sc_tp_ptr(evsel, name, sample) \
 
192
        ({ struct syscall_tp *fields = evsel->priv; \
 
193
           fields->name.pointer(&fields->name, sample); })
 
194
 
 
195
static int perf_evlist__add_syscall_newtp(struct perf_evlist *evlist,
 
196
                                          void *sys_enter_handler,
 
197
                                          void *sys_exit_handler)
 
198
{
 
199
        int ret = -1;
 
200
        struct perf_evsel *sys_enter, *sys_exit;
 
201
 
 
202
        sys_enter = perf_evsel__syscall_newtp("sys_enter", sys_enter_handler);
 
203
        if (sys_enter == NULL)
 
204
                goto out;
 
205
 
 
206
        if (perf_evsel__init_sc_tp_ptr_field(sys_enter, args))
 
207
                goto out_delete_sys_enter;
 
208
 
 
209
        sys_exit = perf_evsel__syscall_newtp("sys_exit", sys_exit_handler);
 
210
        if (sys_exit == NULL)
 
211
                goto out_delete_sys_enter;
 
212
 
 
213
        if (perf_evsel__init_sc_tp_uint_field(sys_exit, ret))
 
214
                goto out_delete_sys_exit;
 
215
 
 
216
        perf_evlist__add(evlist, sys_enter);
 
217
        perf_evlist__add(evlist, sys_exit);
 
218
 
 
219
        ret = 0;
 
220
out:
 
221
        return ret;
 
222
 
 
223
out_delete_sys_exit:
 
224
        perf_evsel__delete_priv(sys_exit);
 
225
out_delete_sys_enter:
 
226
        perf_evsel__delete_priv(sys_enter);
 
227
        goto out;
 
228
}
 
229
 
 
230
 
 
231
struct syscall_arg {
 
232
        unsigned long val;
 
233
        struct thread *thread;
 
234
        struct trace  *trace;
 
235
        void          *parm;
 
236
        u8            idx;
 
237
        u8            mask;
 
238
};
 
239
 
 
240
struct strarray {
 
241
        int         offset;
 
242
        int         nr_entries;
 
243
        const char **entries;
 
244
};
 
245
 
 
246
#define DEFINE_STRARRAY(array) struct strarray strarray__##array = { \
 
247
        .nr_entries = ARRAY_SIZE(array), \
 
248
        .entries = array, \
 
249
}
 
250
 
 
251
#define DEFINE_STRARRAY_OFFSET(array, off) struct strarray strarray__##array = { \
 
252
        .offset     = off, \
 
253
        .nr_entries = ARRAY_SIZE(array), \
 
254
        .entries = array, \
 
255
}
 
256
 
 
257
static size_t __syscall_arg__scnprintf_strarray(char *bf, size_t size,
 
258
                                                const char *intfmt,
 
259
                                                struct syscall_arg *arg)
 
260
{
 
261
        struct strarray *sa = arg->parm;
 
262
        int idx = arg->val - sa->offset;
 
263
 
 
264
        if (idx < 0 || idx >= sa->nr_entries)
 
265
                return scnprintf(bf, size, intfmt, arg->val);
 
266
 
 
267
        return scnprintf(bf, size, "%s", sa->entries[idx]);
 
268
}
 
269
 
 
270
static size_t syscall_arg__scnprintf_strarray(char *bf, size_t size,
 
271
                                              struct syscall_arg *arg)
 
272
{
 
273
        return __syscall_arg__scnprintf_strarray(bf, size, "%d", arg);
 
274
}
 
275
 
 
276
#define SCA_STRARRAY syscall_arg__scnprintf_strarray
 
277
 
 
278
static size_t syscall_arg__scnprintf_strhexarray(char *bf, size_t size,
 
279
                                                 struct syscall_arg *arg)
 
280
{
 
281
        return __syscall_arg__scnprintf_strarray(bf, size, "%#x", arg);
 
282
}
 
283
 
 
284
#define SCA_STRHEXARRAY syscall_arg__scnprintf_strhexarray
 
285
 
 
286
static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
 
287
                                        struct syscall_arg *arg);
 
288
 
 
289
#define SCA_FD syscall_arg__scnprintf_fd
 
290
 
 
291
static size_t syscall_arg__scnprintf_fd_at(char *bf, size_t size,
 
292
                                           struct syscall_arg *arg)
 
293
{
 
294
        int fd = arg->val;
 
295
 
 
296
        if (fd == AT_FDCWD)
 
297
                return scnprintf(bf, size, "CWD");
 
298
 
 
299
        return syscall_arg__scnprintf_fd(bf, size, arg);
 
300
}
 
301
 
 
302
#define SCA_FDAT syscall_arg__scnprintf_fd_at
 
303
 
 
304
static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
 
305
                                              struct syscall_arg *arg);
 
306
 
 
307
#define SCA_CLOSE_FD syscall_arg__scnprintf_close_fd
 
308
 
36
309
static size_t syscall_arg__scnprintf_hex(char *bf, size_t size,
37
 
                                         unsigned long arg,
38
 
                                         u8 arg_idx __maybe_unused,
39
 
                                         u8 *arg_mask __maybe_unused)
 
310
                                         struct syscall_arg *arg)
40
311
{
41
 
        return scnprintf(bf, size, "%#lx", arg);
 
312
        return scnprintf(bf, size, "%#lx", arg->val);
42
313
}
43
314
 
44
315
#define SCA_HEX syscall_arg__scnprintf_hex
45
316
 
46
 
static size_t syscall_arg__scnprintf_whence(char *bf, size_t size,
47
 
                                            unsigned long arg,
48
 
                                            u8 arg_idx __maybe_unused,
49
 
                                            u8 *arg_mask __maybe_unused)
50
 
{
51
 
        int whence = arg;
52
 
 
53
 
        switch (whence) {
54
 
#define P_WHENCE(n) case SEEK_##n: return scnprintf(bf, size, #n)
55
 
        P_WHENCE(SET);
56
 
        P_WHENCE(CUR);
57
 
        P_WHENCE(END);
58
 
#ifdef SEEK_DATA
59
 
        P_WHENCE(DATA);
60
 
#endif
61
 
#ifdef SEEK_HOLE
62
 
        P_WHENCE(HOLE);
63
 
#endif
64
 
#undef P_WHENCE
65
 
        default: break;
66
 
        }
67
 
 
68
 
        return scnprintf(bf, size, "%#x", whence);
69
 
}
70
 
 
71
 
#define SCA_WHENCE syscall_arg__scnprintf_whence
72
 
 
73
317
static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size,
74
 
                                               unsigned long arg,
75
 
                                               u8 arg_idx __maybe_unused,
76
 
                                               u8 *arg_mask __maybe_unused)
 
318
                                               struct syscall_arg *arg)
77
319
{
78
 
        int printed = 0, prot = arg;
 
320
        int printed = 0, prot = arg->val;
79
321
 
80
322
        if (prot == PROT_NONE)
81
323
                return scnprintf(bf, size, "NONE");
104
346
#define SCA_MMAP_PROT syscall_arg__scnprintf_mmap_prot
105
347
 
106
348
static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size,
107
 
                                                unsigned long arg, u8 arg_idx __maybe_unused,
108
 
                                                u8 *arg_mask __maybe_unused)
 
349
                                                struct syscall_arg *arg)
109
350
{
110
 
        int printed = 0, flags = arg;
 
351
        int printed = 0, flags = arg->val;
111
352
 
112
353
#define P_MMAP_FLAG(n) \
113
354
        if (flags & MAP_##n) { \
148
389
#define SCA_MMAP_FLAGS syscall_arg__scnprintf_mmap_flags
149
390
 
150
391
static size_t syscall_arg__scnprintf_madvise_behavior(char *bf, size_t size,
151
 
                                                      unsigned long arg, u8 arg_idx __maybe_unused,
152
 
                                                      u8 *arg_mask __maybe_unused)
 
392
                                                      struct syscall_arg *arg)
153
393
{
154
 
        int behavior = arg;
 
394
        int behavior = arg->val;
155
395
 
156
396
        switch (behavior) {
157
397
#define P_MADV_BHV(n) case MADV_##n: return scnprintf(bf, size, #n)
190
430
 
191
431
#define SCA_MADV_BHV syscall_arg__scnprintf_madvise_behavior
192
432
 
193
 
static size_t syscall_arg__scnprintf_futex_op(char *bf, size_t size, unsigned long arg,
194
 
                                              u8 arg_idx __maybe_unused, u8 *arg_mask)
 
433
static size_t syscall_arg__scnprintf_flock(char *bf, size_t size,
 
434
                                           struct syscall_arg *arg)
 
435
{
 
436
        int printed = 0, op = arg->val;
 
437
 
 
438
        if (op == 0)
 
439
                return scnprintf(bf, size, "NONE");
 
440
#define P_CMD(cmd) \
 
441
        if ((op & LOCK_##cmd) == LOCK_##cmd) { \
 
442
                printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #cmd); \
 
443
                op &= ~LOCK_##cmd; \
 
444
        }
 
445
 
 
446
        P_CMD(SH);
 
447
        P_CMD(EX);
 
448
        P_CMD(NB);
 
449
        P_CMD(UN);
 
450
        P_CMD(MAND);
 
451
        P_CMD(RW);
 
452
        P_CMD(READ);
 
453
        P_CMD(WRITE);
 
454
#undef P_OP
 
455
 
 
456
        if (op)
 
457
                printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", op);
 
458
 
 
459
        return printed;
 
460
}
 
461
 
 
462
#define SCA_FLOCK syscall_arg__scnprintf_flock
 
463
 
 
464
static size_t syscall_arg__scnprintf_futex_op(char *bf, size_t size, struct syscall_arg *arg)
195
465
{
196
466
        enum syscall_futex_args {
197
467
                SCF_UADDR   = (1 << 0),
201
471
                SCF_UADDR2  = (1 << 4),
202
472
                SCF_VAL3    = (1 << 5),
203
473
        };
204
 
        int op = arg;
 
474
        int op = arg->val;
205
475
        int cmd = op & FUTEX_CMD_MASK;
206
476
        size_t printed = 0;
207
477
 
208
478
        switch (cmd) {
209
479
#define P_FUTEX_OP(n) case FUTEX_##n: printed = scnprintf(bf, size, #n);
210
 
        P_FUTEX_OP(WAIT);           *arg_mask |= SCF_VAL3|SCF_UADDR2;             break;
211
 
        P_FUTEX_OP(WAKE);           *arg_mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
212
 
        P_FUTEX_OP(FD);             *arg_mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
213
 
        P_FUTEX_OP(REQUEUE);        *arg_mask |= SCF_VAL3|SCF_TIMEOUT;            break;
214
 
        P_FUTEX_OP(CMP_REQUEUE);    *arg_mask |= SCF_TIMEOUT;                     break;
215
 
        P_FUTEX_OP(CMP_REQUEUE_PI); *arg_mask |= SCF_TIMEOUT;                     break;
 
480
        P_FUTEX_OP(WAIT);           arg->mask |= SCF_VAL3|SCF_UADDR2;             break;
 
481
        P_FUTEX_OP(WAKE);           arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
 
482
        P_FUTEX_OP(FD);             arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
 
483
        P_FUTEX_OP(REQUEUE);        arg->mask |= SCF_VAL3|SCF_TIMEOUT;            break;
 
484
        P_FUTEX_OP(CMP_REQUEUE);    arg->mask |= SCF_TIMEOUT;                     break;
 
485
        P_FUTEX_OP(CMP_REQUEUE_PI); arg->mask |= SCF_TIMEOUT;                     break;
216
486
        P_FUTEX_OP(WAKE_OP);                                                      break;
217
 
        P_FUTEX_OP(LOCK_PI);        *arg_mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
218
 
        P_FUTEX_OP(UNLOCK_PI);      *arg_mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
219
 
        P_FUTEX_OP(TRYLOCK_PI);     *arg_mask |= SCF_VAL3|SCF_UADDR2;             break;
220
 
        P_FUTEX_OP(WAIT_BITSET);    *arg_mask |= SCF_UADDR2;                      break;
221
 
        P_FUTEX_OP(WAKE_BITSET);    *arg_mask |= SCF_UADDR2;                      break;
 
487
        P_FUTEX_OP(LOCK_PI);        arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
 
488
        P_FUTEX_OP(UNLOCK_PI);      arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
 
489
        P_FUTEX_OP(TRYLOCK_PI);     arg->mask |= SCF_VAL3|SCF_UADDR2;             break;
 
490
        P_FUTEX_OP(WAIT_BITSET);    arg->mask |= SCF_UADDR2;                      break;
 
491
        P_FUTEX_OP(WAKE_BITSET);    arg->mask |= SCF_UADDR2;                      break;
222
492
        P_FUTEX_OP(WAIT_REQUEUE_PI);                                              break;
223
493
        default: printed = scnprintf(bf, size, "%#x", cmd);                       break;
224
494
        }
234
504
 
235
505
#define SCA_FUTEX_OP  syscall_arg__scnprintf_futex_op
236
506
 
 
507
static const char *epoll_ctl_ops[] = { "ADD", "DEL", "MOD", };
 
508
static DEFINE_STRARRAY_OFFSET(epoll_ctl_ops, 1);
 
509
 
 
510
static const char *itimers[] = { "REAL", "VIRTUAL", "PROF", };
 
511
static DEFINE_STRARRAY(itimers);
 
512
 
 
513
static const char *whences[] = { "SET", "CUR", "END",
 
514
#ifdef SEEK_DATA
 
515
"DATA",
 
516
#endif
 
517
#ifdef SEEK_HOLE
 
518
"HOLE",
 
519
#endif
 
520
};
 
521
static DEFINE_STRARRAY(whences);
 
522
 
 
523
static const char *fcntl_cmds[] = {
 
524
        "DUPFD", "GETFD", "SETFD", "GETFL", "SETFL", "GETLK", "SETLK",
 
525
        "SETLKW", "SETOWN", "GETOWN", "SETSIG", "GETSIG", "F_GETLK64",
 
526
        "F_SETLK64", "F_SETLKW64", "F_SETOWN_EX", "F_GETOWN_EX",
 
527
        "F_GETOWNER_UIDS",
 
528
};
 
529
static DEFINE_STRARRAY(fcntl_cmds);
 
530
 
 
531
static const char *rlimit_resources[] = {
 
532
        "CPU", "FSIZE", "DATA", "STACK", "CORE", "RSS", "NPROC", "NOFILE",
 
533
        "MEMLOCK", "AS", "LOCKS", "SIGPENDING", "MSGQUEUE", "NICE", "RTPRIO",
 
534
        "RTTIME",
 
535
};
 
536
static DEFINE_STRARRAY(rlimit_resources);
 
537
 
 
538
static const char *sighow[] = { "BLOCK", "UNBLOCK", "SETMASK", };
 
539
static DEFINE_STRARRAY(sighow);
 
540
 
 
541
static const char *clockid[] = {
 
542
        "REALTIME", "MONOTONIC", "PROCESS_CPUTIME_ID", "THREAD_CPUTIME_ID",
 
543
        "MONOTONIC_RAW", "REALTIME_COARSE", "MONOTONIC_COARSE",
 
544
};
 
545
static DEFINE_STRARRAY(clockid);
 
546
 
 
547
static const char *socket_families[] = {
 
548
        "UNSPEC", "LOCAL", "INET", "AX25", "IPX", "APPLETALK", "NETROM",
 
549
        "BRIDGE", "ATMPVC", "X25", "INET6", "ROSE", "DECnet", "NETBEUI",
 
550
        "SECURITY", "KEY", "NETLINK", "PACKET", "ASH", "ECONET", "ATMSVC",
 
551
        "RDS", "SNA", "IRDA", "PPPOX", "WANPIPE", "LLC", "IB", "CAN", "TIPC",
 
552
        "BLUETOOTH", "IUCV", "RXRPC", "ISDN", "PHONET", "IEEE802154", "CAIF",
 
553
        "ALG", "NFC", "VSOCK",
 
554
};
 
555
static DEFINE_STRARRAY(socket_families);
 
556
 
 
557
#ifndef SOCK_TYPE_MASK
 
558
#define SOCK_TYPE_MASK 0xf
 
559
#endif
 
560
 
 
561
static size_t syscall_arg__scnprintf_socket_type(char *bf, size_t size,
 
562
                                                      struct syscall_arg *arg)
 
563
{
 
564
        size_t printed;
 
565
        int type = arg->val,
 
566
            flags = type & ~SOCK_TYPE_MASK;
 
567
 
 
568
        type &= SOCK_TYPE_MASK;
 
569
        /*
 
570
         * Can't use a strarray, MIPS may override for ABI reasons.
 
571
         */
 
572
        switch (type) {
 
573
#define P_SK_TYPE(n) case SOCK_##n: printed = scnprintf(bf, size, #n); break;
 
574
        P_SK_TYPE(STREAM);
 
575
        P_SK_TYPE(DGRAM);
 
576
        P_SK_TYPE(RAW);
 
577
        P_SK_TYPE(RDM);
 
578
        P_SK_TYPE(SEQPACKET);
 
579
        P_SK_TYPE(DCCP);
 
580
        P_SK_TYPE(PACKET);
 
581
#undef P_SK_TYPE
 
582
        default:
 
583
                printed = scnprintf(bf, size, "%#x", type);
 
584
        }
 
585
 
 
586
#define P_SK_FLAG(n) \
 
587
        if (flags & SOCK_##n) { \
 
588
                printed += scnprintf(bf + printed, size - printed, "|%s", #n); \
 
589
                flags &= ~SOCK_##n; \
 
590
        }
 
591
 
 
592
        P_SK_FLAG(CLOEXEC);
 
593
        P_SK_FLAG(NONBLOCK);
 
594
#undef P_SK_FLAG
 
595
 
 
596
        if (flags)
 
597
                printed += scnprintf(bf + printed, size - printed, "|%#x", flags);
 
598
 
 
599
        return printed;
 
600
}
 
601
 
 
602
#define SCA_SK_TYPE syscall_arg__scnprintf_socket_type
 
603
 
 
604
#ifndef MSG_PROBE
 
605
#define MSG_PROBE            0x10
 
606
#endif
 
607
#ifndef MSG_WAITFORONE
 
608
#define MSG_WAITFORONE  0x10000
 
609
#endif
 
610
#ifndef MSG_SENDPAGE_NOTLAST
 
611
#define MSG_SENDPAGE_NOTLAST 0x20000
 
612
#endif
 
613
#ifndef MSG_FASTOPEN
 
614
#define MSG_FASTOPEN         0x20000000
 
615
#endif
 
616
 
 
617
static size_t syscall_arg__scnprintf_msg_flags(char *bf, size_t size,
 
618
                                               struct syscall_arg *arg)
 
619
{
 
620
        int printed = 0, flags = arg->val;
 
621
 
 
622
        if (flags == 0)
 
623
                return scnprintf(bf, size, "NONE");
 
624
#define P_MSG_FLAG(n) \
 
625
        if (flags & MSG_##n) { \
 
626
                printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
 
627
                flags &= ~MSG_##n; \
 
628
        }
 
629
 
 
630
        P_MSG_FLAG(OOB);
 
631
        P_MSG_FLAG(PEEK);
 
632
        P_MSG_FLAG(DONTROUTE);
 
633
        P_MSG_FLAG(TRYHARD);
 
634
        P_MSG_FLAG(CTRUNC);
 
635
        P_MSG_FLAG(PROBE);
 
636
        P_MSG_FLAG(TRUNC);
 
637
        P_MSG_FLAG(DONTWAIT);
 
638
        P_MSG_FLAG(EOR);
 
639
        P_MSG_FLAG(WAITALL);
 
640
        P_MSG_FLAG(FIN);
 
641
        P_MSG_FLAG(SYN);
 
642
        P_MSG_FLAG(CONFIRM);
 
643
        P_MSG_FLAG(RST);
 
644
        P_MSG_FLAG(ERRQUEUE);
 
645
        P_MSG_FLAG(NOSIGNAL);
 
646
        P_MSG_FLAG(MORE);
 
647
        P_MSG_FLAG(WAITFORONE);
 
648
        P_MSG_FLAG(SENDPAGE_NOTLAST);
 
649
        P_MSG_FLAG(FASTOPEN);
 
650
        P_MSG_FLAG(CMSG_CLOEXEC);
 
651
#undef P_MSG_FLAG
 
652
 
 
653
        if (flags)
 
654
                printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
 
655
 
 
656
        return printed;
 
657
}
 
658
 
 
659
#define SCA_MSG_FLAGS syscall_arg__scnprintf_msg_flags
 
660
 
 
661
static size_t syscall_arg__scnprintf_access_mode(char *bf, size_t size,
 
662
                                                 struct syscall_arg *arg)
 
663
{
 
664
        size_t printed = 0;
 
665
        int mode = arg->val;
 
666
 
 
667
        if (mode == F_OK) /* 0 */
 
668
                return scnprintf(bf, size, "F");
 
669
#define P_MODE(n) \
 
670
        if (mode & n##_OK) { \
 
671
                printed += scnprintf(bf + printed, size - printed, "%s", #n); \
 
672
                mode &= ~n##_OK; \
 
673
        }
 
674
 
 
675
        P_MODE(R);
 
676
        P_MODE(W);
 
677
        P_MODE(X);
 
678
#undef P_MODE
 
679
 
 
680
        if (mode)
 
681
                printed += scnprintf(bf + printed, size - printed, "|%#x", mode);
 
682
 
 
683
        return printed;
 
684
}
 
685
 
 
686
#define SCA_ACCMODE syscall_arg__scnprintf_access_mode
 
687
 
237
688
static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
238
 
                                               unsigned long arg,
239
 
                                               u8 arg_idx, u8 *arg_mask)
 
689
                                               struct syscall_arg *arg)
240
690
{
241
 
        int printed = 0, flags = arg;
 
691
        int printed = 0, flags = arg->val;
242
692
 
243
693
        if (!(flags & O_CREAT))
244
 
                *arg_mask |= 1 << (arg_idx + 1); /* Mask the mode parm */
 
694
                arg->mask |= 1 << (arg->idx + 1); /* Mask the mode parm */
245
695
 
246
696
        if (flags == 0)
247
697
                return scnprintf(bf, size, "RDONLY");
291
741
 
292
742
#define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags
293
743
 
 
744
static size_t syscall_arg__scnprintf_eventfd_flags(char *bf, size_t size,
 
745
                                                   struct syscall_arg *arg)
 
746
{
 
747
        int printed = 0, flags = arg->val;
 
748
 
 
749
        if (flags == 0)
 
750
                return scnprintf(bf, size, "NONE");
 
751
#define P_FLAG(n) \
 
752
        if (flags & EFD_##n) { \
 
753
                printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
 
754
                flags &= ~EFD_##n; \
 
755
        }
 
756
 
 
757
        P_FLAG(SEMAPHORE);
 
758
        P_FLAG(CLOEXEC);
 
759
        P_FLAG(NONBLOCK);
 
760
#undef P_FLAG
 
761
 
 
762
        if (flags)
 
763
                printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
 
764
 
 
765
        return printed;
 
766
}
 
767
 
 
768
#define SCA_EFD_FLAGS syscall_arg__scnprintf_eventfd_flags
 
769
 
 
770
static size_t syscall_arg__scnprintf_pipe_flags(char *bf, size_t size,
 
771
                                                struct syscall_arg *arg)
 
772
{
 
773
        int printed = 0, flags = arg->val;
 
774
 
 
775
#define P_FLAG(n) \
 
776
        if (flags & O_##n) { \
 
777
                printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
 
778
                flags &= ~O_##n; \
 
779
        }
 
780
 
 
781
        P_FLAG(CLOEXEC);
 
782
        P_FLAG(NONBLOCK);
 
783
#undef P_FLAG
 
784
 
 
785
        if (flags)
 
786
                printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
 
787
 
 
788
        return printed;
 
789
}
 
790
 
 
791
#define SCA_PIPE_FLAGS syscall_arg__scnprintf_pipe_flags
 
792
 
 
793
static size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscall_arg *arg)
 
794
{
 
795
        int sig = arg->val;
 
796
 
 
797
        switch (sig) {
 
798
#define P_SIGNUM(n) case SIG##n: return scnprintf(bf, size, #n)
 
799
        P_SIGNUM(HUP);
 
800
        P_SIGNUM(INT);
 
801
        P_SIGNUM(QUIT);
 
802
        P_SIGNUM(ILL);
 
803
        P_SIGNUM(TRAP);
 
804
        P_SIGNUM(ABRT);
 
805
        P_SIGNUM(BUS);
 
806
        P_SIGNUM(FPE);
 
807
        P_SIGNUM(KILL);
 
808
        P_SIGNUM(USR1);
 
809
        P_SIGNUM(SEGV);
 
810
        P_SIGNUM(USR2);
 
811
        P_SIGNUM(PIPE);
 
812
        P_SIGNUM(ALRM);
 
813
        P_SIGNUM(TERM);
 
814
        P_SIGNUM(STKFLT);
 
815
        P_SIGNUM(CHLD);
 
816
        P_SIGNUM(CONT);
 
817
        P_SIGNUM(STOP);
 
818
        P_SIGNUM(TSTP);
 
819
        P_SIGNUM(TTIN);
 
820
        P_SIGNUM(TTOU);
 
821
        P_SIGNUM(URG);
 
822
        P_SIGNUM(XCPU);
 
823
        P_SIGNUM(XFSZ);
 
824
        P_SIGNUM(VTALRM);
 
825
        P_SIGNUM(PROF);
 
826
        P_SIGNUM(WINCH);
 
827
        P_SIGNUM(IO);
 
828
        P_SIGNUM(PWR);
 
829
        P_SIGNUM(SYS);
 
830
        default: break;
 
831
        }
 
832
 
 
833
        return scnprintf(bf, size, "%#x", sig);
 
834
}
 
835
 
 
836
#define SCA_SIGNUM syscall_arg__scnprintf_signum
 
837
 
 
838
#define TCGETS          0x5401
 
839
 
 
840
static const char *tioctls[] = {
 
841
        "TCGETS", "TCSETS", "TCSETSW", "TCSETSF", "TCGETA", "TCSETA", "TCSETAW",
 
842
        "TCSETAF", "TCSBRK", "TCXONC", "TCFLSH", "TIOCEXCL", "TIOCNXCL",
 
843
        "TIOCSCTTY", "TIOCGPGRP", "TIOCSPGRP", "TIOCOUTQ", "TIOCSTI",
 
844
        "TIOCGWINSZ", "TIOCSWINSZ", "TIOCMGET", "TIOCMBIS", "TIOCMBIC",
 
845
        "TIOCMSET", "TIOCGSOFTCAR", "TIOCSSOFTCAR", "FIONREAD", "TIOCLINUX",
 
846
        "TIOCCONS", "TIOCGSERIAL", "TIOCSSERIAL", "TIOCPKT", "FIONBIO",
 
847
        "TIOCNOTTY", "TIOCSETD", "TIOCGETD", "TCSBRKP", [0x27] = "TIOCSBRK",
 
848
        "TIOCCBRK", "TIOCGSID", "TCGETS2", "TCSETS2", "TCSETSW2", "TCSETSF2",
 
849
        "TIOCGRS485", "TIOCSRS485", "TIOCGPTN", "TIOCSPTLCK",
 
850
        "TIOCGDEV||TCGETX", "TCSETX", "TCSETXF", "TCSETXW", "TIOCSIG",
 
851
        "TIOCVHANGUP", "TIOCGPKT", "TIOCGPTLCK", "TIOCGEXCL",
 
852
        [0x50] = "FIONCLEX", "FIOCLEX", "FIOASYNC", "TIOCSERCONFIG",
 
853
        "TIOCSERGWILD", "TIOCSERSWILD", "TIOCGLCKTRMIOS", "TIOCSLCKTRMIOS",
 
854
        "TIOCSERGSTRUCT", "TIOCSERGETLSR", "TIOCSERGETMULTI", "TIOCSERSETMULTI",
 
855
        "TIOCMIWAIT", "TIOCGICOUNT", [0x60] = "FIOQSIZE",
 
856
};
 
857
 
 
858
static DEFINE_STRARRAY_OFFSET(tioctls, 0x5401);
 
859
 
 
860
#define STRARRAY(arg, name, array) \
 
861
          .arg_scnprintf = { [arg] = SCA_STRARRAY, }, \
 
862
          .arg_parm      = { [arg] = &strarray__##array, }
 
863
 
294
864
static struct syscall_fmt {
295
865
        const char *name;
296
866
        const char *alias;
297
 
        size_t     (*arg_scnprintf[6])(char *bf, size_t size, unsigned long arg, u8 arg_idx, u8 *arg_mask);
 
867
        size_t     (*arg_scnprintf[6])(char *bf, size_t size, struct syscall_arg *arg);
 
868
        void       *arg_parm[6];
298
869
        bool       errmsg;
299
870
        bool       timeout;
300
871
        bool       hexret;
301
872
} syscall_fmts[] = {
302
 
        { .name     = "access",     .errmsg = true, },
 
873
        { .name     = "access",     .errmsg = true,
 
874
          .arg_scnprintf = { [1] = SCA_ACCMODE, /* mode */ }, },
303
875
        { .name     = "arch_prctl", .errmsg = true, .alias = "prctl", },
304
876
        { .name     = "brk",        .hexret = true,
305
877
          .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, },
306
 
        { .name     = "mmap",       .hexret = true, },
 
878
        { .name     = "clock_gettime",  .errmsg = true, STRARRAY(0, clk_id, clockid), },
 
879
        { .name     = "close",      .errmsg = true,
 
880
          .arg_scnprintf = { [0] = SCA_CLOSE_FD, /* fd */ }, }, 
307
881
        { .name     = "connect",    .errmsg = true, },
308
 
        { .name     = "fstat",      .errmsg = true, .alias = "newfstat", },
309
 
        { .name     = "fstatat",    .errmsg = true, .alias = "newfstatat", },
 
882
        { .name     = "dup",        .errmsg = true,
 
883
          .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
 
884
        { .name     = "dup2",       .errmsg = true,
 
885
          .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
 
886
        { .name     = "dup3",       .errmsg = true,
 
887
          .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
 
888
        { .name     = "epoll_ctl",  .errmsg = true, STRARRAY(1, op, epoll_ctl_ops), },
 
889
        { .name     = "eventfd2",   .errmsg = true,
 
890
          .arg_scnprintf = { [1] = SCA_EFD_FLAGS, /* flags */ }, },
 
891
        { .name     = "faccessat",  .errmsg = true,
 
892
          .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
 
893
        { .name     = "fadvise64",  .errmsg = true,
 
894
          .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
 
895
        { .name     = "fallocate",  .errmsg = true,
 
896
          .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
 
897
        { .name     = "fchdir",     .errmsg = true,
 
898
          .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
 
899
        { .name     = "fchmod",     .errmsg = true,
 
900
          .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
 
901
        { .name     = "fchmodat",   .errmsg = true,
 
902
          .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, 
 
903
        { .name     = "fchown",     .errmsg = true,
 
904
          .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
 
905
        { .name     = "fchownat",   .errmsg = true,
 
906
          .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, 
 
907
        { .name     = "fcntl",      .errmsg = true,
 
908
          .arg_scnprintf = { [0] = SCA_FD, /* fd */
 
909
                             [1] = SCA_STRARRAY, /* cmd */ },
 
910
          .arg_parm      = { [1] = &strarray__fcntl_cmds, /* cmd */ }, },
 
911
        { .name     = "fdatasync",  .errmsg = true,
 
912
          .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
 
913
        { .name     = "flock",      .errmsg = true,
 
914
          .arg_scnprintf = { [0] = SCA_FD, /* fd */
 
915
                             [1] = SCA_FLOCK, /* cmd */ }, },
 
916
        { .name     = "fsetxattr",  .errmsg = true,
 
917
          .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
 
918
        { .name     = "fstat",      .errmsg = true, .alias = "newfstat",
 
919
          .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
 
920
        { .name     = "fstatat",    .errmsg = true, .alias = "newfstatat",
 
921
          .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, 
 
922
        { .name     = "fstatfs",    .errmsg = true,
 
923
          .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
 
924
        { .name     = "fsync",    .errmsg = true,
 
925
          .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
 
926
        { .name     = "ftruncate", .errmsg = true,
 
927
          .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
310
928
        { .name     = "futex",      .errmsg = true,
311
929
          .arg_scnprintf = { [1] = SCA_FUTEX_OP, /* op */ }, },
 
930
        { .name     = "futimesat", .errmsg = true,
 
931
          .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, 
 
932
        { .name     = "getdents",   .errmsg = true,
 
933
          .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
 
934
        { .name     = "getdents64", .errmsg = true,
 
935
          .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
 
936
        { .name     = "getitimer",  .errmsg = true, STRARRAY(0, which, itimers), },
 
937
        { .name     = "getrlimit",  .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
312
938
        { .name     = "ioctl",      .errmsg = true,
313
 
          .arg_scnprintf = { [2] = SCA_HEX, /* arg */ }, },
 
939
          .arg_scnprintf = { [0] = SCA_FD, /* fd */ 
 
940
                             [1] = SCA_STRHEXARRAY, /* cmd */
 
941
                             [2] = SCA_HEX, /* arg */ },
 
942
          .arg_parm      = { [1] = &strarray__tioctls, /* cmd */ }, },
 
943
        { .name     = "kill",       .errmsg = true,
 
944
          .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
 
945
        { .name     = "linkat",     .errmsg = true,
 
946
          .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, 
314
947
        { .name     = "lseek",      .errmsg = true,
315
 
          .arg_scnprintf = { [2] = SCA_WHENCE, /* whence */ }, },
 
948
          .arg_scnprintf = { [0] = SCA_FD, /* fd */
 
949
                             [2] = SCA_STRARRAY, /* whence */ },
 
950
          .arg_parm      = { [2] = &strarray__whences, /* whence */ }, },
316
951
        { .name     = "lstat",      .errmsg = true, .alias = "newlstat", },
317
952
        { .name     = "madvise",    .errmsg = true,
318
953
          .arg_scnprintf = { [0] = SCA_HEX,      /* start */
319
954
                             [2] = SCA_MADV_BHV, /* behavior */ }, },
 
955
        { .name     = "mkdirat",    .errmsg = true,
 
956
          .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, 
 
957
        { .name     = "mknodat",    .errmsg = true,
 
958
          .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, 
 
959
        { .name     = "mlock",      .errmsg = true,
 
960
          .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
 
961
        { .name     = "mlockall",   .errmsg = true,
 
962
          .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
320
963
        { .name     = "mmap",       .hexret = true,
321
964
          .arg_scnprintf = { [0] = SCA_HEX,       /* addr */
322
965
                             [2] = SCA_MMAP_PROT, /* prot */
323
 
                             [3] = SCA_MMAP_FLAGS, /* flags */ }, },
 
966
                             [3] = SCA_MMAP_FLAGS, /* flags */
 
967
                             [4] = SCA_FD,        /* fd */ }, },
324
968
        { .name     = "mprotect",   .errmsg = true,
325
969
          .arg_scnprintf = { [0] = SCA_HEX, /* start */
326
970
                             [2] = SCA_MMAP_PROT, /* prot */ }, },
327
971
        { .name     = "mremap",     .hexret = true,
328
972
          .arg_scnprintf = { [0] = SCA_HEX, /* addr */
329
973
                             [4] = SCA_HEX, /* new_addr */ }, },
 
974
        { .name     = "munlock",    .errmsg = true,
 
975
          .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
330
976
        { .name     = "munmap",     .errmsg = true,
331
977
          .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
 
978
        { .name     = "name_to_handle_at", .errmsg = true,
 
979
          .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, 
 
980
        { .name     = "newfstatat", .errmsg = true,
 
981
          .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, 
332
982
        { .name     = "open",       .errmsg = true,
333
983
          .arg_scnprintf = { [1] = SCA_OPEN_FLAGS, /* flags */ }, },
334
984
        { .name     = "open_by_handle_at", .errmsg = true,
335
 
          .arg_scnprintf = { [2] = SCA_OPEN_FLAGS, /* flags */ }, },
 
985
          .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
 
986
                             [2] = SCA_OPEN_FLAGS, /* flags */ }, },
336
987
        { .name     = "openat",     .errmsg = true,
337
 
          .arg_scnprintf = { [2] = SCA_OPEN_FLAGS, /* flags */ }, },
 
988
          .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
 
989
                             [2] = SCA_OPEN_FLAGS, /* flags */ }, },
 
990
        { .name     = "pipe2",      .errmsg = true,
 
991
          .arg_scnprintf = { [1] = SCA_PIPE_FLAGS, /* flags */ }, },
338
992
        { .name     = "poll",       .errmsg = true, .timeout = true, },
339
993
        { .name     = "ppoll",      .errmsg = true, .timeout = true, },
340
 
        { .name     = "pread",      .errmsg = true, .alias = "pread64", },
341
 
        { .name     = "pwrite",     .errmsg = true, .alias = "pwrite64", },
342
 
        { .name     = "read",       .errmsg = true, },
343
 
        { .name     = "recvfrom",   .errmsg = true, },
 
994
        { .name     = "pread",      .errmsg = true, .alias = "pread64",
 
995
          .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
 
996
        { .name     = "preadv",     .errmsg = true, .alias = "pread",
 
997
          .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
 
998
        { .name     = "prlimit64",  .errmsg = true, STRARRAY(1, resource, rlimit_resources), },
 
999
        { .name     = "pwrite",     .errmsg = true, .alias = "pwrite64",
 
1000
          .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
 
1001
        { .name     = "pwritev",    .errmsg = true,
 
1002
          .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
 
1003
        { .name     = "read",       .errmsg = true,
 
1004
          .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
 
1005
        { .name     = "readlinkat", .errmsg = true,
 
1006
          .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, 
 
1007
        { .name     = "readv",      .errmsg = true,
 
1008
          .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
 
1009
        { .name     = "recvfrom",   .errmsg = true,
 
1010
          .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
 
1011
        { .name     = "recvmmsg",   .errmsg = true,
 
1012
          .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
 
1013
        { .name     = "recvmsg",    .errmsg = true,
 
1014
          .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, },
 
1015
        { .name     = "renameat",   .errmsg = true,
 
1016
          .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, 
 
1017
        { .name     = "rt_sigaction", .errmsg = true,
 
1018
          .arg_scnprintf = { [0] = SCA_SIGNUM, /* sig */ }, },
 
1019
        { .name     = "rt_sigprocmask",  .errmsg = true, STRARRAY(0, how, sighow), },
 
1020
        { .name     = "rt_sigqueueinfo", .errmsg = true,
 
1021
          .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
 
1022
        { .name     = "rt_tgsigqueueinfo", .errmsg = true,
 
1023
          .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
344
1024
        { .name     = "select",     .errmsg = true, .timeout = true, },
345
 
        { .name     = "socket",     .errmsg = true, },
 
1025
        { .name     = "sendmmsg",    .errmsg = true,
 
1026
          .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
 
1027
        { .name     = "sendmsg",    .errmsg = true,
 
1028
          .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, },
 
1029
        { .name     = "sendto",     .errmsg = true,
 
1030
          .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
 
1031
        { .name     = "setitimer",  .errmsg = true, STRARRAY(0, which, itimers), },
 
1032
        { .name     = "setrlimit",  .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
 
1033
        { .name     = "shutdown",   .errmsg = true,
 
1034
          .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
 
1035
        { .name     = "socket",     .errmsg = true,
 
1036
          .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
 
1037
                             [1] = SCA_SK_TYPE, /* type */ },
 
1038
          .arg_parm      = { [0] = &strarray__socket_families, /* family */ }, },
 
1039
        { .name     = "socketpair", .errmsg = true,
 
1040
          .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
 
1041
                             [1] = SCA_SK_TYPE, /* type */ },
 
1042
          .arg_parm      = { [0] = &strarray__socket_families, /* family */ }, },
346
1043
        { .name     = "stat",       .errmsg = true, .alias = "newstat", },
 
1044
        { .name     = "symlinkat",  .errmsg = true,
 
1045
          .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, 
 
1046
        { .name     = "tgkill",     .errmsg = true,
 
1047
          .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
 
1048
        { .name     = "tkill",      .errmsg = true,
 
1049
          .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
347
1050
        { .name     = "uname",      .errmsg = true, .alias = "newuname", },
 
1051
        { .name     = "unlinkat",   .errmsg = true,
 
1052
          .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
 
1053
        { .name     = "utimensat",  .errmsg = true,
 
1054
          .arg_scnprintf = { [0] = SCA_FDAT, /* dirfd */ }, },
 
1055
        { .name     = "write",      .errmsg = true,
 
1056
          .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
 
1057
        { .name     = "writev",     .errmsg = true,
 
1058
          .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
348
1059
};
349
1060
 
350
1061
static int syscall_fmt__cmp(const void *name, const void *fmtp)
364
1075
        const char          *name;
365
1076
        bool                filtered;
366
1077
        struct syscall_fmt  *fmt;
367
 
        size_t              (**arg_scnprintf)(char *bf, size_t size,
368
 
                                              unsigned long arg, u8 arg_idx, u8 *args_mask);
 
1078
        size_t              (**arg_scnprintf)(char *bf, size_t size, struct syscall_arg *arg);
 
1079
        void                **arg_parm;
369
1080
};
370
1081
 
371
1082
static size_t fprintf_duration(unsigned long t, FILE *fp)
389
1100
        unsigned long     nr_events;
390
1101
        char              *entry_str;
391
1102
        double            runtime_ms;
 
1103
        struct {
 
1104
                int       max;
 
1105
                char      **table;
 
1106
        } paths;
 
1107
 
 
1108
        struct intlist *syscall_stats;
392
1109
};
393
1110
 
394
1111
static struct thread_trace *thread_trace__new(void)
395
1112
{
396
 
        return zalloc(sizeof(struct thread_trace));
 
1113
        struct thread_trace *ttrace =  zalloc(sizeof(struct thread_trace));
 
1114
 
 
1115
        if (ttrace)
 
1116
                ttrace->paths.max = -1;
 
1117
 
 
1118
        ttrace->syscall_stats = intlist__new(NULL);
 
1119
 
 
1120
        return ttrace;
397
1121
}
398
1122
 
399
1123
static struct thread_trace *thread__trace(struct thread *thread, FILE *fp)
421
1145
 
422
1146
struct trace {
423
1147
        struct perf_tool        tool;
424
 
        int                     audit_machine;
 
1148
        struct {
 
1149
                int             machine;
 
1150
                int             open_id;
 
1151
        }                       audit;
425
1152
        struct {
426
1153
                int             max;
427
1154
                struct syscall  *table;
428
1155
        } syscalls;
429
1156
        struct perf_record_opts opts;
430
 
        struct machine          host;
 
1157
        struct machine          *host;
431
1158
        u64                     base_time;
 
1159
        bool                    full_time;
432
1160
        FILE                    *output;
433
1161
        unsigned long           nr_events;
434
1162
        struct strlist          *ev_qualifier;
435
1163
        bool                    not_ev_qualifier;
 
1164
        bool                    live;
 
1165
        const char              *last_vfs_getname;
436
1166
        struct intlist          *tid_list;
437
1167
        struct intlist          *pid_list;
438
1168
        bool                    sched;
439
1169
        bool                    multiple_threads;
 
1170
        bool                    summary;
 
1171
        bool                    summary_only;
 
1172
        bool                    show_comm;
 
1173
        bool                    show_tool_stats;
440
1174
        double                  duration_filter;
441
1175
        double                  runtime_ms;
 
1176
        struct {
 
1177
                u64             vfs_getname, proc_getname;
 
1178
        } stats;
442
1179
};
443
1180
 
 
1181
static int trace__set_fd_pathname(struct thread *thread, int fd, const char *pathname)
 
1182
{
 
1183
        struct thread_trace *ttrace = thread->priv;
 
1184
 
 
1185
        if (fd > ttrace->paths.max) {
 
1186
                char **npath = realloc(ttrace->paths.table, (fd + 1) * sizeof(char *));
 
1187
 
 
1188
                if (npath == NULL)
 
1189
                        return -1;
 
1190
 
 
1191
                if (ttrace->paths.max != -1) {
 
1192
                        memset(npath + ttrace->paths.max + 1, 0,
 
1193
                               (fd - ttrace->paths.max) * sizeof(char *));
 
1194
                } else {
 
1195
                        memset(npath, 0, (fd + 1) * sizeof(char *));
 
1196
                }
 
1197
 
 
1198
                ttrace->paths.table = npath;
 
1199
                ttrace->paths.max   = fd;
 
1200
        }
 
1201
 
 
1202
        ttrace->paths.table[fd] = strdup(pathname);
 
1203
 
 
1204
        return ttrace->paths.table[fd] != NULL ? 0 : -1;
 
1205
}
 
1206
 
 
1207
static int thread__read_fd_path(struct thread *thread, int fd)
 
1208
{
 
1209
        char linkname[PATH_MAX], pathname[PATH_MAX];
 
1210
        struct stat st;
 
1211
        int ret;
 
1212
 
 
1213
        if (thread->pid_ == thread->tid) {
 
1214
                scnprintf(linkname, sizeof(linkname),
 
1215
                          "/proc/%d/fd/%d", thread->pid_, fd);
 
1216
        } else {
 
1217
                scnprintf(linkname, sizeof(linkname),
 
1218
                          "/proc/%d/task/%d/fd/%d", thread->pid_, thread->tid, fd);
 
1219
        }
 
1220
 
 
1221
        if (lstat(linkname, &st) < 0 || st.st_size + 1 > (off_t)sizeof(pathname))
 
1222
                return -1;
 
1223
 
 
1224
        ret = readlink(linkname, pathname, sizeof(pathname));
 
1225
 
 
1226
        if (ret < 0 || ret > st.st_size)
 
1227
                return -1;
 
1228
 
 
1229
        pathname[ret] = '\0';
 
1230
        return trace__set_fd_pathname(thread, fd, pathname);
 
1231
}
 
1232
 
 
1233
static const char *thread__fd_path(struct thread *thread, int fd,
 
1234
                                   struct trace *trace)
 
1235
{
 
1236
        struct thread_trace *ttrace = thread->priv;
 
1237
 
 
1238
        if (ttrace == NULL)
 
1239
                return NULL;
 
1240
 
 
1241
        if (fd < 0)
 
1242
                return NULL;
 
1243
 
 
1244
        if ((fd > ttrace->paths.max || ttrace->paths.table[fd] == NULL))
 
1245
                if (!trace->live)
 
1246
                        return NULL;
 
1247
                ++trace->stats.proc_getname;
 
1248
                if (thread__read_fd_path(thread, fd)) {
 
1249
                        return NULL;
 
1250
        }
 
1251
 
 
1252
        return ttrace->paths.table[fd];
 
1253
}
 
1254
 
 
1255
static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
 
1256
                                        struct syscall_arg *arg)
 
1257
{
 
1258
        int fd = arg->val;
 
1259
        size_t printed = scnprintf(bf, size, "%d", fd);
 
1260
        const char *path = thread__fd_path(arg->thread, fd, arg->trace);
 
1261
 
 
1262
        if (path)
 
1263
                printed += scnprintf(bf + printed, size - printed, "<%s>", path);
 
1264
 
 
1265
        return printed;
 
1266
}
 
1267
 
 
1268
static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
 
1269
                                              struct syscall_arg *arg)
 
1270
{
 
1271
        int fd = arg->val;
 
1272
        size_t printed = syscall_arg__scnprintf_fd(bf, size, arg);
 
1273
        struct thread_trace *ttrace = arg->thread->priv;
 
1274
 
 
1275
        if (ttrace && fd >= 0 && fd <= ttrace->paths.max) {
 
1276
                free(ttrace->paths.table[fd]);
 
1277
                ttrace->paths.table[fd] = NULL;
 
1278
        }
 
1279
 
 
1280
        return printed;
 
1281
}
 
1282
 
444
1283
static bool trace__filter_duration(struct trace *trace, double t)
445
1284
{
446
1285
        return t < (trace->duration_filter * NSEC_PER_MSEC);
454
1293
}
455
1294
 
456
1295
static bool done = false;
 
1296
static bool interrupted = false;
457
1297
 
458
 
static void sig_handler(int sig __maybe_unused)
 
1298
static void sig_handler(int sig)
459
1299
{
460
1300
        done = true;
 
1301
        interrupted = sig == SIGINT;
461
1302
}
462
1303
 
463
1304
static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thread,
466
1307
        size_t printed = trace__fprintf_tstamp(trace, tstamp, fp);
467
1308
        printed += fprintf_duration(duration, fp);
468
1309
 
469
 
        if (trace->multiple_threads)
 
1310
        if (trace->multiple_threads) {
 
1311
                if (trace->show_comm)
 
1312
                        printed += fprintf(fp, "%.14s/", thread__comm_str(thread));
470
1313
                printed += fprintf(fp, "%d ", thread->tid);
 
1314
        }
471
1315
 
472
1316
        return printed;
473
1317
}
474
1318
 
475
1319
static int trace__process_event(struct trace *trace, struct machine *machine,
476
 
                                union perf_event *event)
 
1320
                                union perf_event *event, struct perf_sample *sample)
477
1321
{
478
1322
        int ret = 0;
479
1323
 
481
1325
        case PERF_RECORD_LOST:
482
1326
                color_fprintf(trace->output, PERF_COLOR_RED,
483
1327
                              "LOST %" PRIu64 " events!\n", event->lost.lost);
484
 
                ret = machine__process_lost_event(machine, event);
 
1328
                ret = machine__process_lost_event(machine, event, sample);
485
1329
        default:
486
 
                ret = machine__process_event(machine, event);
 
1330
                ret = machine__process_event(machine, event, sample);
487
1331
                break;
488
1332
        }
489
1333
 
492
1336
 
493
1337
static int trace__tool_process(struct perf_tool *tool,
494
1338
                               union perf_event *event,
495
 
                               struct perf_sample *sample __maybe_unused,
 
1339
                               struct perf_sample *sample,
496
1340
                               struct machine *machine)
497
1341
{
498
1342
        struct trace *trace = container_of(tool, struct trace, tool);
499
 
        return trace__process_event(trace, machine, event);
 
1343
        return trace__process_event(trace, machine, event, sample);
500
1344
}
501
1345
 
502
1346
static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
506
1350
        if (err)
507
1351
                return err;
508
1352
 
509
 
        machine__init(&trace->host, "", HOST_KERNEL_ID);
510
 
        machine__create_kernel_maps(&trace->host);
511
 
 
512
 
        if (perf_target__has_task(&trace->opts.target)) {
513
 
                err = perf_event__synthesize_thread_map(&trace->tool, evlist->threads,
514
 
                                                        trace__tool_process,
515
 
                                                        &trace->host);
516
 
        } else {
517
 
                err = perf_event__synthesize_threads(&trace->tool, trace__tool_process,
518
 
                                                     &trace->host);
519
 
        }
520
 
 
 
1353
        trace->host = machine__new_host();
 
1354
        if (trace->host == NULL)
 
1355
                return -ENOMEM;
 
1356
 
 
1357
        err = __machine__synthesize_threads(trace->host, &trace->tool, &trace->opts.target,
 
1358
                                            evlist->threads, trace__tool_process, false);
521
1359
        if (err)
522
1360
                symbol__exit();
523
1361
 
533
1371
        if (sc->arg_scnprintf == NULL)
534
1372
                return -1;
535
1373
 
 
1374
        if (sc->fmt)
 
1375
                sc->arg_parm = sc->fmt->arg_parm;
 
1376
 
536
1377
        for (field = sc->tp_format->format.fields->next; field; field = field->next) {
537
1378
                if (sc->fmt && sc->fmt->arg_scnprintf[idx])
538
1379
                        sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx];
548
1389
{
549
1390
        char tp_name[128];
550
1391
        struct syscall *sc;
551
 
        const char *name = audit_syscall_to_name(id, trace->audit_machine);
 
1392
        const char *name = audit_syscall_to_name(id, trace->audit.machine);
552
1393
 
553
1394
        if (name == NULL)
554
1395
                return -1;
603
1444
}
604
1445
 
605
1446
static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
606
 
                                      unsigned long *args)
 
1447
                                      unsigned long *args, struct trace *trace,
 
1448
                                      struct thread *thread)
607
1449
{
608
 
        int i = 0;
609
1450
        size_t printed = 0;
610
1451
 
611
1452
        if (sc->tp_format != NULL) {
612
1453
                struct format_field *field;
613
 
                u8 mask = 0, bit = 1;
 
1454
                u8 bit = 1;
 
1455
                struct syscall_arg arg = {
 
1456
                        .idx    = 0,
 
1457
                        .mask   = 0,
 
1458
                        .trace  = trace,
 
1459
                        .thread = thread,
 
1460
                };
614
1461
 
615
1462
                for (field = sc->tp_format->format.fields->next; field;
616
 
                     field = field->next, ++i, bit <<= 1) {
617
 
                        if (mask & bit)
 
1463
                     field = field->next, ++arg.idx, bit <<= 1) {
 
1464
                        if (arg.mask & bit)
 
1465
                                continue;
 
1466
                        /*
 
1467
                         * Suppress this argument if its value is zero and
 
1468
                         * and we don't have a string associated in an
 
1469
                         * strarray for it.
 
1470
                         */
 
1471
                        if (args[arg.idx] == 0 &&
 
1472
                            !(sc->arg_scnprintf &&
 
1473
                              sc->arg_scnprintf[arg.idx] == SCA_STRARRAY &&
 
1474
                              sc->arg_parm[arg.idx]))
618
1475
                                continue;
619
1476
 
620
1477
                        printed += scnprintf(bf + printed, size - printed,
621
1478
                                             "%s%s: ", printed ? ", " : "", field->name);
622
 
 
623
 
                        if (sc->arg_scnprintf && sc->arg_scnprintf[i]) {
624
 
                                printed += sc->arg_scnprintf[i](bf + printed, size - printed,
625
 
                                                                args[i], i, &mask);
 
1479
                        if (sc->arg_scnprintf && sc->arg_scnprintf[arg.idx]) {
 
1480
                                arg.val = args[arg.idx];
 
1481
                                if (sc->arg_parm)
 
1482
                                        arg.parm = sc->arg_parm[arg.idx];
 
1483
                                printed += sc->arg_scnprintf[arg.idx](bf + printed,
 
1484
                                                                      size - printed, &arg);
626
1485
                        } else {
627
1486
                                printed += scnprintf(bf + printed, size - printed,
628
 
                                                     "%ld", args[i]);
 
1487
                                                     "%ld", args[arg.idx]);
629
1488
                        }
630
1489
                }
631
1490
        } else {
 
1491
                int i = 0;
 
1492
 
632
1493
                while (i < 6) {
633
1494
                        printed += scnprintf(bf + printed, size - printed,
634
1495
                                             "%sarg%d: %ld",
644
1505
                                  struct perf_sample *sample);
645
1506
 
646
1507
static struct syscall *trace__syscall_info(struct trace *trace,
647
 
                                           struct perf_evsel *evsel,
648
 
                                           struct perf_sample *sample)
 
1508
                                           struct perf_evsel *evsel, int id)
649
1509
{
650
 
        int id = perf_evsel__intval(evsel, sample, "id");
651
1510
 
652
1511
        if (id < 0) {
653
1512
 
688
1547
        return NULL;
689
1548
}
690
1549
 
 
1550
static void thread__update_stats(struct thread_trace *ttrace,
 
1551
                                 int id, struct perf_sample *sample)
 
1552
{
 
1553
        struct int_node *inode;
 
1554
        struct stats *stats;
 
1555
        u64 duration = 0;
 
1556
 
 
1557
        inode = intlist__findnew(ttrace->syscall_stats, id);
 
1558
        if (inode == NULL)
 
1559
                return;
 
1560
 
 
1561
        stats = inode->priv;
 
1562
        if (stats == NULL) {
 
1563
                stats = malloc(sizeof(struct stats));
 
1564
                if (stats == NULL)
 
1565
                        return;
 
1566
                init_stats(stats);
 
1567
                inode->priv = stats;
 
1568
        }
 
1569
 
 
1570
        if (ttrace->entry_time && sample->time > ttrace->entry_time)
 
1571
                duration = sample->time - ttrace->entry_time;
 
1572
 
 
1573
        update_stats(stats, duration);
 
1574
}
 
1575
 
691
1576
static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
692
1577
                            struct perf_sample *sample)
693
1578
{
695
1580
        void *args;
696
1581
        size_t printed = 0;
697
1582
        struct thread *thread;
698
 
        struct syscall *sc = trace__syscall_info(trace, evsel, sample);
 
1583
        int id = perf_evsel__sc_tp_uint(evsel, id, sample);
 
1584
        struct syscall *sc = trace__syscall_info(trace, evsel, id);
699
1585
        struct thread_trace *ttrace;
700
1586
 
701
1587
        if (sc == NULL)
704
1590
        if (sc->filtered)
705
1591
                return 0;
706
1592
 
707
 
        thread = machine__findnew_thread(&trace->host, sample->pid,
708
 
                                         sample->tid);
 
1593
        thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
709
1594
        ttrace = thread__trace(thread, trace->output);
710
1595
        if (ttrace == NULL)
711
1596
                return -1;
712
1597
 
713
 
        args = perf_evsel__rawptr(evsel, sample, "args");
714
 
        if (args == NULL) {
715
 
                fprintf(trace->output, "Problems reading syscall arguments\n");
716
 
                return -1;
717
 
        }
718
 
 
 
1598
        args = perf_evsel__sc_tp_ptr(evsel, args, sample);
719
1599
        ttrace = thread->priv;
720
1600
 
721
1601
        if (ttrace->entry_str == NULL) {
728
1608
        msg = ttrace->entry_str;
729
1609
        printed += scnprintf(msg + printed, 1024 - printed, "%s(", sc->name);
730
1610
 
731
 
        printed += syscall__scnprintf_args(sc, msg + printed, 1024 - printed,  args);
 
1611
        printed += syscall__scnprintf_args(sc, msg + printed, 1024 - printed,
 
1612
                                           args, trace, thread);
732
1613
 
733
1614
        if (!strcmp(sc->name, "exit_group") || !strcmp(sc->name, "exit")) {
734
 
                if (!trace->duration_filter) {
 
1615
                if (!trace->duration_filter && !trace->summary_only) {
735
1616
                        trace__fprintf_entry_head(trace, thread, 1, sample->time, trace->output);
736
1617
                        fprintf(trace->output, "%-70s\n", ttrace->entry_str);
737
1618
                }
747
1628
        int ret;
748
1629
        u64 duration = 0;
749
1630
        struct thread *thread;
750
 
        struct syscall *sc = trace__syscall_info(trace, evsel, sample);
 
1631
        int id = perf_evsel__sc_tp_uint(evsel, id, sample);
 
1632
        struct syscall *sc = trace__syscall_info(trace, evsel, id);
751
1633
        struct thread_trace *ttrace;
752
1634
 
753
1635
        if (sc == NULL)
756
1638
        if (sc->filtered)
757
1639
                return 0;
758
1640
 
759
 
        thread = machine__findnew_thread(&trace->host, sample->pid,
760
 
                                         sample->tid);
 
1641
        thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
761
1642
        ttrace = thread__trace(thread, trace->output);
762
1643
        if (ttrace == NULL)
763
1644
                return -1;
764
1645
 
765
 
        ret = perf_evsel__intval(evsel, sample, "ret");
 
1646
        if (trace->summary)
 
1647
                thread__update_stats(ttrace, id, sample);
 
1648
 
 
1649
        ret = perf_evsel__sc_tp_uint(evsel, ret, sample);
 
1650
 
 
1651
        if (id == trace->audit.open_id && ret >= 0 && trace->last_vfs_getname) {
 
1652
                trace__set_fd_pathname(thread, ret, trace->last_vfs_getname);
 
1653
                trace->last_vfs_getname = NULL;
 
1654
                ++trace->stats.vfs_getname;
 
1655
        }
766
1656
 
767
1657
        ttrace = thread->priv;
768
1658
 
775
1665
        } else if (trace->duration_filter)
776
1666
                goto out;
777
1667
 
 
1668
        if (trace->summary_only)
 
1669
                goto out;
 
1670
 
778
1671
        trace__fprintf_entry_head(trace, thread, duration, sample->time, trace->output);
779
1672
 
780
1673
        if (ttrace->entry_pending) {
808
1701
        return 0;
809
1702
}
810
1703
 
 
1704
static int trace__vfs_getname(struct trace *trace, struct perf_evsel *evsel,
 
1705
                              struct perf_sample *sample)
 
1706
{
 
1707
        trace->last_vfs_getname = perf_evsel__rawptr(evsel, sample, "pathname");
 
1708
        return 0;
 
1709
}
 
1710
 
811
1711
static int trace__sched_stat_runtime(struct trace *trace, struct perf_evsel *evsel,
812
1712
                                     struct perf_sample *sample)
813
1713
{
814
1714
        u64 runtime = perf_evsel__intval(evsel, sample, "runtime");
815
1715
        double runtime_ms = (double)runtime / NSEC_PER_MSEC;
816
 
        struct thread *thread = machine__findnew_thread(&trace->host,
 
1716
        struct thread *thread = machine__findnew_thread(trace->host,
817
1717
                                                        sample->pid,
818
1718
                                                        sample->tid);
819
1719
        struct thread_trace *ttrace = thread__trace(thread, trace->output);
856
1756
        struct trace *trace = container_of(tool, struct trace, tool);
857
1757
        int err = 0;
858
1758
 
859
 
        tracepoint_handler handler = evsel->handler.func;
 
1759
        tracepoint_handler handler = evsel->handler;
860
1760
 
861
1761
        if (skip_sample(trace, sample))
862
1762
                return 0;
863
1763
 
864
 
        if (trace->base_time == 0)
 
1764
        if (!trace->full_time && trace->base_time == 0)
865
1765
                trace->base_time = sample->time;
866
1766
 
867
1767
        if (handler)
870
1770
        return err;
871
1771
}
872
1772
 
873
 
static bool
874
 
perf_session__has_tp(struct perf_session *session, const char *name)
875
 
{
876
 
        struct perf_evsel *evsel;
877
 
 
878
 
        evsel = perf_evlist__find_tracepoint_by_name(session->evlist, name);
879
 
 
880
 
        return evsel != NULL;
881
 
}
882
 
 
883
1773
static int parse_target_str(struct trace *trace)
884
1774
{
885
1775
        if (trace->opts.target.pid) {
901
1791
        return 0;
902
1792
}
903
1793
 
 
1794
static int trace__record(int argc, const char **argv)
 
1795
{
 
1796
        unsigned int rec_argc, i, j;
 
1797
        const char **rec_argv;
 
1798
        const char * const record_args[] = {
 
1799
                "record",
 
1800
                "-R",
 
1801
                "-m", "1024",
 
1802
                "-c", "1",
 
1803
                "-e", "raw_syscalls:sys_enter,raw_syscalls:sys_exit",
 
1804
        };
 
1805
 
 
1806
        rec_argc = ARRAY_SIZE(record_args) + argc;
 
1807
        rec_argv = calloc(rec_argc + 1, sizeof(char *));
 
1808
 
 
1809
        if (rec_argv == NULL)
 
1810
                return -ENOMEM;
 
1811
 
 
1812
        for (i = 0; i < ARRAY_SIZE(record_args); i++)
 
1813
                rec_argv[i] = record_args[i];
 
1814
 
 
1815
        for (j = 0; j < (unsigned int)argc; j++, i++)
 
1816
                rec_argv[i] = argv[j];
 
1817
 
 
1818
        return cmd_record(i, rec_argv, NULL);
 
1819
}
 
1820
 
 
1821
static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp);
 
1822
 
 
1823
static void perf_evlist__add_vfs_getname(struct perf_evlist *evlist)
 
1824
{
 
1825
        struct perf_evsel *evsel = perf_evsel__newtp("probe", "vfs_getname");
 
1826
        if (evsel == NULL)
 
1827
                return;
 
1828
 
 
1829
        if (perf_evsel__field(evsel, "pathname") == NULL) {
 
1830
                perf_evsel__delete(evsel);
 
1831
                return;
 
1832
        }
 
1833
 
 
1834
        evsel->handler = trace__vfs_getname;
 
1835
        perf_evlist__add(evlist, evsel);
 
1836
}
 
1837
 
904
1838
static int trace__run(struct trace *trace, int argc, const char **argv)
905
1839
{
906
1840
        struct perf_evlist *evlist = perf_evlist__new();
909
1843
        unsigned long before;
910
1844
        const bool forks = argc > 0;
911
1845
 
 
1846
        trace->live = true;
 
1847
 
912
1848
        if (evlist == NULL) {
913
1849
                fprintf(trace->output, "Not enough memory to run!\n");
914
1850
                goto out;
915
1851
        }
916
1852
 
917
 
        if (perf_evlist__add_newtp(evlist, "raw_syscalls", "sys_enter", trace__sys_enter) ||
918
 
            perf_evlist__add_newtp(evlist, "raw_syscalls", "sys_exit", trace__sys_exit)) {
919
 
                fprintf(trace->output, "Couldn't read the raw_syscalls tracepoints information!\n");
920
 
                goto out_delete_evlist;
921
 
        }
 
1853
        if (perf_evlist__add_syscall_newtp(evlist, trace__sys_enter, trace__sys_exit))
 
1854
                goto out_error_tp;
 
1855
 
 
1856
        perf_evlist__add_vfs_getname(evlist);
922
1857
 
923
1858
        if (trace->sched &&
924
 
            perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime",
925
 
                                   trace__sched_stat_runtime)) {
926
 
                fprintf(trace->output, "Couldn't read the sched_stat_runtime tracepoint information!\n");
927
 
                goto out_delete_evlist;
928
 
        }
 
1859
                perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime",
 
1860
                                trace__sched_stat_runtime))
 
1861
                goto out_error_tp;
929
1862
 
930
1863
        err = perf_evlist__create_maps(evlist, &trace->opts.target);
931
1864
        if (err < 0) {
954
1887
        }
955
1888
 
956
1889
        err = perf_evlist__open(evlist);
957
 
        if (err < 0) {
958
 
                fprintf(trace->output, "Couldn't create the events: %s\n", strerror(errno));
959
 
                goto out_delete_maps;
960
 
        }
 
1890
        if (err < 0)
 
1891
                goto out_error_open;
961
1892
 
962
1893
        err = perf_evlist__mmap(evlist, UINT_MAX, false);
963
1894
        if (err < 0) {
990
1921
                                goto next_event;
991
1922
                        }
992
1923
 
993
 
                        if (trace->base_time == 0)
 
1924
                        if (!trace->full_time && trace->base_time == 0)
994
1925
                                trace->base_time = sample.time;
995
1926
 
996
1927
                        if (type != PERF_RECORD_SAMPLE) {
997
 
                                trace__process_event(trace, &trace->host, event);
 
1928
                                trace__process_event(trace, trace->host, event, &sample);
998
1929
                                continue;
999
1930
                        }
1000
1931
 
1011
1942
                                goto next_event;
1012
1943
                        }
1013
1944
 
1014
 
                        handler = evsel->handler.func;
 
1945
                        handler = evsel->handler;
1015
1946
                        handler(trace, evsel, &sample);
1016
1947
next_event:
1017
1948
                        perf_evlist__mmap_consume(evlist, i);
1018
1949
 
1019
 
                        if (done)
1020
 
                                goto out_unmap_evlist;
 
1950
                        if (interrupted)
 
1951
                                goto out_disable;
1021
1952
                }
1022
1953
        }
1023
1954
 
1024
1955
        if (trace->nr_events == before) {
1025
 
                if (done)
1026
 
                        goto out_unmap_evlist;
1027
 
 
1028
 
                poll(evlist->pollfd, evlist->nr_fds, -1);
1029
 
        }
1030
 
 
1031
 
        if (done)
1032
 
                perf_evlist__disable(evlist);
1033
 
 
1034
 
        goto again;
1035
 
 
1036
 
out_unmap_evlist:
 
1956
                int timeout = done ? 100 : -1;
 
1957
 
 
1958
                if (poll(evlist->pollfd, evlist->nr_fds, timeout) > 0)
 
1959
                        goto again;
 
1960
        } else {
 
1961
                goto again;
 
1962
        }
 
1963
 
 
1964
out_disable:
 
1965
        perf_evlist__disable(evlist);
 
1966
 
 
1967
        if (!err) {
 
1968
                if (trace->summary)
 
1969
                        trace__fprintf_thread_summary(trace, trace->output);
 
1970
 
 
1971
                if (trace->show_tool_stats) {
 
1972
                        fprintf(trace->output, "Stats:\n "
 
1973
                                               " vfs_getname : %" PRIu64 "\n"
 
1974
                                               " proc_getname: %" PRIu64 "\n",
 
1975
                                trace->stats.vfs_getname,
 
1976
                                trace->stats.proc_getname);
 
1977
                }
 
1978
        }
 
1979
 
1037
1980
        perf_evlist__munmap(evlist);
1038
1981
out_close_evlist:
1039
1982
        perf_evlist__close(evlist);
1042
1985
out_delete_evlist:
1043
1986
        perf_evlist__delete(evlist);
1044
1987
out:
 
1988
        trace->live = false;
1045
1989
        return err;
 
1990
{
 
1991
        char errbuf[BUFSIZ];
 
1992
 
 
1993
out_error_tp:
 
1994
        perf_evlist__strerror_tp(evlist, errno, errbuf, sizeof(errbuf));
 
1995
        goto out_error;
 
1996
 
 
1997
out_error_open:
 
1998
        perf_evlist__strerror_open(evlist, errno, errbuf, sizeof(errbuf));
 
1999
 
 
2000
out_error:
 
2001
        fprintf(trace->output, "%s\n", errbuf);
 
2002
        goto out_delete_evlist;
 
2003
}
1046
2004
}
1047
2005
 
1048
2006
static int trace__replay(struct trace *trace)
1049
2007
{
1050
2008
        const struct perf_evsel_str_handler handlers[] = {
1051
 
                { "raw_syscalls:sys_enter",  trace__sys_enter, },
1052
 
                { "raw_syscalls:sys_exit",   trace__sys_exit, },
1053
 
        };
1054
 
 
 
2009
                { "probe:vfs_getname",       trace__vfs_getname, },
 
2010
        };
 
2011
        struct perf_data_file file = {
 
2012
                .path  = input_name,
 
2013
                .mode  = PERF_DATA_MODE_READ,
 
2014
        };
1055
2015
        struct perf_session *session;
 
2016
        struct perf_evsel *evsel;
1056
2017
        int err = -1;
1057
2018
 
1058
2019
        trace->tool.sample        = trace__process_sample;
1074
2035
        if (symbol__init() < 0)
1075
2036
                return -1;
1076
2037
 
1077
 
        session = perf_session__new(input_name, O_RDONLY, 0, false,
1078
 
                                    &trace->tool);
 
2038
        session = perf_session__new(&file, false, &trace->tool);
1079
2039
        if (session == NULL)
1080
2040
                return -ENOMEM;
1081
2041
 
 
2042
        trace->host = &session->machines.host;
 
2043
 
1082
2044
        err = perf_session__set_tracepoints_handlers(session, handlers);
1083
2045
        if (err)
1084
2046
                goto out;
1085
2047
 
1086
 
        if (!perf_session__has_tp(session, "raw_syscalls:sys_enter")) {
1087
 
                pr_err("Data file does not have raw_syscalls:sys_enter events\n");
1088
 
                goto out;
1089
 
        }
1090
 
 
1091
 
        if (!perf_session__has_tp(session, "raw_syscalls:sys_exit")) {
1092
 
                pr_err("Data file does not have raw_syscalls:sys_exit events\n");
 
2048
        evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
 
2049
                                                     "raw_syscalls:sys_enter");
 
2050
        if (evsel == NULL) {
 
2051
                pr_err("Data file does not have raw_syscalls:sys_enter event\n");
 
2052
                goto out;
 
2053
        }
 
2054
 
 
2055
        if (perf_evsel__init_syscall_tp(evsel, trace__sys_enter) < 0 ||
 
2056
            perf_evsel__init_sc_tp_ptr_field(evsel, args)) {
 
2057
                pr_err("Error during initialize raw_syscalls:sys_enter event\n");
 
2058
                goto out;
 
2059
        }
 
2060
 
 
2061
        evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
 
2062
                                                     "raw_syscalls:sys_exit");
 
2063
        if (evsel == NULL) {
 
2064
                pr_err("Data file does not have raw_syscalls:sys_exit event\n");
 
2065
                goto out;
 
2066
        }
 
2067
 
 
2068
        if (perf_evsel__init_syscall_tp(evsel, trace__sys_exit) < 0 ||
 
2069
            perf_evsel__init_sc_tp_uint_field(evsel, ret)) {
 
2070
                pr_err("Error during initialize raw_syscalls:sys_exit event\n");
1093
2071
                goto out;
1094
2072
        }
1095
2073
 
1103
2081
        if (err)
1104
2082
                pr_err("Failed to process events, error %d", err);
1105
2083
 
 
2084
        else if (trace->summary)
 
2085
                trace__fprintf_thread_summary(trace, trace->output);
 
2086
 
1106
2087
out:
1107
2088
        perf_session__delete(session);
1108
2089
 
1113
2094
{
1114
2095
        size_t printed;
1115
2096
 
1116
 
        printed  = fprintf(fp, "\n _____________________________________________________________________\n");
1117
 
        printed += fprintf(fp," __)    Summary of events    (__\n\n");
1118
 
        printed += fprintf(fp,"              [ task - pid ]     [ events ] [ ratio ]  [ runtime ]\n");
1119
 
        printed += fprintf(fp," _____________________________________________________________________\n\n");
1120
 
 
1121
 
        return printed;
 
2097
        printed  = fprintf(fp, "\n Summary of events:\n\n");
 
2098
 
 
2099
        return printed;
 
2100
}
 
2101
 
 
2102
static size_t thread__dump_stats(struct thread_trace *ttrace,
 
2103
                                 struct trace *trace, FILE *fp)
 
2104
{
 
2105
        struct stats *stats;
 
2106
        size_t printed = 0;
 
2107
        struct syscall *sc;
 
2108
        struct int_node *inode = intlist__first(ttrace->syscall_stats);
 
2109
 
 
2110
        if (inode == NULL)
 
2111
                return 0;
 
2112
 
 
2113
        printed += fprintf(fp, "\n");
 
2114
 
 
2115
        printed += fprintf(fp, "   syscall            calls      min       avg       max      stddev\n");
 
2116
        printed += fprintf(fp, "                               (msec)    (msec)    (msec)        (%%)\n");
 
2117
        printed += fprintf(fp, "   --------------- -------- --------- --------- ---------     ------\n");
 
2118
 
 
2119
        /* each int_node is a syscall */
 
2120
        while (inode) {
 
2121
                stats = inode->priv;
 
2122
                if (stats) {
 
2123
                        double min = (double)(stats->min) / NSEC_PER_MSEC;
 
2124
                        double max = (double)(stats->max) / NSEC_PER_MSEC;
 
2125
                        double avg = avg_stats(stats);
 
2126
                        double pct;
 
2127
                        u64 n = (u64) stats->n;
 
2128
 
 
2129
                        pct = avg ? 100.0 * stddev_stats(stats)/avg : 0.0;
 
2130
                        avg /= NSEC_PER_MSEC;
 
2131
 
 
2132
                        sc = &trace->syscalls.table[inode->i];
 
2133
                        printed += fprintf(fp, "   %-15s", sc->name);
 
2134
                        printed += fprintf(fp, " %8" PRIu64 " %9.3f %9.3f",
 
2135
                                           n, min, avg);
 
2136
                        printed += fprintf(fp, " %9.3f %9.2f%%\n", max, pct);
 
2137
                }
 
2138
 
 
2139
                inode = intlist__next(inode);
 
2140
        }
 
2141
 
 
2142
        printed += fprintf(fp, "\n\n");
 
2143
 
 
2144
        return printed;
 
2145
}
 
2146
 
 
2147
/* struct used to pass data to per-thread function */
 
2148
struct summary_data {
 
2149
        FILE *fp;
 
2150
        struct trace *trace;
 
2151
        size_t printed;
 
2152
};
 
2153
 
 
2154
static int trace__fprintf_one_thread(struct thread *thread, void *priv)
 
2155
{
 
2156
        struct summary_data *data = priv;
 
2157
        FILE *fp = data->fp;
 
2158
        size_t printed = data->printed;
 
2159
        struct trace *trace = data->trace;
 
2160
        struct thread_trace *ttrace = thread->priv;
 
2161
        const char *color;
 
2162
        double ratio;
 
2163
 
 
2164
        if (ttrace == NULL)
 
2165
                return 0;
 
2166
 
 
2167
        ratio = (double)ttrace->nr_events / trace->nr_events * 100.0;
 
2168
 
 
2169
        color = PERF_COLOR_NORMAL;
 
2170
        if (ratio > 50.0)
 
2171
                color = PERF_COLOR_RED;
 
2172
        else if (ratio > 25.0)
 
2173
                color = PERF_COLOR_GREEN;
 
2174
        else if (ratio > 5.0)
 
2175
                color = PERF_COLOR_YELLOW;
 
2176
 
 
2177
        printed += color_fprintf(fp, color, " %s (%d), ", thread__comm_str(thread), thread->tid);
 
2178
        printed += fprintf(fp, "%lu events, ", ttrace->nr_events);
 
2179
        printed += color_fprintf(fp, color, "%.1f%%", ratio);
 
2180
        printed += fprintf(fp, ", %.3f msec\n", ttrace->runtime_ms);
 
2181
        printed += thread__dump_stats(ttrace, trace, fp);
 
2182
 
 
2183
        data->printed += printed;
 
2184
 
 
2185
        return 0;
1122
2186
}
1123
2187
 
1124
2188
static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp)
1125
2189
{
1126
 
        size_t printed = trace__fprintf_threads_header(fp);
1127
 
        struct rb_node *nd;
1128
 
 
1129
 
        for (nd = rb_first(&trace->host.threads); nd; nd = rb_next(nd)) {
1130
 
                struct thread *thread = rb_entry(nd, struct thread, rb_node);
1131
 
                struct thread_trace *ttrace = thread->priv;
1132
 
                const char *color;
1133
 
                double ratio;
1134
 
 
1135
 
                if (ttrace == NULL)
1136
 
                        continue;
1137
 
 
1138
 
                ratio = (double)ttrace->nr_events / trace->nr_events * 100.0;
1139
 
 
1140
 
                color = PERF_COLOR_NORMAL;
1141
 
                if (ratio > 50.0)
1142
 
                        color = PERF_COLOR_RED;
1143
 
                else if (ratio > 25.0)
1144
 
                        color = PERF_COLOR_GREEN;
1145
 
                else if (ratio > 5.0)
1146
 
                        color = PERF_COLOR_YELLOW;
1147
 
 
1148
 
                printed += color_fprintf(fp, color, "%20s", thread->comm);
1149
 
                printed += fprintf(fp, " - %-5d :%11lu   [", thread->tid, ttrace->nr_events);
1150
 
                printed += color_fprintf(fp, color, "%5.1f%%", ratio);
1151
 
                printed += fprintf(fp, " ] %10.3f ms\n", ttrace->runtime_ms);
1152
 
        }
1153
 
 
1154
 
        return printed;
 
2190
        struct summary_data data = {
 
2191
                .fp = fp,
 
2192
                .trace = trace
 
2193
        };
 
2194
        data.printed = trace__fprintf_threads_header(fp);
 
2195
 
 
2196
        machine__for_each_thread(trace->host, trace__fprintf_one_thread, &data);
 
2197
 
 
2198
        return data.printed;
1155
2199
}
1156
2200
 
1157
2201
static int trace__set_duration(const struct option *opt, const char *str,
1185
2229
        const char * const trace_usage[] = {
1186
2230
                "perf trace [<options>] [<command>]",
1187
2231
                "perf trace [<options>] -- <command> [<options>]",
 
2232
                "perf trace record [<options>] [<command>]",
 
2233
                "perf trace record [<options>] -- <command> [<options>]",
1188
2234
                NULL
1189
2235
        };
1190
2236
        struct trace trace = {
1191
 
                .audit_machine = audit_detect_machine(),
 
2237
                .audit = {
 
2238
                        .machine = audit_detect_machine(),
 
2239
                        .open_id = audit_name_to_syscall("open", trace.audit.machine),
 
2240
                },
1192
2241
                .syscalls = {
1193
2242
                        . max = -1,
1194
2243
                },
1203
2252
                        .mmap_pages    = 1024,
1204
2253
                },
1205
2254
                .output = stdout,
 
2255
                .show_comm = true,
1206
2256
        };
1207
2257
        const char *output_name = NULL;
1208
2258
        const char *ev_qualifier_str = NULL;
1209
2259
        const struct option trace_options[] = {
 
2260
        OPT_BOOLEAN(0, "comm", &trace.show_comm,
 
2261
                    "show the thread COMM next to its id"),
 
2262
        OPT_BOOLEAN(0, "tool_stats", &trace.show_tool_stats, "show tool stats"),
1210
2263
        OPT_STRING('e', "expr", &ev_qualifier_str, "expr",
1211
2264
                    "list of events to trace"),
1212
2265
        OPT_STRING('o', "output", &output_name, "file", "output file name"),
1221
2274
                    "list of cpus to monitor"),
1222
2275
        OPT_BOOLEAN(0, "no-inherit", &trace.opts.no_inherit,
1223
2276
                    "child tasks do not inherit counters"),
1224
 
        OPT_UINTEGER('m', "mmap-pages", &trace.opts.mmap_pages,
1225
 
                     "number of mmap data pages"),
 
2277
        OPT_CALLBACK('m', "mmap-pages", &trace.opts.mmap_pages, "pages",
 
2278
                     "number of mmap data pages",
 
2279
                     perf_evlist__parse_mmap_pages),
1226
2280
        OPT_STRING('u', "uid", &trace.opts.target.uid_str, "user",
1227
2281
                   "user to profile"),
1228
2282
        OPT_CALLBACK(0, "duration", &trace, "float",
1230
2284
                     trace__set_duration),
1231
2285
        OPT_BOOLEAN(0, "sched", &trace.sched, "show blocking scheduler events"),
1232
2286
        OPT_INCR('v', "verbose", &verbose, "be more verbose"),
 
2287
        OPT_BOOLEAN('T', "time", &trace.full_time,
 
2288
                    "Show full timestamp, not time relative to first start"),
 
2289
        OPT_BOOLEAN('s', "summary", &trace.summary_only,
 
2290
                    "Show only syscall summary with statistics"),
 
2291
        OPT_BOOLEAN('S', "with-summary", &trace.summary,
 
2292
                    "Show all syscalls and summary with statistics"),
1233
2293
        OPT_END()
1234
2294
        };
1235
2295
        int err;
1236
2296
        char bf[BUFSIZ];
1237
2297
 
 
2298
        if ((argc > 1) && (strcmp(argv[1], "record") == 0))
 
2299
                return trace__record(argc-2, &argv[2]);
 
2300
 
1238
2301
        argc = parse_options(argc, argv, trace_options, trace_usage, 0);
1239
2302
 
 
2303
        /* summary_only implies summary option, but don't overwrite summary if set */
 
2304
        if (trace.summary_only)
 
2305
                trace.summary = trace.summary_only;
 
2306
 
1240
2307
        if (output_name != NULL) {
1241
2308
                err = trace__open_output(&trace, output_name);
1242
2309
                if (err < 0) {
1260
2327
                }
1261
2328
        }
1262
2329
 
1263
 
        err = perf_target__validate(&trace.opts.target);
1264
 
        if (err) {
1265
 
                perf_target__strerror(&trace.opts.target, err, bf, sizeof(bf));
1266
 
                fprintf(trace.output, "%s", bf);
1267
 
                goto out_close;
1268
 
        }
1269
 
 
1270
 
        err = perf_target__parse_uid(&trace.opts.target);
1271
 
        if (err) {
1272
 
                perf_target__strerror(&trace.opts.target, err, bf, sizeof(bf));
1273
 
                fprintf(trace.output, "%s", bf);
1274
 
                goto out_close;
1275
 
        }
1276
 
 
1277
 
        if (!argc && perf_target__none(&trace.opts.target))
 
2330
        err = target__validate(&trace.opts.target);
 
2331
        if (err) {
 
2332
                target__strerror(&trace.opts.target, err, bf, sizeof(bf));
 
2333
                fprintf(trace.output, "%s", bf);
 
2334
                goto out_close;
 
2335
        }
 
2336
 
 
2337
        err = target__parse_uid(&trace.opts.target);
 
2338
        if (err) {
 
2339
                target__strerror(&trace.opts.target, err, bf, sizeof(bf));
 
2340
                fprintf(trace.output, "%s", bf);
 
2341
                goto out_close;
 
2342
        }
 
2343
 
 
2344
        if (!argc && target__none(&trace.opts.target))
1278
2345
                trace.opts.target.system_wide = true;
1279
2346
 
1280
2347
        if (input_name)
1282
2349
        else
1283
2350
                err = trace__run(&trace, argc, argv);
1284
2351
 
1285
 
        if (trace.sched && !err)
1286
 
                trace__fprintf_thread_summary(&trace, trace.output);
1287
 
 
1288
2352
out_close:
1289
2353
        if (output_name != NULL)
1290
2354
                fclose(trace.output);