1#include "builtin.h"
2
3#include "perf.h"
4#include "util/cache.h"
5#include "util/debug.h"
6#include <subcmd/exec-cmd.h>
7#include "util/header.h"
8#include <subcmd/parse-options.h>
9#include "util/perf_regs.h"
10#include "util/session.h"
11#include "util/tool.h"
12#include "util/symbol.h"
13#include "util/thread.h"
14#include "util/trace-event.h"
15#include "util/util.h"
16#include "util/evlist.h"
17#include "util/evsel.h"
18#include "util/sort.h"
19#include "util/data.h"
20#include "util/auxtrace.h"
21#include "util/cpumap.h"
22#include "util/thread_map.h"
23#include "util/stat.h"
24#include "util/string2.h"
25#include "util/thread-stack.h"
26#include "util/time-utils.h"
27#include "print_binary.h"
28#include <linux/bitmap.h>
29#include <linux/kernel.h>
30#include <linux/stringify.h>
31#include <linux/time64.h>
32#include "asm/bug.h"
33#include "util/mem-events.h"
34#include "util/dump-insn.h"
35#include <dirent.h>
36#include <errno.h>
37#include <inttypes.h>
38#include <signal.h>
39#include <sys/param.h>
40#include <sys/types.h>
41#include <sys/stat.h>
42#include <unistd.h>
43
44#include "sane_ctype.h"
45
46static char const *script_name;
47static char const *generate_script_lang;
48static bool debug_mode;
49static u64 last_timestamp;
50static u64 nr_unordered;
51static bool no_callchain;
52static bool latency_format;
53static bool system_wide;
54static bool print_flags;
55static bool nanosecs;
56static const char *cpu_list;
57static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
58static struct perf_stat_config stat_config;
59static int max_blocks;
60
61unsigned int scripting_max_stack = PERF_MAX_STACK_DEPTH;
62
63enum perf_output_field {
64 PERF_OUTPUT_COMM = 1U << 0,
65 PERF_OUTPUT_TID = 1U << 1,
66 PERF_OUTPUT_PID = 1U << 2,
67 PERF_OUTPUT_TIME = 1U << 3,
68 PERF_OUTPUT_CPU = 1U << 4,
69 PERF_OUTPUT_EVNAME = 1U << 5,
70 PERF_OUTPUT_TRACE = 1U << 6,
71 PERF_OUTPUT_IP = 1U << 7,
72 PERF_OUTPUT_SYM = 1U << 8,
73 PERF_OUTPUT_DSO = 1U << 9,
74 PERF_OUTPUT_ADDR = 1U << 10,
75 PERF_OUTPUT_SYMOFFSET = 1U << 11,
76 PERF_OUTPUT_SRCLINE = 1U << 12,
77 PERF_OUTPUT_PERIOD = 1U << 13,
78 PERF_OUTPUT_IREGS = 1U << 14,
79 PERF_OUTPUT_BRSTACK = 1U << 15,
80 PERF_OUTPUT_BRSTACKSYM = 1U << 16,
81 PERF_OUTPUT_DATA_SRC = 1U << 17,
82 PERF_OUTPUT_WEIGHT = 1U << 18,
83 PERF_OUTPUT_CALLINDENT = 1U << 20,
84 PERF_OUTPUT_INSN = 1U << 21,
85 PERF_OUTPUT_INSNLEN = 1U << 22,
86 PERF_OUTPUT_BRSTACKINSN = 1U << 23,
87};
88
89struct output_option {
90 const char *str;
91 enum perf_output_field field;
92} all_output_options[] = {
93 {.str = "comm", .field = PERF_OUTPUT_COMM},
94 {.str = "tid", .field = PERF_OUTPUT_TID},
95 {.str = "pid", .field = PERF_OUTPUT_PID},
96 {.str = "time", .field = PERF_OUTPUT_TIME},
97 {.str = "cpu", .field = PERF_OUTPUT_CPU},
98 {.str = "event", .field = PERF_OUTPUT_EVNAME},
99 {.str = "trace", .field = PERF_OUTPUT_TRACE},
100 {.str = "ip", .field = PERF_OUTPUT_IP},
101 {.str = "sym", .field = PERF_OUTPUT_SYM},
102 {.str = "dso", .field = PERF_OUTPUT_DSO},
103 {.str = "addr", .field = PERF_OUTPUT_ADDR},
104 {.str = "symoff", .field = PERF_OUTPUT_SYMOFFSET},
105 {.str = "srcline", .field = PERF_OUTPUT_SRCLINE},
106 {.str = "period", .field = PERF_OUTPUT_PERIOD},
107 {.str = "iregs", .field = PERF_OUTPUT_IREGS},
108 {.str = "brstack", .field = PERF_OUTPUT_BRSTACK},
109 {.str = "brstacksym", .field = PERF_OUTPUT_BRSTACKSYM},
110 {.str = "data_src", .field = PERF_OUTPUT_DATA_SRC},
111 {.str = "weight", .field = PERF_OUTPUT_WEIGHT},
112 {.str = "callindent", .field = PERF_OUTPUT_CALLINDENT},
113 {.str = "insn", .field = PERF_OUTPUT_INSN},
114 {.str = "insnlen", .field = PERF_OUTPUT_INSNLEN},
115 {.str = "brstackinsn", .field = PERF_OUTPUT_BRSTACKINSN},
116};
117
118
119static struct {
120 bool user_set;
121 bool wildcard_set;
122 unsigned int print_ip_opts;
123 u64 fields;
124 u64 invalid_fields;
125} output[PERF_TYPE_MAX] = {
126
127 [PERF_TYPE_HARDWARE] = {
128 .user_set = false,
129
130 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
131 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
132 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
133 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO |
134 PERF_OUTPUT_PERIOD,
135
136 .invalid_fields = PERF_OUTPUT_TRACE,
137 },
138
139 [PERF_TYPE_SOFTWARE] = {
140 .user_set = false,
141
142 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
143 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
144 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
145 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO |
146 PERF_OUTPUT_PERIOD,
147
148 .invalid_fields = PERF_OUTPUT_TRACE,
149 },
150
151 [PERF_TYPE_TRACEPOINT] = {
152 .user_set = false,
153
154 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
155 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
156 PERF_OUTPUT_EVNAME | PERF_OUTPUT_TRACE,
157 },
158
159 [PERF_TYPE_RAW] = {
160 .user_set = false,
161
162 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
163 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
164 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
165 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO |
166 PERF_OUTPUT_PERIOD | PERF_OUTPUT_ADDR |
167 PERF_OUTPUT_DATA_SRC | PERF_OUTPUT_WEIGHT,
168
169 .invalid_fields = PERF_OUTPUT_TRACE,
170 },
171
172 [PERF_TYPE_BREAKPOINT] = {
173 .user_set = false,
174
175 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
176 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
177 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
178 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO |
179 PERF_OUTPUT_PERIOD,
180
181 .invalid_fields = PERF_OUTPUT_TRACE,
182 },
183};
184
185static bool output_set_by_user(void)
186{
187 int j;
188 for (j = 0; j < PERF_TYPE_MAX; ++j) {
189 if (output[j].user_set)
190 return true;
191 }
192 return false;
193}
194
195static const char *output_field2str(enum perf_output_field field)
196{
197 int i, imax = ARRAY_SIZE(all_output_options);
198 const char *str = "";
199
200 for (i = 0; i < imax; ++i) {
201 if (all_output_options[i].field == field) {
202 str = all_output_options[i].str;
203 break;
204 }
205 }
206 return str;
207}
208
209#define PRINT_FIELD(x) (output[attr->type].fields & PERF_OUTPUT_##x)
210
211static int perf_evsel__do_check_stype(struct perf_evsel *evsel,
212 u64 sample_type, const char *sample_msg,
213 enum perf_output_field field,
214 bool allow_user_set)
215{
216 struct perf_event_attr *attr = &evsel->attr;
217 int type = attr->type;
218 const char *evname;
219
220 if (attr->sample_type & sample_type)
221 return 0;
222
223 if (output[type].user_set) {
224 if (allow_user_set)
225 return 0;
226 evname = perf_evsel__name(evsel);
227 pr_err("Samples for '%s' event do not have %s attribute set. "
228 "Cannot print '%s' field.\n",
229 evname, sample_msg, output_field2str(field));
230 return -1;
231 }
232
233
234 output[type].fields &= ~field;
235 evname = perf_evsel__name(evsel);
236 pr_debug("Samples for '%s' event do not have %s attribute set. "
237 "Skipping '%s' field.\n",
238 evname, sample_msg, output_field2str(field));
239
240 return 0;
241}
242
243static int perf_evsel__check_stype(struct perf_evsel *evsel,
244 u64 sample_type, const char *sample_msg,
245 enum perf_output_field field)
246{
247 return perf_evsel__do_check_stype(evsel, sample_type, sample_msg, field,
248 false);
249}
250
251static int perf_evsel__check_attr(struct perf_evsel *evsel,
252 struct perf_session *session)
253{
254 struct perf_event_attr *attr = &evsel->attr;
255 bool allow_user_set;
256
257 if (perf_header__has_feat(&session->header, HEADER_STAT))
258 return 0;
259
260 allow_user_set = perf_header__has_feat(&session->header,
261 HEADER_AUXTRACE);
262
263 if (PRINT_FIELD(TRACE) &&
264 !perf_session__has_traces(session, "record -R"))
265 return -EINVAL;
266
267 if (PRINT_FIELD(IP)) {
268 if (perf_evsel__check_stype(evsel, PERF_SAMPLE_IP, "IP",
269 PERF_OUTPUT_IP))
270 return -EINVAL;
271 }
272
273 if (PRINT_FIELD(ADDR) &&
274 perf_evsel__do_check_stype(evsel, PERF_SAMPLE_ADDR, "ADDR",
275 PERF_OUTPUT_ADDR, allow_user_set))
276 return -EINVAL;
277
278 if (PRINT_FIELD(DATA_SRC) &&
279 perf_evsel__check_stype(evsel, PERF_SAMPLE_DATA_SRC, "DATA_SRC",
280 PERF_OUTPUT_DATA_SRC))
281 return -EINVAL;
282
283 if (PRINT_FIELD(WEIGHT) &&
284 perf_evsel__check_stype(evsel, PERF_SAMPLE_WEIGHT, "WEIGHT",
285 PERF_OUTPUT_WEIGHT))
286 return -EINVAL;
287
288 if (PRINT_FIELD(SYM) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) {
289 pr_err("Display of symbols requested but neither sample IP nor "
290 "sample address\nis selected. Hence, no addresses to convert "
291 "to symbols.\n");
292 return -EINVAL;
293 }
294 if (PRINT_FIELD(SYMOFFSET) && !PRINT_FIELD(SYM)) {
295 pr_err("Display of offsets requested but symbol is not"
296 "selected.\n");
297 return -EINVAL;
298 }
299 if (PRINT_FIELD(DSO) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) {
300 pr_err("Display of DSO requested but neither sample IP nor "
301 "sample address\nis selected. Hence, no addresses to convert "
302 "to DSO.\n");
303 return -EINVAL;
304 }
305 if (PRINT_FIELD(SRCLINE) && !PRINT_FIELD(IP)) {
306 pr_err("Display of source line number requested but sample IP is not\n"
307 "selected. Hence, no address to lookup the source line number.\n");
308 return -EINVAL;
309 }
310 if (PRINT_FIELD(BRSTACKINSN) &&
311 !(perf_evlist__combined_branch_type(session->evlist) &
312 PERF_SAMPLE_BRANCH_ANY)) {
313 pr_err("Display of branch stack assembler requested, but non all-branch filter set\n"
314 "Hint: run 'perf record -b ...'\n");
315 return -EINVAL;
316 }
317 if ((PRINT_FIELD(PID) || PRINT_FIELD(TID)) &&
318 perf_evsel__check_stype(evsel, PERF_SAMPLE_TID, "TID",
319 PERF_OUTPUT_TID|PERF_OUTPUT_PID))
320 return -EINVAL;
321
322 if (PRINT_FIELD(TIME) &&
323 perf_evsel__check_stype(evsel, PERF_SAMPLE_TIME, "TIME",
324 PERF_OUTPUT_TIME))
325 return -EINVAL;
326
327 if (PRINT_FIELD(CPU) &&
328 perf_evsel__do_check_stype(evsel, PERF_SAMPLE_CPU, "CPU",
329 PERF_OUTPUT_CPU, allow_user_set))
330 return -EINVAL;
331
332 if (PRINT_FIELD(PERIOD) &&
333 perf_evsel__check_stype(evsel, PERF_SAMPLE_PERIOD, "PERIOD",
334 PERF_OUTPUT_PERIOD))
335 return -EINVAL;
336
337 if (PRINT_FIELD(IREGS) &&
338 perf_evsel__check_stype(evsel, PERF_SAMPLE_REGS_INTR, "IREGS",
339 PERF_OUTPUT_IREGS))
340 return -EINVAL;
341
342 return 0;
343}
344
345static void set_print_ip_opts(struct perf_event_attr *attr)
346{
347 unsigned int type = attr->type;
348
349 output[type].print_ip_opts = 0;
350 if (PRINT_FIELD(IP))
351 output[type].print_ip_opts |= EVSEL__PRINT_IP;
352
353 if (PRINT_FIELD(SYM))
354 output[type].print_ip_opts |= EVSEL__PRINT_SYM;
355
356 if (PRINT_FIELD(DSO))
357 output[type].print_ip_opts |= EVSEL__PRINT_DSO;
358
359 if (PRINT_FIELD(SYMOFFSET))
360 output[type].print_ip_opts |= EVSEL__PRINT_SYMOFFSET;
361
362 if (PRINT_FIELD(SRCLINE))
363 output[type].print_ip_opts |= EVSEL__PRINT_SRCLINE;
364}
365
366
367
368
369
370static int perf_session__check_output_opt(struct perf_session *session)
371{
372 unsigned int j;
373 struct perf_evsel *evsel;
374
375 for (j = 0; j < PERF_TYPE_MAX; ++j) {
376 evsel = perf_session__find_first_evtype(session, j);
377
378
379
380
381
382 if (!evsel && output[j].user_set && !output[j].wildcard_set) {
383 pr_err("%s events do not exist. "
384 "Remove corresponding -f option to proceed.\n",
385 event_type(j));
386 return -1;
387 }
388
389 if (evsel && output[j].fields &&
390 perf_evsel__check_attr(evsel, session))
391 return -1;
392
393 if (evsel == NULL)
394 continue;
395
396 set_print_ip_opts(&evsel->attr);
397 }
398
399 if (!no_callchain) {
400 bool use_callchain = false;
401 bool not_pipe = false;
402
403 evlist__for_each_entry(session->evlist, evsel) {
404 not_pipe = true;
405 if (evsel->attr.sample_type & PERF_SAMPLE_CALLCHAIN) {
406 use_callchain = true;
407 break;
408 }
409 }
410 if (not_pipe && !use_callchain)
411 symbol_conf.use_callchain = false;
412 }
413
414
415
416
417
418 if (symbol_conf.use_callchain &&
419 !output[PERF_TYPE_TRACEPOINT].user_set) {
420 struct perf_event_attr *attr;
421
422 j = PERF_TYPE_TRACEPOINT;
423
424 evlist__for_each_entry(session->evlist, evsel) {
425 if (evsel->attr.type != j)
426 continue;
427
428 attr = &evsel->attr;
429
430 if (attr->sample_type & PERF_SAMPLE_CALLCHAIN) {
431 output[j].fields |= PERF_OUTPUT_IP;
432 output[j].fields |= PERF_OUTPUT_SYM;
433 output[j].fields |= PERF_OUTPUT_DSO;
434 set_print_ip_opts(attr);
435 goto out;
436 }
437 }
438 }
439
440out:
441 return 0;
442}
443
444static void print_sample_iregs(struct perf_sample *sample,
445 struct perf_event_attr *attr)
446{
447 struct regs_dump *regs = &sample->intr_regs;
448 uint64_t mask = attr->sample_regs_intr;
449 unsigned i = 0, r;
450
451 if (!regs)
452 return;
453
454 for_each_set_bit(r, (unsigned long *) &mask, sizeof(mask) * 8) {
455 u64 val = regs->regs[i++];
456 printf("%5s:0x%"PRIx64" ", perf_reg_name(r), val);
457 }
458}
459
460static void print_sample_start(struct perf_sample *sample,
461 struct thread *thread,
462 struct perf_evsel *evsel)
463{
464 struct perf_event_attr *attr = &evsel->attr;
465 unsigned long secs;
466 unsigned long long nsecs;
467
468 if (PRINT_FIELD(COMM)) {
469 if (latency_format)
470 printf("%8.8s ", thread__comm_str(thread));
471 else if (PRINT_FIELD(IP) && symbol_conf.use_callchain)
472 printf("%s ", thread__comm_str(thread));
473 else
474 printf("%16s ", thread__comm_str(thread));
475 }
476
477 if (PRINT_FIELD(PID) && PRINT_FIELD(TID))
478 printf("%5d/%-5d ", sample->pid, sample->tid);
479 else if (PRINT_FIELD(PID))
480 printf("%5d ", sample->pid);
481 else if (PRINT_FIELD(TID))
482 printf("%5d ", sample->tid);
483
484 if (PRINT_FIELD(CPU)) {
485 if (latency_format)
486 printf("%3d ", sample->cpu);
487 else
488 printf("[%03d] ", sample->cpu);
489 }
490
491 if (PRINT_FIELD(TIME)) {
492 nsecs = sample->time;
493 secs = nsecs / NSEC_PER_SEC;
494 nsecs -= secs * NSEC_PER_SEC;
495
496 if (nanosecs)
497 printf("%5lu.%09llu: ", secs, nsecs);
498 else {
499 char sample_time[32];
500 timestamp__scnprintf_usec(sample->time, sample_time, sizeof(sample_time));
501 printf("%12s: ", sample_time);
502 }
503 }
504}
505
506static inline char
507mispred_str(struct branch_entry *br)
508{
509 if (!(br->flags.mispred || br->flags.predicted))
510 return '-';
511
512 return br->flags.predicted ? 'P' : 'M';
513}
514
515static void print_sample_brstack(struct perf_sample *sample)
516{
517 struct branch_stack *br = sample->branch_stack;
518 u64 i;
519
520 if (!(br && br->nr))
521 return;
522
523 for (i = 0; i < br->nr; i++) {
524 printf(" 0x%"PRIx64"/0x%"PRIx64"/%c/%c/%c/%d ",
525 br->entries[i].from,
526 br->entries[i].to,
527 mispred_str( br->entries + i),
528 br->entries[i].flags.in_tx? 'X' : '-',
529 br->entries[i].flags.abort? 'A' : '-',
530 br->entries[i].flags.cycles);
531 }
532}
533
534static void print_sample_brstacksym(struct perf_sample *sample,
535 struct thread *thread)
536{
537 struct branch_stack *br = sample->branch_stack;
538 struct addr_location alf, alt;
539 u64 i, from, to;
540
541 if (!(br && br->nr))
542 return;
543
544 for (i = 0; i < br->nr; i++) {
545
546 memset(&alf, 0, sizeof(alf));
547 memset(&alt, 0, sizeof(alt));
548 from = br->entries[i].from;
549 to = br->entries[i].to;
550
551 thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, from, &alf);
552 if (alf.map)
553 alf.sym = map__find_symbol(alf.map, alf.addr);
554
555 thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, to, &alt);
556 if (alt.map)
557 alt.sym = map__find_symbol(alt.map, alt.addr);
558
559 symbol__fprintf_symname_offs(alf.sym, &alf, stdout);
560 putchar('/');
561 symbol__fprintf_symname_offs(alt.sym, &alt, stdout);
562 printf("/%c/%c/%c/%d ",
563 mispred_str( br->entries + i),
564 br->entries[i].flags.in_tx? 'X' : '-',
565 br->entries[i].flags.abort? 'A' : '-',
566 br->entries[i].flags.cycles);
567 }
568}
569
570#define MAXBB 16384UL
571
572static int grab_bb(u8 *buffer, u64 start, u64 end,
573 struct machine *machine, struct thread *thread,
574 bool *is64bit, u8 *cpumode, bool last)
575{
576 long offset, len;
577 struct addr_location al;
578 bool kernel;
579
580 if (!start || !end)
581 return 0;
582
583 kernel = machine__kernel_ip(machine, start);
584 if (kernel)
585 *cpumode = PERF_RECORD_MISC_KERNEL;
586 else
587 *cpumode = PERF_RECORD_MISC_USER;
588
589
590
591
592
593
594
595 if (kernel != machine__kernel_ip(machine, end)) {
596 printf("\tblock %" PRIx64 "-%" PRIx64 " transfers between kernel and user\n",
597 start, end);
598 return -ENXIO;
599 }
600
601 memset(&al, 0, sizeof(al));
602 if (end - start > MAXBB - MAXINSN) {
603 if (last)
604 printf("\tbrstack does not reach to final jump (%" PRIx64 "-%" PRIx64 ")\n", start, end);
605 else
606 printf("\tblock %" PRIx64 "-%" PRIx64 " (%" PRIu64 ") too long to dump\n", start, end, end - start);
607 return 0;
608 }
609
610 thread__find_addr_map(thread, *cpumode, MAP__FUNCTION, start, &al);
611 if (!al.map || !al.map->dso) {
612 printf("\tcannot resolve %" PRIx64 "-%" PRIx64 "\n", start, end);
613 return 0;
614 }
615 if (al.map->dso->data.status == DSO_DATA_STATUS_ERROR) {
616 printf("\tcannot resolve %" PRIx64 "-%" PRIx64 "\n", start, end);
617 return 0;
618 }
619
620
621 map__load(al.map);
622
623 offset = al.map->map_ip(al.map, start);
624 len = dso__data_read_offset(al.map->dso, machine, offset, (u8 *)buffer,
625 end - start + MAXINSN);
626
627 *is64bit = al.map->dso->is_64_bit;
628 if (len <= 0)
629 printf("\tcannot fetch code for block at %" PRIx64 "-%" PRIx64 "\n",
630 start, end);
631 return len;
632}
633
634static void print_jump(uint64_t ip, struct branch_entry *en,
635 struct perf_insn *x, u8 *inbuf, int len,
636 int insn)
637{
638 printf("\t%016" PRIx64 "\t%-30s\t#%s%s%s%s",
639 ip,
640 dump_insn(x, ip, inbuf, len, NULL),
641 en->flags.predicted ? " PRED" : "",
642 en->flags.mispred ? " MISPRED" : "",
643 en->flags.in_tx ? " INTX" : "",
644 en->flags.abort ? " ABORT" : "");
645 if (en->flags.cycles) {
646 printf(" %d cycles", en->flags.cycles);
647 if (insn)
648 printf(" %.2f IPC", (float)insn / en->flags.cycles);
649 }
650 putchar('\n');
651}
652
653static void print_ip_sym(struct thread *thread, u8 cpumode, int cpu,
654 uint64_t addr, struct symbol **lastsym,
655 struct perf_event_attr *attr)
656{
657 struct addr_location al;
658 int off;
659
660 memset(&al, 0, sizeof(al));
661
662 thread__find_addr_map(thread, cpumode, MAP__FUNCTION, addr, &al);
663 if (!al.map)
664 thread__find_addr_map(thread, cpumode, MAP__VARIABLE,
665 addr, &al);
666 if ((*lastsym) && al.addr >= (*lastsym)->start && al.addr < (*lastsym)->end)
667 return;
668
669 al.cpu = cpu;
670 al.sym = NULL;
671 if (al.map)
672 al.sym = map__find_symbol(al.map, al.addr);
673
674 if (!al.sym)
675 return;
676
677 if (al.addr < al.sym->end)
678 off = al.addr - al.sym->start;
679 else
680 off = al.addr - al.map->start - al.sym->start;
681 printf("\t%s", al.sym->name);
682 if (off)
683 printf("%+d", off);
684 putchar(':');
685 if (PRINT_FIELD(SRCLINE))
686 map__fprintf_srcline(al.map, al.addr, "\t", stdout);
687 putchar('\n');
688 *lastsym = al.sym;
689}
690
691static void print_sample_brstackinsn(struct perf_sample *sample,
692 struct thread *thread,
693 struct perf_event_attr *attr,
694 struct machine *machine)
695{
696 struct branch_stack *br = sample->branch_stack;
697 u64 start, end;
698 int i, insn, len, nr, ilen;
699 struct perf_insn x;
700 u8 buffer[MAXBB];
701 unsigned off;
702 struct symbol *lastsym = NULL;
703
704 if (!(br && br->nr))
705 return;
706 nr = br->nr;
707 if (max_blocks && nr > max_blocks + 1)
708 nr = max_blocks + 1;
709
710 x.thread = thread;
711 x.cpu = sample->cpu;
712
713 putchar('\n');
714
715
716 len = grab_bb(buffer, br->entries[nr-1].from,
717 br->entries[nr-1].from,
718 machine, thread, &x.is64bit, &x.cpumode, false);
719 if (len > 0) {
720 print_ip_sym(thread, x.cpumode, x.cpu,
721 br->entries[nr - 1].from, &lastsym, attr);
722 print_jump(br->entries[nr - 1].from, &br->entries[nr - 1],
723 &x, buffer, len, 0);
724 }
725
726
727 for (i = nr - 2; i >= 0; i--) {
728 if (br->entries[i].from || br->entries[i].to)
729 pr_debug("%d: %" PRIx64 "-%" PRIx64 "\n", i,
730 br->entries[i].from,
731 br->entries[i].to);
732 start = br->entries[i + 1].to;
733 end = br->entries[i].from;
734
735 len = grab_bb(buffer, start, end, machine, thread, &x.is64bit, &x.cpumode, false);
736
737 if (len == -ENXIO && i > 0) {
738 end = br->entries[--i].from;
739 pr_debug("\tpatching up to %" PRIx64 "-%" PRIx64 "\n", start, end);
740 len = grab_bb(buffer, start, end, machine, thread, &x.is64bit, &x.cpumode, false);
741 }
742 if (len <= 0)
743 continue;
744
745 insn = 0;
746 for (off = 0;; off += ilen) {
747 uint64_t ip = start + off;
748
749 print_ip_sym(thread, x.cpumode, x.cpu, ip, &lastsym, attr);
750 if (ip == end) {
751 print_jump(ip, &br->entries[i], &x, buffer + off, len - off, insn);
752 break;
753 } else {
754 printf("\t%016" PRIx64 "\t%s\n", ip,
755 dump_insn(&x, ip, buffer + off, len - off, &ilen));
756 if (ilen == 0)
757 break;
758 insn++;
759 }
760 }
761 }
762
763
764
765
766
767 if (br->entries[0].from == sample->ip)
768 return;
769 if (br->entries[0].flags.abort)
770 return;
771
772
773
774
775 start = br->entries[0].to;
776 end = sample->ip;
777 len = grab_bb(buffer, start, end, machine, thread, &x.is64bit, &x.cpumode, true);
778 print_ip_sym(thread, x.cpumode, x.cpu, start, &lastsym, attr);
779 if (len <= 0) {
780
781 len = grab_bb(buffer, sample->ip, sample->ip,
782 machine, thread, &x.is64bit, &x.cpumode, false);
783 if (len <= 0)
784 return;
785
786 printf("\t%016" PRIx64 "\t%s\n", sample->ip,
787 dump_insn(&x, sample->ip, buffer, len, NULL));
788 return;
789 }
790 for (off = 0; off <= end - start; off += ilen) {
791 printf("\t%016" PRIx64 "\t%s\n", start + off,
792 dump_insn(&x, start + off, buffer + off, len - off, &ilen));
793 if (ilen == 0)
794 break;
795 }
796}
797
798static void print_sample_addr(struct perf_sample *sample,
799 struct thread *thread,
800 struct perf_event_attr *attr)
801{
802 struct addr_location al;
803
804 printf("%16" PRIx64, sample->addr);
805
806 if (!sample_addr_correlates_sym(attr))
807 return;
808
809 thread__resolve(thread, &al, sample);
810
811 if (PRINT_FIELD(SYM)) {
812 printf(" ");
813 if (PRINT_FIELD(SYMOFFSET))
814 symbol__fprintf_symname_offs(al.sym, &al, stdout);
815 else
816 symbol__fprintf_symname(al.sym, stdout);
817 }
818
819 if (PRINT_FIELD(DSO)) {
820 printf(" (");
821 map__fprintf_dsoname(al.map, stdout);
822 printf(")");
823 }
824}
825
826static void print_sample_callindent(struct perf_sample *sample,
827 struct perf_evsel *evsel,
828 struct thread *thread,
829 struct addr_location *al)
830{
831 struct perf_event_attr *attr = &evsel->attr;
832 size_t depth = thread_stack__depth(thread);
833 struct addr_location addr_al;
834 const char *name = NULL;
835 static int spacing;
836 int len = 0;
837 u64 ip = 0;
838
839
840
841
842
843 if (thread->ts && sample->flags & PERF_IP_FLAG_RETURN)
844 depth += 1;
845
846 if (sample->flags & (PERF_IP_FLAG_CALL | PERF_IP_FLAG_TRACE_BEGIN)) {
847 if (sample_addr_correlates_sym(attr)) {
848 thread__resolve(thread, &addr_al, sample);
849 if (addr_al.sym)
850 name = addr_al.sym->name;
851 else
852 ip = sample->addr;
853 } else {
854 ip = sample->addr;
855 }
856 } else if (sample->flags & (PERF_IP_FLAG_RETURN | PERF_IP_FLAG_TRACE_END)) {
857 if (al->sym)
858 name = al->sym->name;
859 else
860 ip = sample->ip;
861 }
862
863 if (name)
864 len = printf("%*s%s", (int)depth * 4, "", name);
865 else if (ip)
866 len = printf("%*s%16" PRIx64, (int)depth * 4, "", ip);
867
868 if (len < 0)
869 return;
870
871
872
873
874
875 if (len > spacing || (len && len < spacing - 52))
876 spacing = round_up(len + 4, 32);
877
878 if (len < spacing)
879 printf("%*s", spacing - len, "");
880}
881
882static void print_insn(struct perf_sample *sample,
883 struct perf_event_attr *attr,
884 struct thread *thread,
885 struct machine *machine)
886{
887 if (PRINT_FIELD(INSNLEN))
888 printf(" ilen: %d", sample->insn_len);
889 if (PRINT_FIELD(INSN)) {
890 int i;
891
892 printf(" insn:");
893 for (i = 0; i < sample->insn_len; i++)
894 printf(" %02x", (unsigned char)sample->insn[i]);
895 }
896 if (PRINT_FIELD(BRSTACKINSN))
897 print_sample_brstackinsn(sample, thread, attr, machine);
898}
899
900static void print_sample_bts(struct perf_sample *sample,
901 struct perf_evsel *evsel,
902 struct thread *thread,
903 struct addr_location *al,
904 struct machine *machine)
905{
906 struct perf_event_attr *attr = &evsel->attr;
907 bool print_srcline_last = false;
908
909 if (PRINT_FIELD(CALLINDENT))
910 print_sample_callindent(sample, evsel, thread, al);
911
912
913 if (PRINT_FIELD(IP)) {
914 unsigned int print_opts = output[attr->type].print_ip_opts;
915 struct callchain_cursor *cursor = NULL;
916
917 if (symbol_conf.use_callchain && sample->callchain &&
918 thread__resolve_callchain(al->thread, &callchain_cursor, evsel,
919 sample, NULL, NULL, scripting_max_stack) == 0)
920 cursor = &callchain_cursor;
921
922 if (cursor == NULL) {
923 putchar(' ');
924 if (print_opts & EVSEL__PRINT_SRCLINE) {
925 print_srcline_last = true;
926 print_opts &= ~EVSEL__PRINT_SRCLINE;
927 }
928 } else
929 putchar('\n');
930
931 sample__fprintf_sym(sample, al, 0, print_opts, cursor, stdout);
932 }
933
934
935 if (PRINT_FIELD(ADDR) ||
936 ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) &&
937 !output[attr->type].user_set)) {
938 printf(" => ");
939 print_sample_addr(sample, thread, attr);
940 }
941
942 if (print_srcline_last)
943 map__fprintf_srcline(al->map, al->addr, "\n ", stdout);
944
945 print_insn(sample, attr, thread, machine);
946
947 printf("\n");
948}
949
950static struct {
951 u32 flags;
952 const char *name;
953} sample_flags[] = {
954 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL, "call"},
955 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN, "return"},
956 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CONDITIONAL, "jcc"},
957 {PERF_IP_FLAG_BRANCH, "jmp"},
958 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_INTERRUPT, "int"},
959 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN | PERF_IP_FLAG_INTERRUPT, "iret"},
960 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_SYSCALLRET, "syscall"},
961 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN | PERF_IP_FLAG_SYSCALLRET, "sysret"},
962 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_ASYNC, "async"},
963 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_ASYNC | PERF_IP_FLAG_INTERRUPT, "hw int"},
964 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TX_ABORT, "tx abrt"},
965 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TRACE_BEGIN, "tr strt"},
966 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TRACE_END, "tr end"},
967 {0, NULL}
968};
969
970static void print_sample_flags(u32 flags)
971{
972 const char *chars = PERF_IP_FLAG_CHARS;
973 const int n = strlen(PERF_IP_FLAG_CHARS);
974 bool in_tx = flags & PERF_IP_FLAG_IN_TX;
975 const char *name = NULL;
976 char str[33];
977 int i, pos = 0;
978
979 for (i = 0; sample_flags[i].name ; i++) {
980 if (sample_flags[i].flags == (flags & ~PERF_IP_FLAG_IN_TX)) {
981 name = sample_flags[i].name;
982 break;
983 }
984 }
985
986 for (i = 0; i < n; i++, flags >>= 1) {
987 if (flags & 1)
988 str[pos++] = chars[i];
989 }
990 for (; i < 32; i++, flags >>= 1) {
991 if (flags & 1)
992 str[pos++] = '?';
993 }
994 str[pos] = 0;
995
996 if (name)
997 printf(" %-7s%4s ", name, in_tx ? "(x)" : "");
998 else
999 printf(" %-11s ", str);
1000}
1001
1002struct perf_script {
1003 struct perf_tool tool;
1004 struct perf_session *session;
1005 bool show_task_events;
1006 bool show_mmap_events;
1007 bool show_switch_events;
1008 bool allocated;
1009 struct cpu_map *cpus;
1010 struct thread_map *threads;
1011 int name_width;
1012 const char *time_str;
1013 struct perf_time_interval ptime;
1014};
1015
1016static int perf_evlist__max_name_len(struct perf_evlist *evlist)
1017{
1018 struct perf_evsel *evsel;
1019 int max = 0;
1020
1021 evlist__for_each_entry(evlist, evsel) {
1022 int len = strlen(perf_evsel__name(evsel));
1023
1024 max = MAX(len, max);
1025 }
1026
1027 return max;
1028}
1029
1030static size_t data_src__printf(u64 data_src)
1031{
1032 struct mem_info mi = { .data_src.val = data_src };
1033 char decode[100];
1034 char out[100];
1035 static int maxlen;
1036 int len;
1037
1038 perf_script__meminfo_scnprintf(decode, 100, &mi);
1039
1040 len = scnprintf(out, 100, "%16" PRIx64 " %s", data_src, decode);
1041 if (maxlen < len)
1042 maxlen = len;
1043
1044 return printf("%-*s", maxlen, out);
1045}
1046
1047static void process_event(struct perf_script *script,
1048 struct perf_sample *sample, struct perf_evsel *evsel,
1049 struct addr_location *al,
1050 struct machine *machine)
1051{
1052 struct thread *thread = al->thread;
1053 struct perf_event_attr *attr = &evsel->attr;
1054
1055 if (output[attr->type].fields == 0)
1056 return;
1057
1058 print_sample_start(sample, thread, evsel);
1059
1060 if (PRINT_FIELD(PERIOD))
1061 printf("%10" PRIu64 " ", sample->period);
1062
1063 if (PRINT_FIELD(EVNAME)) {
1064 const char *evname = perf_evsel__name(evsel);
1065
1066 if (!script->name_width)
1067 script->name_width = perf_evlist__max_name_len(script->session->evlist);
1068
1069 printf("%*s: ", script->name_width,
1070 evname ? evname : "[unknown]");
1071 }
1072
1073 if (print_flags)
1074 print_sample_flags(sample->flags);
1075
1076 if (is_bts_event(attr)) {
1077 print_sample_bts(sample, evsel, thread, al, machine);
1078 return;
1079 }
1080
1081 if (PRINT_FIELD(TRACE))
1082 event_format__print(evsel->tp_format, sample->cpu,
1083 sample->raw_data, sample->raw_size);
1084 if (PRINT_FIELD(ADDR))
1085 print_sample_addr(sample, thread, attr);
1086
1087 if (PRINT_FIELD(DATA_SRC))
1088 data_src__printf(sample->data_src);
1089
1090 if (PRINT_FIELD(WEIGHT))
1091 printf("%16" PRIu64, sample->weight);
1092
1093 if (PRINT_FIELD(IP)) {
1094 struct callchain_cursor *cursor = NULL;
1095
1096 if (symbol_conf.use_callchain && sample->callchain &&
1097 thread__resolve_callchain(al->thread, &callchain_cursor, evsel,
1098 sample, NULL, NULL, scripting_max_stack) == 0)
1099 cursor = &callchain_cursor;
1100
1101 putchar(cursor ? '\n' : ' ');
1102 sample__fprintf_sym(sample, al, 0, output[attr->type].print_ip_opts, cursor, stdout);
1103 }
1104
1105 if (PRINT_FIELD(IREGS))
1106 print_sample_iregs(sample, attr);
1107
1108 if (PRINT_FIELD(BRSTACK))
1109 print_sample_brstack(sample);
1110 else if (PRINT_FIELD(BRSTACKSYM))
1111 print_sample_brstacksym(sample, thread);
1112 print_insn(sample, attr, thread, machine);
1113 printf("\n");
1114}
1115
1116static struct scripting_ops *scripting_ops;
1117
1118static void __process_stat(struct perf_evsel *counter, u64 tstamp)
1119{
1120 int nthreads = thread_map__nr(counter->threads);
1121 int ncpus = perf_evsel__nr_cpus(counter);
1122 int cpu, thread;
1123 static int header_printed;
1124
1125 if (counter->system_wide)
1126 nthreads = 1;
1127
1128 if (!header_printed) {
1129 printf("%3s %8s %15s %15s %15s %15s %s\n",
1130 "CPU", "THREAD", "VAL", "ENA", "RUN", "TIME", "EVENT");
1131 header_printed = 1;
1132 }
1133
1134 for (thread = 0; thread < nthreads; thread++) {
1135 for (cpu = 0; cpu < ncpus; cpu++) {
1136 struct perf_counts_values *counts;
1137
1138 counts = perf_counts(counter->counts, cpu, thread);
1139
1140 printf("%3d %8d %15" PRIu64 " %15" PRIu64 " %15" PRIu64 " %15" PRIu64 " %s\n",
1141 counter->cpus->map[cpu],
1142 thread_map__pid(counter->threads, thread),
1143 counts->val,
1144 counts->ena,
1145 counts->run,
1146 tstamp,
1147 perf_evsel__name(counter));
1148 }
1149 }
1150}
1151
1152static void process_stat(struct perf_evsel *counter, u64 tstamp)
1153{
1154 if (scripting_ops && scripting_ops->process_stat)
1155 scripting_ops->process_stat(&stat_config, counter, tstamp);
1156 else
1157 __process_stat(counter, tstamp);
1158}
1159
1160static void process_stat_interval(u64 tstamp)
1161{
1162 if (scripting_ops && scripting_ops->process_stat_interval)
1163 scripting_ops->process_stat_interval(tstamp);
1164}
1165
1166static void setup_scripting(void)
1167{
1168 setup_perl_scripting();
1169 setup_python_scripting();
1170}
1171
1172static int flush_scripting(void)
1173{
1174 return scripting_ops ? scripting_ops->flush_script() : 0;
1175}
1176
1177static int cleanup_scripting(void)
1178{
1179 pr_debug("\nperf script stopped\n");
1180
1181 return scripting_ops ? scripting_ops->stop_script() : 0;
1182}
1183
1184static int process_sample_event(struct perf_tool *tool,
1185 union perf_event *event,
1186 struct perf_sample *sample,
1187 struct perf_evsel *evsel,
1188 struct machine *machine)
1189{
1190 struct perf_script *scr = container_of(tool, struct perf_script, tool);
1191 struct addr_location al;
1192
1193 if (perf_time__skip_sample(&scr->ptime, sample->time))
1194 return 0;
1195
1196 if (debug_mode) {
1197 if (sample->time < last_timestamp) {
1198 pr_err("Samples misordered, previous: %" PRIu64
1199 " this: %" PRIu64 "\n", last_timestamp,
1200 sample->time);
1201 nr_unordered++;
1202 }
1203 last_timestamp = sample->time;
1204 return 0;
1205 }
1206
1207 if (machine__resolve(machine, &al, sample) < 0) {
1208 pr_err("problem processing %d event, skipping it.\n",
1209 event->header.type);
1210 return -1;
1211 }
1212
1213 if (al.filtered)
1214 goto out_put;
1215
1216 if (cpu_list && !test_bit(sample->cpu, cpu_bitmap))
1217 goto out_put;
1218
1219 if (scripting_ops)
1220 scripting_ops->process_event(event, sample, evsel, &al);
1221 else
1222 process_event(scr, sample, evsel, &al, machine);
1223
1224out_put:
1225 addr_location__put(&al);
1226 return 0;
1227}
1228
1229static int process_attr(struct perf_tool *tool, union perf_event *event,
1230 struct perf_evlist **pevlist)
1231{
1232 struct perf_script *scr = container_of(tool, struct perf_script, tool);
1233 struct perf_evlist *evlist;
1234 struct perf_evsel *evsel, *pos;
1235 int err;
1236
1237 err = perf_event__process_attr(tool, event, pevlist);
1238 if (err)
1239 return err;
1240
1241 evlist = *pevlist;
1242 evsel = perf_evlist__last(*pevlist);
1243
1244 if (evsel->attr.type >= PERF_TYPE_MAX)
1245 return 0;
1246
1247 evlist__for_each_entry(evlist, pos) {
1248 if (pos->attr.type == evsel->attr.type && pos != evsel)
1249 return 0;
1250 }
1251
1252 set_print_ip_opts(&evsel->attr);
1253
1254 if (evsel->attr.sample_type)
1255 err = perf_evsel__check_attr(evsel, scr->session);
1256
1257 return err;
1258}
1259
1260static int process_comm_event(struct perf_tool *tool,
1261 union perf_event *event,
1262 struct perf_sample *sample,
1263 struct machine *machine)
1264{
1265 struct thread *thread;
1266 struct perf_script *script = container_of(tool, struct perf_script, tool);
1267 struct perf_session *session = script->session;
1268 struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
1269 int ret = -1;
1270
1271 thread = machine__findnew_thread(machine, event->comm.pid, event->comm.tid);
1272 if (thread == NULL) {
1273 pr_debug("problem processing COMM event, skipping it.\n");
1274 return -1;
1275 }
1276
1277 if (perf_event__process_comm(tool, event, sample, machine) < 0)
1278 goto out;
1279
1280 if (!evsel->attr.sample_id_all) {
1281 sample->cpu = 0;
1282 sample->time = 0;
1283 sample->tid = event->comm.tid;
1284 sample->pid = event->comm.pid;
1285 }
1286 print_sample_start(sample, thread, evsel);
1287 perf_event__fprintf(event, stdout);
1288 ret = 0;
1289out:
1290 thread__put(thread);
1291 return ret;
1292}
1293
1294static int process_fork_event(struct perf_tool *tool,
1295 union perf_event *event,
1296 struct perf_sample *sample,
1297 struct machine *machine)
1298{
1299 struct thread *thread;
1300 struct perf_script *script = container_of(tool, struct perf_script, tool);
1301 struct perf_session *session = script->session;
1302 struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
1303
1304 if (perf_event__process_fork(tool, event, sample, machine) < 0)
1305 return -1;
1306
1307 thread = machine__findnew_thread(machine, event->fork.pid, event->fork.tid);
1308 if (thread == NULL) {
1309 pr_debug("problem processing FORK event, skipping it.\n");
1310 return -1;
1311 }
1312
1313 if (!evsel->attr.sample_id_all) {
1314 sample->cpu = 0;
1315 sample->time = event->fork.time;
1316 sample->tid = event->fork.tid;
1317 sample->pid = event->fork.pid;
1318 }
1319 print_sample_start(sample, thread, evsel);
1320 perf_event__fprintf(event, stdout);
1321 thread__put(thread);
1322
1323 return 0;
1324}
1325static int process_exit_event(struct perf_tool *tool,
1326 union perf_event *event,
1327 struct perf_sample *sample,
1328 struct machine *machine)
1329{
1330 int err = 0;
1331 struct thread *thread;
1332 struct perf_script *script = container_of(tool, struct perf_script, tool);
1333 struct perf_session *session = script->session;
1334 struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
1335
1336 thread = machine__findnew_thread(machine, event->fork.pid, event->fork.tid);
1337 if (thread == NULL) {
1338 pr_debug("problem processing EXIT event, skipping it.\n");
1339 return -1;
1340 }
1341
1342 if (!evsel->attr.sample_id_all) {
1343 sample->cpu = 0;
1344 sample->time = 0;
1345 sample->tid = event->fork.tid;
1346 sample->pid = event->fork.pid;
1347 }
1348 print_sample_start(sample, thread, evsel);
1349 perf_event__fprintf(event, stdout);
1350
1351 if (perf_event__process_exit(tool, event, sample, machine) < 0)
1352 err = -1;
1353
1354 thread__put(thread);
1355 return err;
1356}
1357
1358static int process_mmap_event(struct perf_tool *tool,
1359 union perf_event *event,
1360 struct perf_sample *sample,
1361 struct machine *machine)
1362{
1363 struct thread *thread;
1364 struct perf_script *script = container_of(tool, struct perf_script, tool);
1365 struct perf_session *session = script->session;
1366 struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
1367
1368 if (perf_event__process_mmap(tool, event, sample, machine) < 0)
1369 return -1;
1370
1371 thread = machine__findnew_thread(machine, event->mmap.pid, event->mmap.tid);
1372 if (thread == NULL) {
1373 pr_debug("problem processing MMAP event, skipping it.\n");
1374 return -1;
1375 }
1376
1377 if (!evsel->attr.sample_id_all) {
1378 sample->cpu = 0;
1379 sample->time = 0;
1380 sample->tid = event->mmap.tid;
1381 sample->pid = event->mmap.pid;
1382 }
1383 print_sample_start(sample, thread, evsel);
1384 perf_event__fprintf(event, stdout);
1385 thread__put(thread);
1386 return 0;
1387}
1388
1389static int process_mmap2_event(struct perf_tool *tool,
1390 union perf_event *event,
1391 struct perf_sample *sample,
1392 struct machine *machine)
1393{
1394 struct thread *thread;
1395 struct perf_script *script = container_of(tool, struct perf_script, tool);
1396 struct perf_session *session = script->session;
1397 struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
1398
1399 if (perf_event__process_mmap2(tool, event, sample, machine) < 0)
1400 return -1;
1401
1402 thread = machine__findnew_thread(machine, event->mmap2.pid, event->mmap2.tid);
1403 if (thread == NULL) {
1404 pr_debug("problem processing MMAP2 event, skipping it.\n");
1405 return -1;
1406 }
1407
1408 if (!evsel->attr.sample_id_all) {
1409 sample->cpu = 0;
1410 sample->time = 0;
1411 sample->tid = event->mmap2.tid;
1412 sample->pid = event->mmap2.pid;
1413 }
1414 print_sample_start(sample, thread, evsel);
1415 perf_event__fprintf(event, stdout);
1416 thread__put(thread);
1417 return 0;
1418}
1419
1420static int process_switch_event(struct perf_tool *tool,
1421 union perf_event *event,
1422 struct perf_sample *sample,
1423 struct machine *machine)
1424{
1425 struct thread *thread;
1426 struct perf_script *script = container_of(tool, struct perf_script, tool);
1427 struct perf_session *session = script->session;
1428 struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
1429
1430 if (perf_event__process_switch(tool, event, sample, machine) < 0)
1431 return -1;
1432
1433 thread = machine__findnew_thread(machine, sample->pid,
1434 sample->tid);
1435 if (thread == NULL) {
1436 pr_debug("problem processing SWITCH event, skipping it.\n");
1437 return -1;
1438 }
1439
1440 print_sample_start(sample, thread, evsel);
1441 perf_event__fprintf(event, stdout);
1442 thread__put(thread);
1443 return 0;
1444}
1445
1446static void sig_handler(int sig __maybe_unused)
1447{
1448 session_done = 1;
1449}
1450
1451static int __cmd_script(struct perf_script *script)
1452{
1453 int ret;
1454
1455 signal(SIGINT, sig_handler);
1456
1457
1458 if (script->show_task_events) {
1459 script->tool.comm = process_comm_event;
1460 script->tool.fork = process_fork_event;
1461 script->tool.exit = process_exit_event;
1462 }
1463 if (script->show_mmap_events) {
1464 script->tool.mmap = process_mmap_event;
1465 script->tool.mmap2 = process_mmap2_event;
1466 }
1467 if (script->show_switch_events)
1468 script->tool.context_switch = process_switch_event;
1469
1470 ret = perf_session__process_events(script->session);
1471
1472 if (debug_mode)
1473 pr_err("Misordered timestamps: %" PRIu64 "\n", nr_unordered);
1474
1475 return ret;
1476}
1477
1478struct script_spec {
1479 struct list_head node;
1480 struct scripting_ops *ops;
1481 char spec[0];
1482};
1483
1484static LIST_HEAD(script_specs);
1485
1486static struct script_spec *script_spec__new(const char *spec,
1487 struct scripting_ops *ops)
1488{
1489 struct script_spec *s = malloc(sizeof(*s) + strlen(spec) + 1);
1490
1491 if (s != NULL) {
1492 strcpy(s->spec, spec);
1493 s->ops = ops;
1494 }
1495
1496 return s;
1497}
1498
1499static void script_spec__add(struct script_spec *s)
1500{
1501 list_add_tail(&s->node, &script_specs);
1502}
1503
1504static struct script_spec *script_spec__find(const char *spec)
1505{
1506 struct script_spec *s;
1507
1508 list_for_each_entry(s, &script_specs, node)
1509 if (strcasecmp(s->spec, spec) == 0)
1510 return s;
1511 return NULL;
1512}
1513
1514int script_spec_register(const char *spec, struct scripting_ops *ops)
1515{
1516 struct script_spec *s;
1517
1518 s = script_spec__find(spec);
1519 if (s)
1520 return -1;
1521
1522 s = script_spec__new(spec, ops);
1523 if (!s)
1524 return -1;
1525 else
1526 script_spec__add(s);
1527
1528 return 0;
1529}
1530
1531static struct scripting_ops *script_spec__lookup(const char *spec)
1532{
1533 struct script_spec *s = script_spec__find(spec);
1534 if (!s)
1535 return NULL;
1536
1537 return s->ops;
1538}
1539
1540static void list_available_languages(void)
1541{
1542 struct script_spec *s;
1543
1544 fprintf(stderr, "\n");
1545 fprintf(stderr, "Scripting language extensions (used in "
1546 "perf script -s [spec:]script.[spec]):\n\n");
1547
1548 list_for_each_entry(s, &script_specs, node)
1549 fprintf(stderr, " %-42s [%s]\n", s->spec, s->ops->name);
1550
1551 fprintf(stderr, "\n");
1552}
1553
1554static int parse_scriptname(const struct option *opt __maybe_unused,
1555 const char *str, int unset __maybe_unused)
1556{
1557 char spec[PATH_MAX];
1558 const char *script, *ext;
1559 int len;
1560
1561 if (strcmp(str, "lang") == 0) {
1562 list_available_languages();
1563 exit(0);
1564 }
1565
1566 script = strchr(str, ':');
1567 if (script) {
1568 len = script - str;
1569 if (len >= PATH_MAX) {
1570 fprintf(stderr, "invalid language specifier");
1571 return -1;
1572 }
1573 strncpy(spec, str, len);
1574 spec[len] = '\0';
1575 scripting_ops = script_spec__lookup(spec);
1576 if (!scripting_ops) {
1577 fprintf(stderr, "invalid language specifier");
1578 return -1;
1579 }
1580 script++;
1581 } else {
1582 script = str;
1583 ext = strrchr(script, '.');
1584 if (!ext) {
1585 fprintf(stderr, "invalid script extension");
1586 return -1;
1587 }
1588 scripting_ops = script_spec__lookup(++ext);
1589 if (!scripting_ops) {
1590 fprintf(stderr, "invalid script extension");
1591 return -1;
1592 }
1593 }
1594
1595 script_name = strdup(script);
1596
1597 return 0;
1598}
1599
1600static int parse_output_fields(const struct option *opt __maybe_unused,
1601 const char *arg, int unset __maybe_unused)
1602{
1603 char *tok, *strtok_saveptr = NULL;
1604 int i, imax = ARRAY_SIZE(all_output_options);
1605 int j;
1606 int rc = 0;
1607 char *str = strdup(arg);
1608 int type = -1;
1609
1610 if (!str)
1611 return -ENOMEM;
1612
1613
1614
1615
1616
1617 tok = strchr(str, ':');
1618 if (tok) {
1619 *tok = '\0';
1620 tok++;
1621 if (!strcmp(str, "hw"))
1622 type = PERF_TYPE_HARDWARE;
1623 else if (!strcmp(str, "sw"))
1624 type = PERF_TYPE_SOFTWARE;
1625 else if (!strcmp(str, "trace"))
1626 type = PERF_TYPE_TRACEPOINT;
1627 else if (!strcmp(str, "raw"))
1628 type = PERF_TYPE_RAW;
1629 else if (!strcmp(str, "break"))
1630 type = PERF_TYPE_BREAKPOINT;
1631 else {
1632 fprintf(stderr, "Invalid event type in field string.\n");
1633 rc = -EINVAL;
1634 goto out;
1635 }
1636
1637 if (output[type].user_set)
1638 pr_warning("Overriding previous field request for %s events.\n",
1639 event_type(type));
1640
1641 output[type].fields = 0;
1642 output[type].user_set = true;
1643 output[type].wildcard_set = false;
1644
1645 } else {
1646 tok = str;
1647 if (strlen(str) == 0) {
1648 fprintf(stderr,
1649 "Cannot set fields to 'none' for all event types.\n");
1650 rc = -EINVAL;
1651 goto out;
1652 }
1653
1654 if (output_set_by_user())
1655 pr_warning("Overriding previous field request for all events.\n");
1656
1657 for (j = 0; j < PERF_TYPE_MAX; ++j) {
1658 output[j].fields = 0;
1659 output[j].user_set = true;
1660 output[j].wildcard_set = true;
1661 }
1662 }
1663
1664 for (tok = strtok_r(tok, ",", &strtok_saveptr); tok; tok = strtok_r(NULL, ",", &strtok_saveptr)) {
1665 for (i = 0; i < imax; ++i) {
1666 if (strcmp(tok, all_output_options[i].str) == 0)
1667 break;
1668 }
1669 if (i == imax && strcmp(tok, "flags") == 0) {
1670 print_flags = true;
1671 continue;
1672 }
1673 if (i == imax) {
1674 fprintf(stderr, "Invalid field requested.\n");
1675 rc = -EINVAL;
1676 goto out;
1677 }
1678
1679 if (type == -1) {
1680
1681
1682
1683 for (j = 0; j < PERF_TYPE_MAX; ++j) {
1684 if (output[j].invalid_fields & all_output_options[i].field) {
1685 pr_warning("\'%s\' not valid for %s events. Ignoring.\n",
1686 all_output_options[i].str, event_type(j));
1687 } else
1688 output[j].fields |= all_output_options[i].field;
1689 }
1690 } else {
1691 if (output[type].invalid_fields & all_output_options[i].field) {
1692 fprintf(stderr, "\'%s\' not valid for %s events.\n",
1693 all_output_options[i].str, event_type(type));
1694
1695 rc = -EINVAL;
1696 goto out;
1697 }
1698 output[type].fields |= all_output_options[i].field;
1699 }
1700 }
1701
1702 if (type >= 0) {
1703 if (output[type].fields == 0) {
1704 pr_debug("No fields requested for %s type. "
1705 "Events will not be displayed.\n", event_type(type));
1706 }
1707 }
1708
1709out:
1710 free(str);
1711 return rc;
1712}
1713
1714
1715static int is_directory(const char *base_path, const struct dirent *dent)
1716{
1717 char path[PATH_MAX];
1718 struct stat st;
1719
1720 sprintf(path, "%s/%s", base_path, dent->d_name);
1721 if (stat(path, &st))
1722 return 0;
1723
1724 return S_ISDIR(st.st_mode);
1725}
1726
1727#define for_each_lang(scripts_path, scripts_dir, lang_dirent) \
1728 while ((lang_dirent = readdir(scripts_dir)) != NULL) \
1729 if ((lang_dirent->d_type == DT_DIR || \
1730 (lang_dirent->d_type == DT_UNKNOWN && \
1731 is_directory(scripts_path, lang_dirent))) && \
1732 (strcmp(lang_dirent->d_name, ".")) && \
1733 (strcmp(lang_dirent->d_name, "..")))
1734
1735#define for_each_script(lang_path, lang_dir, script_dirent) \
1736 while ((script_dirent = readdir(lang_dir)) != NULL) \
1737 if (script_dirent->d_type != DT_DIR && \
1738 (script_dirent->d_type != DT_UNKNOWN || \
1739 !is_directory(lang_path, script_dirent)))
1740
1741
1742#define RECORD_SUFFIX "-record"
1743#define REPORT_SUFFIX "-report"
1744
1745struct script_desc {
1746 struct list_head node;
1747 char *name;
1748 char *half_liner;
1749 char *args;
1750};
1751
1752static LIST_HEAD(script_descs);
1753
1754static struct script_desc *script_desc__new(const char *name)
1755{
1756 struct script_desc *s = zalloc(sizeof(*s));
1757
1758 if (s != NULL && name)
1759 s->name = strdup(name);
1760
1761 return s;
1762}
1763
1764static void script_desc__delete(struct script_desc *s)
1765{
1766 zfree(&s->name);
1767 zfree(&s->half_liner);
1768 zfree(&s->args);
1769 free(s);
1770}
1771
1772static void script_desc__add(struct script_desc *s)
1773{
1774 list_add_tail(&s->node, &script_descs);
1775}
1776
1777static struct script_desc *script_desc__find(const char *name)
1778{
1779 struct script_desc *s;
1780
1781 list_for_each_entry(s, &script_descs, node)
1782 if (strcasecmp(s->name, name) == 0)
1783 return s;
1784 return NULL;
1785}
1786
1787static struct script_desc *script_desc__findnew(const char *name)
1788{
1789 struct script_desc *s = script_desc__find(name);
1790
1791 if (s)
1792 return s;
1793
1794 s = script_desc__new(name);
1795 if (!s)
1796 goto out_delete_desc;
1797
1798 script_desc__add(s);
1799
1800 return s;
1801
1802out_delete_desc:
1803 script_desc__delete(s);
1804
1805 return NULL;
1806}
1807
1808static const char *ends_with(const char *str, const char *suffix)
1809{
1810 size_t suffix_len = strlen(suffix);
1811 const char *p = str;
1812
1813 if (strlen(str) > suffix_len) {
1814 p = str + strlen(str) - suffix_len;
1815 if (!strncmp(p, suffix, suffix_len))
1816 return p;
1817 }
1818
1819 return NULL;
1820}
1821
1822static int read_script_info(struct script_desc *desc, const char *filename)
1823{
1824 char line[BUFSIZ], *p;
1825 FILE *fp;
1826
1827 fp = fopen(filename, "r");
1828 if (!fp)
1829 return -1;
1830
1831 while (fgets(line, sizeof(line), fp)) {
1832 p = ltrim(line);
1833 if (strlen(p) == 0)
1834 continue;
1835 if (*p != '#')
1836 continue;
1837 p++;
1838 if (strlen(p) && *p == '!')
1839 continue;
1840
1841 p = ltrim(p);
1842 if (strlen(p) && p[strlen(p) - 1] == '\n')
1843 p[strlen(p) - 1] = '\0';
1844
1845 if (!strncmp(p, "description:", strlen("description:"))) {
1846 p += strlen("description:");
1847 desc->half_liner = strdup(ltrim(p));
1848 continue;
1849 }
1850
1851 if (!strncmp(p, "args:", strlen("args:"))) {
1852 p += strlen("args:");
1853 desc->args = strdup(ltrim(p));
1854 continue;
1855 }
1856 }
1857
1858 fclose(fp);
1859
1860 return 0;
1861}
1862
1863static char *get_script_root(struct dirent *script_dirent, const char *suffix)
1864{
1865 char *script_root, *str;
1866
1867 script_root = strdup(script_dirent->d_name);
1868 if (!script_root)
1869 return NULL;
1870
1871 str = (char *)ends_with(script_root, suffix);
1872 if (!str) {
1873 free(script_root);
1874 return NULL;
1875 }
1876
1877 *str = '\0';
1878 return script_root;
1879}
1880
1881static int list_available_scripts(const struct option *opt __maybe_unused,
1882 const char *s __maybe_unused,
1883 int unset __maybe_unused)
1884{
1885 struct dirent *script_dirent, *lang_dirent;
1886 char scripts_path[MAXPATHLEN];
1887 DIR *scripts_dir, *lang_dir;
1888 char script_path[MAXPATHLEN];
1889 char lang_path[MAXPATHLEN];
1890 struct script_desc *desc;
1891 char first_half[BUFSIZ];
1892 char *script_root;
1893
1894 snprintf(scripts_path, MAXPATHLEN, "%s/scripts", get_argv_exec_path());
1895
1896 scripts_dir = opendir(scripts_path);
1897 if (!scripts_dir) {
1898 fprintf(stdout,
1899 "open(%s) failed.\n"
1900 "Check \"PERF_EXEC_PATH\" env to set scripts dir.\n",
1901 scripts_path);
1902 exit(-1);
1903 }
1904
1905 for_each_lang(scripts_path, scripts_dir, lang_dirent) {
1906 snprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path,
1907 lang_dirent->d_name);
1908 lang_dir = opendir(lang_path);
1909 if (!lang_dir)
1910 continue;
1911
1912 for_each_script(lang_path, lang_dir, script_dirent) {
1913 script_root = get_script_root(script_dirent, REPORT_SUFFIX);
1914 if (script_root) {
1915 desc = script_desc__findnew(script_root);
1916 snprintf(script_path, MAXPATHLEN, "%s/%s",
1917 lang_path, script_dirent->d_name);
1918 read_script_info(desc, script_path);
1919 free(script_root);
1920 }
1921 }
1922 }
1923
1924 fprintf(stdout, "List of available trace scripts:\n");
1925 list_for_each_entry(desc, &script_descs, node) {
1926 sprintf(first_half, "%s %s", desc->name,
1927 desc->args ? desc->args : "");
1928 fprintf(stdout, " %-36s %s\n", first_half,
1929 desc->half_liner ? desc->half_liner : "");
1930 }
1931
1932 exit(0);
1933}
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944static int check_ev_match(char *dir_name, char *scriptname,
1945 struct perf_session *session)
1946{
1947 char filename[MAXPATHLEN], evname[128];
1948 char line[BUFSIZ], *p;
1949 struct perf_evsel *pos;
1950 int match, len;
1951 FILE *fp;
1952
1953 sprintf(filename, "%s/bin/%s-record", dir_name, scriptname);
1954
1955 fp = fopen(filename, "r");
1956 if (!fp)
1957 return -1;
1958
1959 while (fgets(line, sizeof(line), fp)) {
1960 p = ltrim(line);
1961 if (*p == '#')
1962 continue;
1963
1964 while (strlen(p)) {
1965 p = strstr(p, "-e");
1966 if (!p)
1967 break;
1968
1969 p += 2;
1970 p = ltrim(p);
1971 len = strcspn(p, " \t");
1972 if (!len)
1973 break;
1974
1975 snprintf(evname, len + 1, "%s", p);
1976
1977 match = 0;
1978 evlist__for_each_entry(session->evlist, pos) {
1979 if (!strcmp(perf_evsel__name(pos), evname)) {
1980 match = 1;
1981 break;
1982 }
1983 }
1984
1985 if (!match) {
1986 fclose(fp);
1987 return -1;
1988 }
1989 }
1990 }
1991
1992 fclose(fp);
1993 return 0;
1994}
1995
1996
1997
1998
1999
2000
2001
2002
2003int find_scripts(char **scripts_array, char **scripts_path_array)
2004{
2005 struct dirent *script_dirent, *lang_dirent;
2006 char scripts_path[MAXPATHLEN], lang_path[MAXPATHLEN];
2007 DIR *scripts_dir, *lang_dir;
2008 struct perf_session *session;
2009 struct perf_data_file file = {
2010 .path = input_name,
2011 .mode = PERF_DATA_MODE_READ,
2012 };
2013 char *temp;
2014 int i = 0;
2015
2016 session = perf_session__new(&file, false, NULL);
2017 if (!session)
2018 return -1;
2019
2020 snprintf(scripts_path, MAXPATHLEN, "%s/scripts", get_argv_exec_path());
2021
2022 scripts_dir = opendir(scripts_path);
2023 if (!scripts_dir) {
2024 perf_session__delete(session);
2025 return -1;
2026 }
2027
2028 for_each_lang(scripts_path, scripts_dir, lang_dirent) {
2029 snprintf(lang_path, MAXPATHLEN, "%s/%s", scripts_path,
2030 lang_dirent->d_name);
2031#ifdef NO_LIBPERL
2032 if (strstr(lang_path, "perl"))
2033 continue;
2034#endif
2035#ifdef NO_LIBPYTHON
2036 if (strstr(lang_path, "python"))
2037 continue;
2038#endif
2039
2040 lang_dir = opendir(lang_path);
2041 if (!lang_dir)
2042 continue;
2043
2044 for_each_script(lang_path, lang_dir, script_dirent) {
2045
2046 if (strstr(script_dirent->d_name, "top."))
2047 continue;
2048 sprintf(scripts_path_array[i], "%s/%s", lang_path,
2049 script_dirent->d_name);
2050 temp = strchr(script_dirent->d_name, '.');
2051 snprintf(scripts_array[i],
2052 (temp - script_dirent->d_name) + 1,
2053 "%s", script_dirent->d_name);
2054
2055 if (check_ev_match(lang_path,
2056 scripts_array[i], session))
2057 continue;
2058
2059 i++;
2060 }
2061 closedir(lang_dir);
2062 }
2063
2064 closedir(scripts_dir);
2065 perf_session__delete(session);
2066 return i;
2067}
2068
2069static char *get_script_path(const char *script_root, const char *suffix)
2070{
2071 struct dirent *script_dirent, *lang_dirent;
2072 char scripts_path[MAXPATHLEN];
2073 char script_path[MAXPATHLEN];
2074 DIR *scripts_dir, *lang_dir;
2075 char lang_path[MAXPATHLEN];
2076 char *__script_root;
2077
2078 snprintf(scripts_path, MAXPATHLEN, "%s/scripts", get_argv_exec_path());
2079
2080 scripts_dir = opendir(scripts_path);
2081 if (!scripts_dir)
2082 return NULL;
2083
2084 for_each_lang(scripts_path, scripts_dir, lang_dirent) {
2085 snprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path,
2086 lang_dirent->d_name);
2087 lang_dir = opendir(lang_path);
2088 if (!lang_dir)
2089 continue;
2090
2091 for_each_script(lang_path, lang_dir, script_dirent) {
2092 __script_root = get_script_root(script_dirent, suffix);
2093 if (__script_root && !strcmp(script_root, __script_root)) {
2094 free(__script_root);
2095 closedir(lang_dir);
2096 closedir(scripts_dir);
2097 snprintf(script_path, MAXPATHLEN, "%s/%s",
2098 lang_path, script_dirent->d_name);
2099 return strdup(script_path);
2100 }
2101 free(__script_root);
2102 }
2103 closedir(lang_dir);
2104 }
2105 closedir(scripts_dir);
2106
2107 return NULL;
2108}
2109
2110static bool is_top_script(const char *script_path)
2111{
2112 return ends_with(script_path, "top") == NULL ? false : true;
2113}
2114
2115static int has_required_arg(char *script_path)
2116{
2117 struct script_desc *desc;
2118 int n_args = 0;
2119 char *p;
2120
2121 desc = script_desc__new(NULL);
2122
2123 if (read_script_info(desc, script_path))
2124 goto out;
2125
2126 if (!desc->args)
2127 goto out;
2128
2129 for (p = desc->args; *p; p++)
2130 if (*p == '<')
2131 n_args++;
2132out:
2133 script_desc__delete(desc);
2134
2135 return n_args;
2136}
2137
2138static int have_cmd(int argc, const char **argv)
2139{
2140 char **__argv = malloc(sizeof(const char *) * argc);
2141
2142 if (!__argv) {
2143 pr_err("malloc failed\n");
2144 return -1;
2145 }
2146
2147 memcpy(__argv, argv, sizeof(const char *) * argc);
2148 argc = parse_options(argc, (const char **)__argv, record_options,
2149 NULL, PARSE_OPT_STOP_AT_NON_OPTION);
2150 free(__argv);
2151
2152 system_wide = (argc == 0);
2153
2154 return 0;
2155}
2156
2157static void script__setup_sample_type(struct perf_script *script)
2158{
2159 struct perf_session *session = script->session;
2160 u64 sample_type = perf_evlist__combined_sample_type(session->evlist);
2161
2162 if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain) {
2163 if ((sample_type & PERF_SAMPLE_REGS_USER) &&
2164 (sample_type & PERF_SAMPLE_STACK_USER))
2165 callchain_param.record_mode = CALLCHAIN_DWARF;
2166 else if (sample_type & PERF_SAMPLE_BRANCH_STACK)
2167 callchain_param.record_mode = CALLCHAIN_LBR;
2168 else
2169 callchain_param.record_mode = CALLCHAIN_FP;
2170 }
2171}
2172
2173static int process_stat_round_event(struct perf_tool *tool __maybe_unused,
2174 union perf_event *event,
2175 struct perf_session *session)
2176{
2177 struct stat_round_event *round = &event->stat_round;
2178 struct perf_evsel *counter;
2179
2180 evlist__for_each_entry(session->evlist, counter) {
2181 perf_stat_process_counter(&stat_config, counter);
2182 process_stat(counter, round->time);
2183 }
2184
2185 process_stat_interval(round->time);
2186 return 0;
2187}
2188
2189static int process_stat_config_event(struct perf_tool *tool __maybe_unused,
2190 union perf_event *event,
2191 struct perf_session *session __maybe_unused)
2192{
2193 perf_event__read_stat_config(&stat_config, &event->stat_config);
2194 return 0;
2195}
2196
2197static int set_maps(struct perf_script *script)
2198{
2199 struct perf_evlist *evlist = script->session->evlist;
2200
2201 if (!script->cpus || !script->threads)
2202 return 0;
2203
2204 if (WARN_ONCE(script->allocated, "stats double allocation\n"))
2205 return -EINVAL;
2206
2207 perf_evlist__set_maps(evlist, script->cpus, script->threads);
2208
2209 if (perf_evlist__alloc_stats(evlist, true))
2210 return -ENOMEM;
2211
2212 script->allocated = true;
2213 return 0;
2214}
2215
2216static
2217int process_thread_map_event(struct perf_tool *tool,
2218 union perf_event *event,
2219 struct perf_session *session __maybe_unused)
2220{
2221 struct perf_script *script = container_of(tool, struct perf_script, tool);
2222
2223 if (script->threads) {
2224 pr_warning("Extra thread map event, ignoring.\n");
2225 return 0;
2226 }
2227
2228 script->threads = thread_map__new_event(&event->thread_map);
2229 if (!script->threads)
2230 return -ENOMEM;
2231
2232 return set_maps(script);
2233}
2234
2235static
2236int process_cpu_map_event(struct perf_tool *tool __maybe_unused,
2237 union perf_event *event,
2238 struct perf_session *session __maybe_unused)
2239{
2240 struct perf_script *script = container_of(tool, struct perf_script, tool);
2241
2242 if (script->cpus) {
2243 pr_warning("Extra cpu map event, ignoring.\n");
2244 return 0;
2245 }
2246
2247 script->cpus = cpu_map__new_data(&event->cpu_map.data);
2248 if (!script->cpus)
2249 return -ENOMEM;
2250
2251 return set_maps(script);
2252}
2253
2254int cmd_script(int argc, const char **argv)
2255{
2256 bool show_full_info = false;
2257 bool header = false;
2258 bool header_only = false;
2259 bool script_started = false;
2260 char *rec_script_path = NULL;
2261 char *rep_script_path = NULL;
2262 struct perf_session *session;
2263 struct itrace_synth_opts itrace_synth_opts = { .set = false, };
2264 char *script_path = NULL;
2265 const char **__argv;
2266 int i, j, err = 0;
2267 struct perf_script script = {
2268 .tool = {
2269 .sample = process_sample_event,
2270 .mmap = perf_event__process_mmap,
2271 .mmap2 = perf_event__process_mmap2,
2272 .comm = perf_event__process_comm,
2273 .exit = perf_event__process_exit,
2274 .fork = perf_event__process_fork,
2275 .attr = process_attr,
2276 .event_update = perf_event__process_event_update,
2277 .tracing_data = perf_event__process_tracing_data,
2278 .build_id = perf_event__process_build_id,
2279 .id_index = perf_event__process_id_index,
2280 .auxtrace_info = perf_event__process_auxtrace_info,
2281 .auxtrace = perf_event__process_auxtrace,
2282 .auxtrace_error = perf_event__process_auxtrace_error,
2283 .stat = perf_event__process_stat_event,
2284 .stat_round = process_stat_round_event,
2285 .stat_config = process_stat_config_event,
2286 .thread_map = process_thread_map_event,
2287 .cpu_map = process_cpu_map_event,
2288 .ordered_events = true,
2289 .ordering_requires_timestamps = true,
2290 },
2291 };
2292 struct perf_data_file file = {
2293 .mode = PERF_DATA_MODE_READ,
2294 };
2295 const struct option options[] = {
2296 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
2297 "dump raw trace in ASCII"),
2298 OPT_INCR('v', "verbose", &verbose,
2299 "be more verbose (show symbol address, etc)"),
2300 OPT_BOOLEAN('L', "Latency", &latency_format,
2301 "show latency attributes (irqs/preemption disabled, etc)"),
2302 OPT_CALLBACK_NOOPT('l', "list", NULL, NULL, "list available scripts",
2303 list_available_scripts),
2304 OPT_CALLBACK('s', "script", NULL, "name",
2305 "script file name (lang:script name, script name, or *)",
2306 parse_scriptname),
2307 OPT_STRING('g', "gen-script", &generate_script_lang, "lang",
2308 "generate perf-script.xx script in specified language"),
2309 OPT_STRING('i', "input", &input_name, "file", "input file name"),
2310 OPT_BOOLEAN('d', "debug-mode", &debug_mode,
2311 "do various checks like samples ordering and lost events"),
2312 OPT_BOOLEAN(0, "header", &header, "Show data header."),
2313 OPT_BOOLEAN(0, "header-only", &header_only, "Show only data header."),
2314 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
2315 "file", "vmlinux pathname"),
2316 OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name,
2317 "file", "kallsyms pathname"),
2318 OPT_BOOLEAN('G', "hide-call-graph", &no_callchain,
2319 "When printing symbols do not display call chain"),
2320 OPT_CALLBACK(0, "symfs", NULL, "directory",
2321 "Look for files with symbols relative to this directory",
2322 symbol__config_symfs),
2323 OPT_CALLBACK('F', "fields", NULL, "str",
2324 "comma separated output fields prepend with 'type:'. "
2325 "Valid types: hw,sw,trace,raw. "
2326 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,"
2327 "addr,symoff,period,iregs,brstack,brstacksym,flags,"
2328 "callindent,insn,insnlen,brstackinsn",
2329 parse_output_fields),
2330 OPT_BOOLEAN('a', "all-cpus", &system_wide,
2331 "system-wide collection from all CPUs"),
2332 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
2333 "only consider these symbols"),
2334 OPT_STRING(0, "stop-bt", &symbol_conf.bt_stop_list_str, "symbol[,symbol...]",
2335 "Stop display of callgraph at these symbols"),
2336 OPT_STRING('C', "cpu", &cpu_list, "cpu", "list of cpus to profile"),
2337 OPT_STRING('c', "comms", &symbol_conf.comm_list_str, "comm[,comm...]",
2338 "only display events for these comms"),
2339 OPT_STRING(0, "pid", &symbol_conf.pid_list_str, "pid[,pid...]",
2340 "only consider symbols in these pids"),
2341 OPT_STRING(0, "tid", &symbol_conf.tid_list_str, "tid[,tid...]",
2342 "only consider symbols in these tids"),
2343 OPT_UINTEGER(0, "max-stack", &scripting_max_stack,
2344 "Set the maximum stack depth when parsing the callchain, "
2345 "anything beyond the specified depth will be ignored. "
2346 "Default: kernel.perf_event_max_stack or " __stringify(PERF_MAX_STACK_DEPTH)),
2347 OPT_BOOLEAN('I', "show-info", &show_full_info,
2348 "display extended information from perf.data file"),
2349 OPT_BOOLEAN('\0', "show-kernel-path", &symbol_conf.show_kernel_path,
2350 "Show the path of [kernel.kallsyms]"),
2351 OPT_BOOLEAN('\0', "show-task-events", &script.show_task_events,
2352 "Show the fork/comm/exit events"),
2353 OPT_BOOLEAN('\0', "show-mmap-events", &script.show_mmap_events,
2354 "Show the mmap events"),
2355 OPT_BOOLEAN('\0', "show-switch-events", &script.show_switch_events,
2356 "Show context switch events (if recorded)"),
2357 OPT_BOOLEAN('f', "force", &symbol_conf.force, "don't complain, do it"),
2358 OPT_INTEGER(0, "max-blocks", &max_blocks,
2359 "Maximum number of code blocks to dump with brstackinsn"),
2360 OPT_BOOLEAN(0, "ns", &nanosecs,
2361 "Use 9 decimal places when displaying time"),
2362 OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts",
2363 "Instruction Tracing options",
2364 itrace_parse_synth_opts),
2365 OPT_BOOLEAN(0, "full-source-path", &srcline_full_filename,
2366 "Show full source file name path for source lines"),
2367 OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle,
2368 "Enable symbol demangling"),
2369 OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel,
2370 "Enable kernel symbol demangling"),
2371 OPT_STRING(0, "time", &script.time_str, "str",
2372 "Time span of interest (start,stop)"),
2373 OPT_BOOLEAN(0, "inline", &symbol_conf.inline_name,
2374 "Show inline function"),
2375 OPT_END()
2376 };
2377 const char * const script_subcommands[] = { "record", "report", NULL };
2378 const char *script_usage[] = {
2379 "perf script [<options>]",
2380 "perf script [<options>] record <script> [<record-options>] <command>",
2381 "perf script [<options>] report <script> [script-args]",
2382 "perf script [<options>] <script> [<record-options>] <command>",
2383 "perf script [<options>] <top-script> [script-args]",
2384 NULL
2385 };
2386
2387 scripting_max_stack = sysctl_perf_event_max_stack;
2388
2389 setup_scripting();
2390
2391 argc = parse_options_subcommand(argc, argv, options, script_subcommands, script_usage,
2392 PARSE_OPT_STOP_AT_NON_OPTION);
2393
2394 file.path = input_name;
2395 file.force = symbol_conf.force;
2396
2397 if (argc > 1 && !strncmp(argv[0], "rec", strlen("rec"))) {
2398 rec_script_path = get_script_path(argv[1], RECORD_SUFFIX);
2399 if (!rec_script_path)
2400 return cmd_record(argc, argv);
2401 }
2402
2403 if (argc > 1 && !strncmp(argv[0], "rep", strlen("rep"))) {
2404 rep_script_path = get_script_path(argv[1], REPORT_SUFFIX);
2405 if (!rep_script_path) {
2406 fprintf(stderr,
2407 "Please specify a valid report script"
2408 "(see 'perf script -l' for listing)\n");
2409 return -1;
2410 }
2411 }
2412
2413 if (itrace_synth_opts.callchain &&
2414 itrace_synth_opts.callchain_sz > scripting_max_stack)
2415 scripting_max_stack = itrace_synth_opts.callchain_sz;
2416
2417
2418 set_argv_exec_path(get_argv_exec_path());
2419
2420 if (argc && !script_name && !rec_script_path && !rep_script_path) {
2421 int live_pipe[2];
2422 int rep_args;
2423 pid_t pid;
2424
2425 rec_script_path = get_script_path(argv[0], RECORD_SUFFIX);
2426 rep_script_path = get_script_path(argv[0], REPORT_SUFFIX);
2427
2428 if (!rec_script_path && !rep_script_path) {
2429 usage_with_options_msg(script_usage, options,
2430 "Couldn't find script `%s'\n\n See perf"
2431 " script -l for available scripts.\n", argv[0]);
2432 }
2433
2434 if (is_top_script(argv[0])) {
2435 rep_args = argc - 1;
2436 } else {
2437 int rec_args;
2438
2439 rep_args = has_required_arg(rep_script_path);
2440 rec_args = (argc - 1) - rep_args;
2441 if (rec_args < 0) {
2442 usage_with_options_msg(script_usage, options,
2443 "`%s' script requires options."
2444 "\n\n See perf script -l for available "
2445 "scripts and options.\n", argv[0]);
2446 }
2447 }
2448
2449 if (pipe(live_pipe) < 0) {
2450 perror("failed to create pipe");
2451 return -1;
2452 }
2453
2454 pid = fork();
2455 if (pid < 0) {
2456 perror("failed to fork");
2457 return -1;
2458 }
2459
2460 if (!pid) {
2461 j = 0;
2462
2463 dup2(live_pipe[1], 1);
2464 close(live_pipe[0]);
2465
2466 if (is_top_script(argv[0])) {
2467 system_wide = true;
2468 } else if (!system_wide) {
2469 if (have_cmd(argc - rep_args, &argv[rep_args]) != 0) {
2470 err = -1;
2471 goto out;
2472 }
2473 }
2474
2475 __argv = malloc((argc + 6) * sizeof(const char *));
2476 if (!__argv) {
2477 pr_err("malloc failed\n");
2478 err = -ENOMEM;
2479 goto out;
2480 }
2481
2482 __argv[j++] = "/bin/sh";
2483 __argv[j++] = rec_script_path;
2484 if (system_wide)
2485 __argv[j++] = "-a";
2486 __argv[j++] = "-q";
2487 __argv[j++] = "-o";
2488 __argv[j++] = "-";
2489 for (i = rep_args + 1; i < argc; i++)
2490 __argv[j++] = argv[i];
2491 __argv[j++] = NULL;
2492
2493 execvp("/bin/sh", (char **)__argv);
2494 free(__argv);
2495 exit(-1);
2496 }
2497
2498 dup2(live_pipe[0], 0);
2499 close(live_pipe[1]);
2500
2501 __argv = malloc((argc + 4) * sizeof(const char *));
2502 if (!__argv) {
2503 pr_err("malloc failed\n");
2504 err = -ENOMEM;
2505 goto out;
2506 }
2507
2508 j = 0;
2509 __argv[j++] = "/bin/sh";
2510 __argv[j++] = rep_script_path;
2511 for (i = 1; i < rep_args + 1; i++)
2512 __argv[j++] = argv[i];
2513 __argv[j++] = "-i";
2514 __argv[j++] = "-";
2515 __argv[j++] = NULL;
2516
2517 execvp("/bin/sh", (char **)__argv);
2518 free(__argv);
2519 exit(-1);
2520 }
2521
2522 if (rec_script_path)
2523 script_path = rec_script_path;
2524 if (rep_script_path)
2525 script_path = rep_script_path;
2526
2527 if (script_path) {
2528 j = 0;
2529
2530 if (!rec_script_path)
2531 system_wide = false;
2532 else if (!system_wide) {
2533 if (have_cmd(argc - 1, &argv[1]) != 0) {
2534 err = -1;
2535 goto out;
2536 }
2537 }
2538
2539 __argv = malloc((argc + 2) * sizeof(const char *));
2540 if (!__argv) {
2541 pr_err("malloc failed\n");
2542 err = -ENOMEM;
2543 goto out;
2544 }
2545
2546 __argv[j++] = "/bin/sh";
2547 __argv[j++] = script_path;
2548 if (system_wide)
2549 __argv[j++] = "-a";
2550 for (i = 2; i < argc; i++)
2551 __argv[j++] = argv[i];
2552 __argv[j++] = NULL;
2553
2554 execvp("/bin/sh", (char **)__argv);
2555 free(__argv);
2556 exit(-1);
2557 }
2558
2559 if (!script_name)
2560 setup_pager();
2561
2562 session = perf_session__new(&file, false, &script.tool);
2563 if (session == NULL)
2564 return -1;
2565
2566 if (header || header_only) {
2567 perf_session__fprintf_info(session, stdout, show_full_info);
2568 if (header_only)
2569 goto out_delete;
2570 }
2571
2572 if (symbol__init(&session->header.env) < 0)
2573 goto out_delete;
2574
2575 script.session = session;
2576 script__setup_sample_type(&script);
2577
2578 if (output[PERF_TYPE_HARDWARE].fields & PERF_OUTPUT_CALLINDENT)
2579 itrace_synth_opts.thread_stack = true;
2580
2581 session->itrace_synth_opts = &itrace_synth_opts;
2582
2583 if (cpu_list) {
2584 err = perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap);
2585 if (err < 0)
2586 goto out_delete;
2587 }
2588
2589 if (!no_callchain)
2590 symbol_conf.use_callchain = true;
2591 else
2592 symbol_conf.use_callchain = false;
2593
2594 if (session->tevent.pevent &&
2595 pevent_set_function_resolver(session->tevent.pevent,
2596 machine__resolve_kernel_addr,
2597 &session->machines.host) < 0) {
2598 pr_err("%s: failed to set libtraceevent function resolver\n", __func__);
2599 return -1;
2600 }
2601
2602 if (generate_script_lang) {
2603 struct stat perf_stat;
2604 int input;
2605
2606 if (output_set_by_user()) {
2607 fprintf(stderr,
2608 "custom fields not supported for generated scripts");
2609 err = -EINVAL;
2610 goto out_delete;
2611 }
2612
2613 input = open(file.path, O_RDONLY);
2614 if (input < 0) {
2615 err = -errno;
2616 perror("failed to open file");
2617 goto out_delete;
2618 }
2619
2620 err = fstat(input, &perf_stat);
2621 if (err < 0) {
2622 perror("failed to stat file");
2623 goto out_delete;
2624 }
2625
2626 if (!perf_stat.st_size) {
2627 fprintf(stderr, "zero-sized file, nothing to do!\n");
2628 goto out_delete;
2629 }
2630
2631 scripting_ops = script_spec__lookup(generate_script_lang);
2632 if (!scripting_ops) {
2633 fprintf(stderr, "invalid language specifier");
2634 err = -ENOENT;
2635 goto out_delete;
2636 }
2637
2638 err = scripting_ops->generate_script(session->tevent.pevent,
2639 "perf-script");
2640 goto out_delete;
2641 }
2642
2643 if (script_name) {
2644 err = scripting_ops->start_script(script_name, argc, argv);
2645 if (err)
2646 goto out_delete;
2647 pr_debug("perf script started with script %s\n\n", script_name);
2648 script_started = true;
2649 }
2650
2651
2652 err = perf_session__check_output_opt(session);
2653 if (err < 0)
2654 goto out_delete;
2655
2656
2657 if (perf_time__parse_str(&script.ptime, script.time_str) != 0) {
2658 pr_err("Invalid time string\n");
2659 return -EINVAL;
2660 }
2661
2662 err = __cmd_script(&script);
2663
2664 flush_scripting();
2665
2666out_delete:
2667 perf_evlist__free_stats(session->evlist);
2668 perf_session__delete(session);
2669
2670 if (script_started)
2671 cleanup_scripting();
2672out:
2673 return err;
2674}
2675