hc
2023-12-08 01573e231f18eb2d99162747186f59511f56b64d
kernel/tools/perf/builtin-script.c
....@@ -1,21 +1,24 @@
11 // SPDX-License-Identifier: GPL-2.0
22 #include "builtin.h"
33
4
-#include "perf.h"
5
-#include "util/cache.h"
4
+#include "util/counts.h"
65 #include "util/debug.h"
6
+#include "util/dso.h"
77 #include <subcmd/exec-cmd.h>
88 #include "util/header.h"
99 #include <subcmd/parse-options.h>
1010 #include "util/perf_regs.h"
1111 #include "util/session.h"
1212 #include "util/tool.h"
13
+#include "util/map.h"
14
+#include "util/srcline.h"
1315 #include "util/symbol.h"
1416 #include "util/thread.h"
1517 #include "util/trace-event.h"
16
-#include "util/util.h"
1718 #include "util/evlist.h"
1819 #include "util/evsel.h"
20
+#include "util/evsel_fprintf.h"
21
+#include "util/evswitch.h"
1922 #include "util/sort.h"
2023 #include "util/data.h"
2124 #include "util/auxtrace.h"
....@@ -27,11 +30,15 @@
2730 #include "util/thread-stack.h"
2831 #include "util/time-utils.h"
2932 #include "util/path.h"
33
+#include "ui/ui.h"
3034 #include "print_binary.h"
35
+#include "archinsn.h"
3136 #include <linux/bitmap.h>
3237 #include <linux/kernel.h>
3338 #include <linux/stringify.h>
3439 #include <linux/time64.h>
40
+#include <linux/zalloc.h>
41
+#include <sys/utsname.h>
3542 #include "asm/bug.h"
3643 #include "util/mem-events.h"
3744 #include "util/dump-insn.h"
....@@ -44,11 +51,21 @@
4451 #include <sys/stat.h>
4552 #include <fcntl.h>
4653 #include <unistd.h>
54
+#include <subcmd/pager.h>
55
+#include <perf/evlist.h>
56
+#include <linux/err.h>
57
+#include "util/record.h"
58
+#include "util/util.h"
59
+#include "perf.h"
4760
48
-#include "sane_ctype.h"
61
+#include <linux/ctype.h>
4962
5063 static char const *script_name;
5164 static char const *generate_script_lang;
65
+static bool reltime;
66
+static bool deltatime;
67
+static u64 initial_time;
68
+static u64 previous_time;
5269 static bool debug_mode;
5370 static u64 last_timestamp;
5471 static u64 nr_unordered;
....@@ -56,45 +73,73 @@
5673 static bool latency_format;
5774 static bool system_wide;
5875 static bool print_flags;
59
-static bool nanosecs;
6076 static const char *cpu_list;
6177 static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
6278 static struct perf_stat_config stat_config;
6379 static int max_blocks;
80
+static bool native_arch;
6481
6582 unsigned int scripting_max_stack = PERF_MAX_STACK_DEPTH;
6683
6784 enum perf_output_field {
68
- PERF_OUTPUT_COMM = 1U << 0,
69
- PERF_OUTPUT_TID = 1U << 1,
70
- PERF_OUTPUT_PID = 1U << 2,
71
- PERF_OUTPUT_TIME = 1U << 3,
72
- PERF_OUTPUT_CPU = 1U << 4,
73
- PERF_OUTPUT_EVNAME = 1U << 5,
74
- PERF_OUTPUT_TRACE = 1U << 6,
75
- PERF_OUTPUT_IP = 1U << 7,
76
- PERF_OUTPUT_SYM = 1U << 8,
77
- PERF_OUTPUT_DSO = 1U << 9,
78
- PERF_OUTPUT_ADDR = 1U << 10,
79
- PERF_OUTPUT_SYMOFFSET = 1U << 11,
80
- PERF_OUTPUT_SRCLINE = 1U << 12,
81
- PERF_OUTPUT_PERIOD = 1U << 13,
82
- PERF_OUTPUT_IREGS = 1U << 14,
83
- PERF_OUTPUT_BRSTACK = 1U << 15,
84
- PERF_OUTPUT_BRSTACKSYM = 1U << 16,
85
- PERF_OUTPUT_DATA_SRC = 1U << 17,
86
- PERF_OUTPUT_WEIGHT = 1U << 18,
87
- PERF_OUTPUT_BPF_OUTPUT = 1U << 19,
88
- PERF_OUTPUT_CALLINDENT = 1U << 20,
89
- PERF_OUTPUT_INSN = 1U << 21,
90
- PERF_OUTPUT_INSNLEN = 1U << 22,
91
- PERF_OUTPUT_BRSTACKINSN = 1U << 23,
92
- PERF_OUTPUT_BRSTACKOFF = 1U << 24,
93
- PERF_OUTPUT_SYNTH = 1U << 25,
94
- PERF_OUTPUT_PHYS_ADDR = 1U << 26,
95
- PERF_OUTPUT_UREGS = 1U << 27,
96
- PERF_OUTPUT_METRIC = 1U << 28,
97
- PERF_OUTPUT_MISC = 1U << 29,
85
+ PERF_OUTPUT_COMM = 1ULL << 0,
86
+ PERF_OUTPUT_TID = 1ULL << 1,
87
+ PERF_OUTPUT_PID = 1ULL << 2,
88
+ PERF_OUTPUT_TIME = 1ULL << 3,
89
+ PERF_OUTPUT_CPU = 1ULL << 4,
90
+ PERF_OUTPUT_EVNAME = 1ULL << 5,
91
+ PERF_OUTPUT_TRACE = 1ULL << 6,
92
+ PERF_OUTPUT_IP = 1ULL << 7,
93
+ PERF_OUTPUT_SYM = 1ULL << 8,
94
+ PERF_OUTPUT_DSO = 1ULL << 9,
95
+ PERF_OUTPUT_ADDR = 1ULL << 10,
96
+ PERF_OUTPUT_SYMOFFSET = 1ULL << 11,
97
+ PERF_OUTPUT_SRCLINE = 1ULL << 12,
98
+ PERF_OUTPUT_PERIOD = 1ULL << 13,
99
+ PERF_OUTPUT_IREGS = 1ULL << 14,
100
+ PERF_OUTPUT_BRSTACK = 1ULL << 15,
101
+ PERF_OUTPUT_BRSTACKSYM = 1ULL << 16,
102
+ PERF_OUTPUT_DATA_SRC = 1ULL << 17,
103
+ PERF_OUTPUT_WEIGHT = 1ULL << 18,
104
+ PERF_OUTPUT_BPF_OUTPUT = 1ULL << 19,
105
+ PERF_OUTPUT_CALLINDENT = 1ULL << 20,
106
+ PERF_OUTPUT_INSN = 1ULL << 21,
107
+ PERF_OUTPUT_INSNLEN = 1ULL << 22,
108
+ PERF_OUTPUT_BRSTACKINSN = 1ULL << 23,
109
+ PERF_OUTPUT_BRSTACKOFF = 1ULL << 24,
110
+ PERF_OUTPUT_SYNTH = 1ULL << 25,
111
+ PERF_OUTPUT_PHYS_ADDR = 1ULL << 26,
112
+ PERF_OUTPUT_UREGS = 1ULL << 27,
113
+ PERF_OUTPUT_METRIC = 1ULL << 28,
114
+ PERF_OUTPUT_MISC = 1ULL << 29,
115
+ PERF_OUTPUT_SRCCODE = 1ULL << 30,
116
+ PERF_OUTPUT_IPC = 1ULL << 31,
117
+ PERF_OUTPUT_TOD = 1ULL << 32,
118
+};
119
+
120
+struct perf_script {
121
+ struct perf_tool tool;
122
+ struct perf_session *session;
123
+ bool show_task_events;
124
+ bool show_mmap_events;
125
+ bool show_switch_events;
126
+ bool show_namespace_events;
127
+ bool show_lost_events;
128
+ bool show_round_events;
129
+ bool show_bpf_events;
130
+ bool show_cgroup_events;
131
+ bool show_text_poke_events;
132
+ bool allocated;
133
+ bool per_event_dump;
134
+ bool stitch_lbr;
135
+ struct evswitch evswitch;
136
+ struct perf_cpu_map *cpus;
137
+ struct perf_thread_map *threads;
138
+ int name_width;
139
+ const char *time_str;
140
+ struct perf_time_interval *ptime_range;
141
+ int range_size;
142
+ int range_num;
98143 };
99144
100145 struct output_option {
....@@ -131,6 +176,9 @@
131176 {.str = "phys_addr", .field = PERF_OUTPUT_PHYS_ADDR},
132177 {.str = "metric", .field = PERF_OUTPUT_METRIC},
133178 {.str = "misc", .field = PERF_OUTPUT_MISC},
179
+ {.str = "srccode", .field = PERF_OUTPUT_SRCCODE},
180
+ {.str = "ipc", .field = PERF_OUTPUT_IPC},
181
+ {.str = "tod", .field = PERF_OUTPUT_TOD},
134182 };
135183
136184 enum {
....@@ -145,6 +193,8 @@
145193 unsigned int print_ip_opts;
146194 u64 fields;
147195 u64 invalid_fields;
196
+ u64 user_set_fields;
197
+ u64 user_unset_fields;
148198 } output[OUTPUT_TYPE_MAX] = {
149199
150200 [PERF_TYPE_HARDWARE] = {
....@@ -231,7 +281,7 @@
231281 },
232282 };
233283
234
-struct perf_evsel_script {
284
+struct evsel_script {
235285 char *filename;
236286 FILE *fp;
237287 u64 samples;
....@@ -240,18 +290,18 @@
240290 int gnum;
241291 };
242292
243
-static inline struct perf_evsel_script *evsel_script(struct perf_evsel *evsel)
293
+static inline struct evsel_script *evsel_script(struct evsel *evsel)
244294 {
245
- return (struct perf_evsel_script *)evsel->priv;
295
+ return (struct evsel_script *)evsel->priv;
246296 }
247297
248
-static struct perf_evsel_script *perf_evsel_script__new(struct perf_evsel *evsel,
298
+static struct evsel_script *perf_evsel_script__new(struct evsel *evsel,
249299 struct perf_data *data)
250300 {
251
- struct perf_evsel_script *es = zalloc(sizeof(*es));
301
+ struct evsel_script *es = zalloc(sizeof(*es));
252302
253303 if (es != NULL) {
254
- if (asprintf(&es->filename, "%s.%s.dump", data->file.path, perf_evsel__name(evsel)) < 0)
304
+ if (asprintf(&es->filename, "%s.%s.dump", data->file.path, evsel__name(evsel)) < 0)
255305 goto out_free;
256306 es->fp = fopen(es->filename, "w");
257307 if (es->fp == NULL)
....@@ -266,7 +316,7 @@
266316 return NULL;
267317 }
268318
269
-static void perf_evsel_script__delete(struct perf_evsel_script *es)
319
+static void perf_evsel_script__delete(struct evsel_script *es)
270320 {
271321 zfree(&es->filename);
272322 fclose(es->fp);
....@@ -274,7 +324,7 @@
274324 free(es);
275325 }
276326
277
-static int perf_evsel_script__fprintf(struct perf_evsel_script *es, FILE *fp)
327
+static int perf_evsel_script__fprintf(struct evsel_script *es, FILE *fp)
278328 {
279329 struct stat st;
280330
....@@ -329,22 +379,20 @@
329379
330380 #define PRINT_FIELD(x) (output[output_type(attr->type)].fields & PERF_OUTPUT_##x)
331381
332
-static int perf_evsel__do_check_stype(struct perf_evsel *evsel,
333
- u64 sample_type, const char *sample_msg,
334
- enum perf_output_field field,
335
- bool allow_user_set)
382
+static int evsel__do_check_stype(struct evsel *evsel, u64 sample_type, const char *sample_msg,
383
+ enum perf_output_field field, bool allow_user_set)
336384 {
337
- struct perf_event_attr *attr = &evsel->attr;
385
+ struct perf_event_attr *attr = &evsel->core.attr;
338386 int type = output_type(attr->type);
339387 const char *evname;
340388
341389 if (attr->sample_type & sample_type)
342390 return 0;
343391
344
- if (output[type].user_set) {
392
+ if (output[type].user_set_fields & field) {
345393 if (allow_user_set)
346394 return 0;
347
- evname = perf_evsel__name(evsel);
395
+ evname = evsel__name(evsel);
348396 pr_err("Samples for '%s' event do not have %s attribute set. "
349397 "Cannot print '%s' field.\n",
350398 evname, sample_msg, output_field2str(field));
....@@ -353,7 +401,7 @@
353401
354402 /* user did not ask for it explicitly so remove from the default list */
355403 output[type].fields &= ~field;
356
- evname = perf_evsel__name(evsel);
404
+ evname = evsel__name(evsel);
357405 pr_debug("Samples for '%s' event do not have %s attribute set. "
358406 "Skipping '%s' field.\n",
359407 evname, sample_msg, output_field2str(field));
....@@ -361,18 +409,15 @@
361409 return 0;
362410 }
363411
364
-static int perf_evsel__check_stype(struct perf_evsel *evsel,
365
- u64 sample_type, const char *sample_msg,
366
- enum perf_output_field field)
412
+static int evsel__check_stype(struct evsel *evsel, u64 sample_type, const char *sample_msg,
413
+ enum perf_output_field field)
367414 {
368
- return perf_evsel__do_check_stype(evsel, sample_type, sample_msg, field,
369
- false);
415
+ return evsel__do_check_stype(evsel, sample_type, sample_msg, field, false);
370416 }
371417
372
-static int perf_evsel__check_attr(struct perf_evsel *evsel,
373
- struct perf_session *session)
418
+static int evsel__check_attr(struct evsel *evsel, struct perf_session *session)
374419 {
375
- struct perf_event_attr *attr = &evsel->attr;
420
+ struct perf_event_attr *attr = &evsel->core.attr;
376421 bool allow_user_set;
377422
378423 if (perf_header__has_feat(&session->header, HEADER_STAT))
....@@ -382,33 +427,30 @@
382427 HEADER_AUXTRACE);
383428
384429 if (PRINT_FIELD(TRACE) &&
385
- !perf_session__has_traces(session, "record -R"))
430
+ !perf_session__has_traces(session, "record -R"))
386431 return -EINVAL;
387432
388433 if (PRINT_FIELD(IP)) {
389
- if (perf_evsel__check_stype(evsel, PERF_SAMPLE_IP, "IP",
390
- PERF_OUTPUT_IP))
434
+ if (evsel__check_stype(evsel, PERF_SAMPLE_IP, "IP", PERF_OUTPUT_IP))
391435 return -EINVAL;
392436 }
393437
394438 if (PRINT_FIELD(ADDR) &&
395
- perf_evsel__do_check_stype(evsel, PERF_SAMPLE_ADDR, "ADDR",
396
- PERF_OUTPUT_ADDR, allow_user_set))
439
+ evsel__do_check_stype(evsel, PERF_SAMPLE_ADDR, "ADDR", PERF_OUTPUT_ADDR, allow_user_set))
397440 return -EINVAL;
398441
399442 if (PRINT_FIELD(DATA_SRC) &&
400
- perf_evsel__check_stype(evsel, PERF_SAMPLE_DATA_SRC, "DATA_SRC",
401
- PERF_OUTPUT_DATA_SRC))
443
+ evsel__check_stype(evsel, PERF_SAMPLE_DATA_SRC, "DATA_SRC", PERF_OUTPUT_DATA_SRC))
402444 return -EINVAL;
403445
404446 if (PRINT_FIELD(WEIGHT) &&
405
- perf_evsel__check_stype(evsel, PERF_SAMPLE_WEIGHT, "WEIGHT",
406
- PERF_OUTPUT_WEIGHT))
447
+ evsel__check_stype(evsel, PERF_SAMPLE_WEIGHT, "WEIGHT", PERF_OUTPUT_WEIGHT))
407448 return -EINVAL;
408449
409
- if (PRINT_FIELD(SYM) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) {
450
+ if (PRINT_FIELD(SYM) &&
451
+ !(evsel->core.attr.sample_type & (PERF_SAMPLE_IP|PERF_SAMPLE_ADDR))) {
410452 pr_err("Display of symbols requested but neither sample IP nor "
411
- "sample address\nis selected. Hence, no addresses to convert "
453
+ "sample address\navailable. Hence, no addresses to convert "
412454 "to symbols.\n");
413455 return -EINVAL;
414456 }
....@@ -417,52 +459,44 @@
417459 "selected.\n");
418460 return -EINVAL;
419461 }
420
- if (PRINT_FIELD(DSO) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR) &&
421
- !PRINT_FIELD(BRSTACK) && !PRINT_FIELD(BRSTACKSYM) && !PRINT_FIELD(BRSTACKOFF)) {
422
- pr_err("Display of DSO requested but no address to convert. Select\n"
423
- "sample IP, sample address, brstack, brstacksym, or brstackoff.\n");
462
+ if (PRINT_FIELD(DSO) &&
463
+ !(evsel->core.attr.sample_type & (PERF_SAMPLE_IP|PERF_SAMPLE_ADDR))) {
464
+ pr_err("Display of DSO requested but no address to convert.\n");
424465 return -EINVAL;
425466 }
426
- if (PRINT_FIELD(SRCLINE) && !PRINT_FIELD(IP)) {
467
+ if ((PRINT_FIELD(SRCLINE) || PRINT_FIELD(SRCCODE)) && !PRINT_FIELD(IP)) {
427468 pr_err("Display of source line number requested but sample IP is not\n"
428469 "selected. Hence, no address to lookup the source line number.\n");
429470 return -EINVAL;
430471 }
431472 if (PRINT_FIELD(BRSTACKINSN) && !allow_user_set &&
432
- !(perf_evlist__combined_branch_type(session->evlist) &
433
- PERF_SAMPLE_BRANCH_ANY)) {
473
+ !(evlist__combined_branch_type(session->evlist) & PERF_SAMPLE_BRANCH_ANY)) {
434474 pr_err("Display of branch stack assembler requested, but non all-branch filter set\n"
435475 "Hint: run 'perf record -b ...'\n");
436476 return -EINVAL;
437477 }
438478 if ((PRINT_FIELD(PID) || PRINT_FIELD(TID)) &&
439
- perf_evsel__check_stype(evsel, PERF_SAMPLE_TID, "TID",
440
- PERF_OUTPUT_TID|PERF_OUTPUT_PID))
479
+ evsel__check_stype(evsel, PERF_SAMPLE_TID, "TID", PERF_OUTPUT_TID|PERF_OUTPUT_PID))
441480 return -EINVAL;
442481
443482 if (PRINT_FIELD(TIME) &&
444
- perf_evsel__check_stype(evsel, PERF_SAMPLE_TIME, "TIME",
445
- PERF_OUTPUT_TIME))
483
+ evsel__check_stype(evsel, PERF_SAMPLE_TIME, "TIME", PERF_OUTPUT_TIME))
446484 return -EINVAL;
447485
448486 if (PRINT_FIELD(CPU) &&
449
- perf_evsel__do_check_stype(evsel, PERF_SAMPLE_CPU, "CPU",
450
- PERF_OUTPUT_CPU, allow_user_set))
487
+ evsel__do_check_stype(evsel, PERF_SAMPLE_CPU, "CPU", PERF_OUTPUT_CPU, allow_user_set))
451488 return -EINVAL;
452489
453490 if (PRINT_FIELD(IREGS) &&
454
- perf_evsel__check_stype(evsel, PERF_SAMPLE_REGS_INTR, "IREGS",
455
- PERF_OUTPUT_IREGS))
491
+ evsel__do_check_stype(evsel, PERF_SAMPLE_REGS_INTR, "IREGS", PERF_OUTPUT_IREGS, allow_user_set))
456492 return -EINVAL;
457493
458494 if (PRINT_FIELD(UREGS) &&
459
- perf_evsel__check_stype(evsel, PERF_SAMPLE_REGS_USER, "UREGS",
460
- PERF_OUTPUT_UREGS))
495
+ evsel__check_stype(evsel, PERF_SAMPLE_REGS_USER, "UREGS", PERF_OUTPUT_UREGS))
461496 return -EINVAL;
462497
463498 if (PRINT_FIELD(PHYS_ADDR) &&
464
- perf_evsel__check_stype(evsel, PERF_SAMPLE_PHYS_ADDR, "PHYS_ADDR",
465
- PERF_OUTPUT_PHYS_ADDR))
499
+ evsel__check_stype(evsel, PERF_SAMPLE_PHYS_ADDR, "PHYS_ADDR", PERF_OUTPUT_PHYS_ADDR))
466500 return -EINVAL;
467501
468502 return 0;
....@@ -495,8 +529,9 @@
495529 */
496530 static int perf_session__check_output_opt(struct perf_session *session)
497531 {
532
+ bool tod = false;
498533 unsigned int j;
499
- struct perf_evsel *evsel;
534
+ struct evsel *evsel;
500535
501536 for (j = 0; j < OUTPUT_TYPE_MAX; ++j) {
502537 evsel = perf_session__find_first_evtype(session, attr_type(j));
....@@ -514,13 +549,14 @@
514549 }
515550
516551 if (evsel && output[j].fields &&
517
- perf_evsel__check_attr(evsel, session))
552
+ evsel__check_attr(evsel, session))
518553 return -1;
519554
520555 if (evsel == NULL)
521556 continue;
522557
523
- set_print_ip_opts(&evsel->attr);
558
+ set_print_ip_opts(&evsel->core.attr);
559
+ tod |= output[j].fields & PERF_OUTPUT_TOD;
524560 }
525561
526562 if (!no_callchain) {
....@@ -547,7 +583,7 @@
547583 j = PERF_TYPE_TRACEPOINT;
548584
549585 evlist__for_each_entry(session->evlist, evsel) {
550
- if (evsel->attr.type != j)
586
+ if (evsel->core.attr.type != j)
551587 continue;
552588
553589 if (evsel__has_callchain(evsel)) {
....@@ -555,40 +591,24 @@
555591 output[j].fields |= PERF_OUTPUT_SYM;
556592 output[j].fields |= PERF_OUTPUT_SYMOFFSET;
557593 output[j].fields |= PERF_OUTPUT_DSO;
558
- set_print_ip_opts(&evsel->attr);
594
+ set_print_ip_opts(&evsel->core.attr);
559595 goto out;
560596 }
561597 }
562598 }
563599
600
+ if (tod && !session->header.env.clock.enabled) {
601
+ pr_err("Can't provide 'tod' time, missing clock data. "
602
+ "Please record with -k/--clockid option.\n");
603
+ return -1;
604
+ }
564605 out:
565606 return 0;
566607 }
567608
568
-static int perf_sample__fprintf_iregs(struct perf_sample *sample,
569
- struct perf_event_attr *attr, FILE *fp)
609
+static int perf_sample__fprintf_regs(struct regs_dump *regs, uint64_t mask,
610
+ FILE *fp)
570611 {
571
- struct regs_dump *regs = &sample->intr_regs;
572
- uint64_t mask = attr->sample_regs_intr;
573
- unsigned i = 0, r;
574
- int printed = 0;
575
-
576
- if (!regs)
577
- return 0;
578
-
579
- for_each_set_bit(r, (unsigned long *) &mask, sizeof(mask) * 8) {
580
- u64 val = regs->regs[i++];
581
- printed += fprintf(fp, "%5s:0x%"PRIx64" ", perf_reg_name(r), val);
582
- }
583
-
584
- return printed;
585
-}
586
-
587
-static int perf_sample__fprintf_uregs(struct perf_sample *sample,
588
- struct perf_event_attr *attr, FILE *fp)
589
-{
590
- struct regs_dump *regs = &sample->user_regs;
591
- uint64_t mask = attr->sample_regs_user;
592612 unsigned i = 0, r;
593613 int printed = 0;
594614
....@@ -605,23 +625,91 @@
605625 return printed;
606626 }
607627
608
-static int perf_sample__fprintf_start(struct perf_sample *sample,
628
+#define DEFAULT_TOD_FMT "%F %H:%M:%S"
629
+
630
+static char*
631
+tod_scnprintf(struct perf_script *script, char *buf, int buflen,
632
+ u64 timestamp)
633
+{
634
+ u64 tod_ns, clockid_ns;
635
+ struct perf_env *env;
636
+ unsigned long nsec;
637
+ struct tm ltime;
638
+ char date[64];
639
+ time_t sec;
640
+
641
+ buf[0] = '\0';
642
+ if (buflen < 64 || !script)
643
+ return buf;
644
+
645
+ env = &script->session->header.env;
646
+ if (!env->clock.enabled) {
647
+ scnprintf(buf, buflen, "disabled");
648
+ return buf;
649
+ }
650
+
651
+ clockid_ns = env->clock.clockid_ns;
652
+ tod_ns = env->clock.tod_ns;
653
+
654
+ if (timestamp > clockid_ns)
655
+ tod_ns += timestamp - clockid_ns;
656
+ else
657
+ tod_ns -= clockid_ns - timestamp;
658
+
659
+ sec = (time_t) (tod_ns / NSEC_PER_SEC);
660
+ nsec = tod_ns - sec * NSEC_PER_SEC;
661
+
662
+ if (localtime_r(&sec, &ltime) == NULL) {
663
+ scnprintf(buf, buflen, "failed");
664
+ } else {
665
+ strftime(date, sizeof(date), DEFAULT_TOD_FMT, &ltime);
666
+
667
+ if (symbol_conf.nanosecs) {
668
+ snprintf(buf, buflen, "%s.%09lu", date, nsec);
669
+ } else {
670
+ snprintf(buf, buflen, "%s.%06lu",
671
+ date, nsec / NSEC_PER_USEC);
672
+ }
673
+ }
674
+
675
+ return buf;
676
+}
677
+
678
+static int perf_sample__fprintf_iregs(struct perf_sample *sample,
679
+ struct perf_event_attr *attr, FILE *fp)
680
+{
681
+ return perf_sample__fprintf_regs(&sample->intr_regs,
682
+ attr->sample_regs_intr, fp);
683
+}
684
+
685
+static int perf_sample__fprintf_uregs(struct perf_sample *sample,
686
+ struct perf_event_attr *attr, FILE *fp)
687
+{
688
+ return perf_sample__fprintf_regs(&sample->user_regs,
689
+ attr->sample_regs_user, fp);
690
+}
691
+
692
+static int perf_sample__fprintf_start(struct perf_script *script,
693
+ struct perf_sample *sample,
609694 struct thread *thread,
610
- struct perf_evsel *evsel,
695
+ struct evsel *evsel,
611696 u32 type, FILE *fp)
612697 {
613
- struct perf_event_attr *attr = &evsel->attr;
698
+ struct perf_event_attr *attr = &evsel->core.attr;
614699 unsigned long secs;
615700 unsigned long long nsecs;
616701 int printed = 0;
702
+ char tstr[128];
617703
618704 if (PRINT_FIELD(COMM)) {
705
+ const char *comm = thread ? thread__comm_str(thread) : ":-1";
706
+
619707 if (latency_format)
620
- printed += fprintf(fp, "%8.8s ", thread__comm_str(thread));
708
+ printed += fprintf(fp, "%8.8s ", comm);
621709 else if (PRINT_FIELD(IP) && evsel__has_callchain(evsel) && symbol_conf.use_callchain)
622
- printed += fprintf(fp, "%s ", thread__comm_str(thread));
710
+ printed += fprintf(fp, "%s ", comm);
623711 else
624
- printed += fprintf(fp, "%16s ", thread__comm_str(thread));
712
+ printed += fprintf(fp, "%16s ", comm);
625713 }
626714
627715 if (PRINT_FIELD(PID) && PRINT_FIELD(TID))
....@@ -682,16 +770,34 @@
682770 printed += ret;
683771 }
684772
773
+ if (PRINT_FIELD(TOD)) {
774
+ tod_scnprintf(script, tstr, sizeof(tstr), sample->time);
775
+ printed += fprintf(fp, "%s ", tstr);
776
+ }
777
+
685778 if (PRINT_FIELD(TIME)) {
686
- nsecs = sample->time;
779
+ u64 t = sample->time;
780
+ if (reltime) {
781
+ if (!initial_time)
782
+ initial_time = sample->time;
783
+ t = sample->time - initial_time;
784
+ } else if (deltatime) {
785
+ if (previous_time)
786
+ t = sample->time - previous_time;
787
+ else {
788
+ t = 0;
789
+ }
790
+ previous_time = sample->time;
791
+ }
792
+ nsecs = t;
687793 secs = nsecs / NSEC_PER_SEC;
688794 nsecs -= secs * NSEC_PER_SEC;
689795
690
- if (nanosecs)
796
+ if (symbol_conf.nanosecs)
691797 printed += fprintf(fp, "%5lu.%09llu: ", secs, nsecs);
692798 else {
693799 char sample_time[32];
694
- timestamp__scnprintf_usec(sample->time, sample_time, sizeof(sample_time));
800
+ timestamp__scnprintf_usec(t, sample_time, sizeof(sample_time));
695801 printed += fprintf(fp, "%12s: ", sample_time);
696802 }
697803 }
....@@ -713,6 +819,7 @@
713819 struct perf_event_attr *attr, FILE *fp)
714820 {
715821 struct branch_stack *br = sample->branch_stack;
822
+ struct branch_entry *entries = perf_sample__branch_entries(sample);
716823 struct addr_location alf, alt;
717824 u64 i, from, to;
718825 int printed = 0;
....@@ -721,8 +828,8 @@
721828 return 0;
722829
723830 for (i = 0; i < br->nr; i++) {
724
- from = br->entries[i].from;
725
- to = br->entries[i].to;
831
+ from = entries[i].from;
832
+ to = entries[i].to;
726833
727834 if (PRINT_FIELD(DSO)) {
728835 memset(&alf, 0, sizeof(alf));
....@@ -746,10 +853,10 @@
746853 }
747854
748855 printed += fprintf(fp, "/%c/%c/%c/%d ",
749
- mispred_str( br->entries + i),
750
- br->entries[i].flags.in_tx? 'X' : '-',
751
- br->entries[i].flags.abort? 'A' : '-',
752
- br->entries[i].flags.cycles);
856
+ mispred_str(entries + i),
857
+ entries[i].flags.in_tx ? 'X' : '-',
858
+ entries[i].flags.abort ? 'A' : '-',
859
+ entries[i].flags.cycles);
753860 }
754861
755862 return printed;
....@@ -760,6 +867,7 @@
760867 struct perf_event_attr *attr, FILE *fp)
761868 {
762869 struct branch_stack *br = sample->branch_stack;
870
+ struct branch_entry *entries = perf_sample__branch_entries(sample);
763871 struct addr_location alf, alt;
764872 u64 i, from, to;
765873 int printed = 0;
....@@ -771,8 +879,8 @@
771879
772880 memset(&alf, 0, sizeof(alf));
773881 memset(&alt, 0, sizeof(alt));
774
- from = br->entries[i].from;
775
- to = br->entries[i].to;
882
+ from = entries[i].from;
883
+ to = entries[i].to;
776884
777885 thread__find_symbol_fb(thread, sample->cpumode, from, &alf);
778886 thread__find_symbol_fb(thread, sample->cpumode, to, &alt);
....@@ -791,10 +899,10 @@
791899 printed += fprintf(fp, ")");
792900 }
793901 printed += fprintf(fp, "/%c/%c/%c/%d ",
794
- mispred_str( br->entries + i),
795
- br->entries[i].flags.in_tx? 'X' : '-',
796
- br->entries[i].flags.abort? 'A' : '-',
797
- br->entries[i].flags.cycles);
902
+ mispred_str(entries + i),
903
+ entries[i].flags.in_tx ? 'X' : '-',
904
+ entries[i].flags.abort ? 'A' : '-',
905
+ entries[i].flags.cycles);
798906 }
799907
800908 return printed;
....@@ -805,6 +913,7 @@
805913 struct perf_event_attr *attr, FILE *fp)
806914 {
807915 struct branch_stack *br = sample->branch_stack;
916
+ struct branch_entry *entries = perf_sample__branch_entries(sample);
808917 struct addr_location alf, alt;
809918 u64 i, from, to;
810919 int printed = 0;
....@@ -816,8 +925,8 @@
816925
817926 memset(&alf, 0, sizeof(alf));
818927 memset(&alt, 0, sizeof(alt));
819
- from = br->entries[i].from;
820
- to = br->entries[i].to;
928
+ from = entries[i].from;
929
+ to = entries[i].to;
821930
822931 if (thread__find_map_fb(thread, sample->cpumode, from, &alf) &&
823932 !alf.map->dso->adjust_symbols)
....@@ -840,10 +949,10 @@
840949 printed += fprintf(fp, ")");
841950 }
842951 printed += fprintf(fp, "/%c/%c/%c/%d ",
843
- mispred_str(br->entries + i),
844
- br->entries[i].flags.in_tx ? 'X' : '-',
845
- br->entries[i].flags.abort ? 'A' : '-',
846
- br->entries[i].flags.cycles);
952
+ mispred_str(entries + i),
953
+ entries[i].flags.in_tx ? 'X' : '-',
954
+ entries[i].flags.abort ? 'A' : '-',
955
+ entries[i].flags.cycles);
847956 }
848957
849958 return printed;
....@@ -910,9 +1019,67 @@
9101019 return len;
9111020 }
9121021
1022
+static int map__fprintf_srccode(struct map *map, u64 addr, FILE *fp, struct srccode_state *state)
1023
+{
1024
+ char *srcfile;
1025
+ int ret = 0;
1026
+ unsigned line;
1027
+ int len;
1028
+ char *srccode;
1029
+
1030
+ if (!map || !map->dso)
1031
+ return 0;
1032
+ srcfile = get_srcline_split(map->dso,
1033
+ map__rip_2objdump(map, addr),
1034
+ &line);
1035
+ if (!srcfile)
1036
+ return 0;
1037
+
1038
+ /* Avoid redundant printing */
1039
+ if (state &&
1040
+ state->srcfile &&
1041
+ !strcmp(state->srcfile, srcfile) &&
1042
+ state->line == line) {
1043
+ free(srcfile);
1044
+ return 0;
1045
+ }
1046
+
1047
+ srccode = find_sourceline(srcfile, line, &len);
1048
+ if (!srccode)
1049
+ goto out_free_line;
1050
+
1051
+ ret = fprintf(fp, "|%-8d %.*s", line, len, srccode);
1052
+
1053
+ if (state) {
1054
+ state->srcfile = srcfile;
1055
+ state->line = line;
1056
+ }
1057
+ return ret;
1058
+
1059
+out_free_line:
1060
+ free(srcfile);
1061
+ return ret;
1062
+}
1063
+
1064
+static int print_srccode(struct thread *thread, u8 cpumode, uint64_t addr)
1065
+{
1066
+ struct addr_location al;
1067
+ int ret = 0;
1068
+
1069
+ memset(&al, 0, sizeof(al));
1070
+ thread__find_map(thread, cpumode, addr, &al);
1071
+ if (!al.map)
1072
+ return 0;
1073
+ ret = map__fprintf_srccode(al.map, al.addr, stdout,
1074
+ &thread->srccode_state);
1075
+ if (ret)
1076
+ ret += printf("\n");
1077
+ return ret;
1078
+}
1079
+
9131080 static int ip__fprintf_jump(uint64_t ip, struct branch_entry *en,
9141081 struct perf_insn *x, u8 *inbuf, int len,
915
- int insn, FILE *fp)
1082
+ int insn, FILE *fp, int *total_cycles)
9161083 {
9171084 int printed = fprintf(fp, "\t%016" PRIx64 "\t%-30s\t#%s%s%s%s", ip,
9181085 dump_insn(x, ip, inbuf, len, NULL),
....@@ -921,7 +1088,8 @@
9211088 en->flags.in_tx ? " INTX" : "",
9221089 en->flags.abort ? " ABORT" : "");
9231090 if (en->flags.cycles) {
924
- printed += fprintf(fp, " %d cycles", en->flags.cycles);
1091
+ *total_cycles += en->flags.cycles;
1092
+ printed += fprintf(fp, " %d cycles [%d]", en->flags.cycles, *total_cycles);
9251093 if (insn)
9261094 printed += fprintf(fp, " %.2f IPC", (float)insn / en->flags.cycles);
9271095 }
....@@ -972,12 +1140,14 @@
9721140 struct machine *machine, FILE *fp)
9731141 {
9741142 struct branch_stack *br = sample->branch_stack;
1143
+ struct branch_entry *entries = perf_sample__branch_entries(sample);
9751144 u64 start, end;
9761145 int i, insn, len, nr, ilen, printed = 0;
9771146 struct perf_insn x;
9781147 u8 buffer[MAXBB];
9791148 unsigned off;
9801149 struct symbol *lastsym = NULL;
1150
+ int total_cycles = 0;
9811151
9821152 if (!(br && br->nr))
9831153 return 0;
....@@ -991,29 +1161,31 @@
9911161 printed += fprintf(fp, "%c", '\n');
9921162
9931163 /* Handle first from jump, of which we don't know the entry. */
994
- len = grab_bb(buffer, br->entries[nr-1].from,
995
- br->entries[nr-1].from,
1164
+ len = grab_bb(buffer, entries[nr-1].from,
1165
+ entries[nr-1].from,
9961166 machine, thread, &x.is64bit, &x.cpumode, false);
9971167 if (len > 0) {
998
- printed += ip__fprintf_sym(br->entries[nr - 1].from, thread,
1168
+ printed += ip__fprintf_sym(entries[nr - 1].from, thread,
9991169 x.cpumode, x.cpu, &lastsym, attr, fp);
1000
- printed += ip__fprintf_jump(br->entries[nr - 1].from, &br->entries[nr - 1],
1001
- &x, buffer, len, 0, fp);
1170
+ printed += ip__fprintf_jump(entries[nr - 1].from, &entries[nr - 1],
1171
+ &x, buffer, len, 0, fp, &total_cycles);
1172
+ if (PRINT_FIELD(SRCCODE))
1173
+ printed += print_srccode(thread, x.cpumode, entries[nr - 1].from);
10021174 }
10031175
10041176 /* Print all blocks */
10051177 for (i = nr - 2; i >= 0; i--) {
1006
- if (br->entries[i].from || br->entries[i].to)
1178
+ if (entries[i].from || entries[i].to)
10071179 pr_debug("%d: %" PRIx64 "-%" PRIx64 "\n", i,
1008
- br->entries[i].from,
1009
- br->entries[i].to);
1010
- start = br->entries[i + 1].to;
1011
- end = br->entries[i].from;
1180
+ entries[i].from,
1181
+ entries[i].to);
1182
+ start = entries[i + 1].to;
1183
+ end = entries[i].from;
10121184
10131185 len = grab_bb(buffer, start, end, machine, thread, &x.is64bit, &x.cpumode, false);
10141186 /* Patch up missing kernel transfers due to ring filters */
10151187 if (len == -ENXIO && i > 0) {
1016
- end = br->entries[--i].from;
1188
+ end = entries[--i].from;
10171189 pr_debug("\tpatching up to %" PRIx64 "-%" PRIx64 "\n", start, end);
10181190 len = grab_bb(buffer, start, end, machine, thread, &x.is64bit, &x.cpumode, false);
10191191 }
....@@ -1026,7 +1198,10 @@
10261198
10271199 printed += ip__fprintf_sym(ip, thread, x.cpumode, x.cpu, &lastsym, attr, fp);
10281200 if (ip == end) {
1029
- printed += ip__fprintf_jump(ip, &br->entries[i], &x, buffer + off, len - off, insn, fp);
1201
+ printed += ip__fprintf_jump(ip, &entries[i], &x, buffer + off, len - off, ++insn, fp,
1202
+ &total_cycles);
1203
+ if (PRINT_FIELD(SRCCODE))
1204
+ printed += print_srccode(thread, x.cpumode, ip);
10301205 break;
10311206 } else {
10321207 ilen = 0;
....@@ -1034,6 +1209,8 @@
10341209 dump_insn(&x, ip, buffer + off, len - off, &ilen));
10351210 if (ilen == 0)
10361211 break;
1212
+ if (PRINT_FIELD(SRCCODE))
1213
+ print_srccode(thread, x.cpumode, ip);
10371214 insn++;
10381215 }
10391216 }
....@@ -1045,16 +1222,25 @@
10451222 * Hit the branch? In this case we are already done, and the target
10461223 * has not been executed yet.
10471224 */
1048
- if (br->entries[0].from == sample->ip)
1225
+ if (entries[0].from == sample->ip)
10491226 goto out;
1050
- if (br->entries[0].flags.abort)
1227
+ if (entries[0].flags.abort)
10511228 goto out;
10521229
10531230 /*
10541231 * Print final block upto sample
1232
+ *
1233
+ * Due to pipeline delays the LBRs might be missing a branch
1234
+ * or two, which can result in very large or negative blocks
1235
+ * between final branch and sample. When this happens just
1236
+ * continue walking after the last TO until we hit a branch.
10551237 */
1056
- start = br->entries[0].to;
1238
+ start = entries[0].to;
10571239 end = sample->ip;
1240
+ if (end < start) {
1241
+ /* Missing jump. Scan 128 bytes for the next branch */
1242
+ end = start + 128;
1243
+ }
10581244 len = grab_bb(buffer, start, end, machine, thread, &x.is64bit, &x.cpumode, true);
10591245 printed += ip__fprintf_sym(start, thread, x.cpumode, x.cpu, &lastsym, attr, fp);
10601246 if (len <= 0) {
....@@ -1063,9 +1249,10 @@
10631249 machine, thread, &x.is64bit, &x.cpumode, false);
10641250 if (len <= 0)
10651251 goto out;
1066
-
10671252 printed += fprintf(fp, "\t%016" PRIx64 "\t%s\n", sample->ip,
10681253 dump_insn(&x, sample->ip, buffer, len, NULL));
1254
+ if (PRINT_FIELD(SRCCODE))
1255
+ print_srccode(thread, x.cpumode, sample->ip);
10691256 goto out;
10701257 }
10711258 for (off = 0; off <= end - start; off += ilen) {
....@@ -1074,6 +1261,15 @@
10741261 dump_insn(&x, start + off, buffer + off, len - off, &ilen));
10751262 if (ilen == 0)
10761263 break;
1264
+ if (arch_is_branch(buffer + off, len - off, x.is64bit) && start + off != sample->ip) {
1265
+ /*
1266
+ * Hit a missing branch. Just stop.
1267
+ */
1268
+ printed += fprintf(fp, "\t... not reaching sample ...\n");
1269
+ break;
1270
+ }
1271
+ if (PRINT_FIELD(SRCCODE))
1272
+ print_srccode(thread, x.cpumode, start + off);
10771273 }
10781274 out:
10791275 return printed;
....@@ -1108,17 +1304,46 @@
11081304 return printed;
11091305 }
11101306
1307
+static const char *resolve_branch_sym(struct perf_sample *sample,
1308
+ struct evsel *evsel,
1309
+ struct thread *thread,
1310
+ struct addr_location *al,
1311
+ u64 *ip)
1312
+{
1313
+ struct addr_location addr_al;
1314
+ struct perf_event_attr *attr = &evsel->core.attr;
1315
+ const char *name = NULL;
1316
+
1317
+ if (sample->flags & (PERF_IP_FLAG_CALL | PERF_IP_FLAG_TRACE_BEGIN)) {
1318
+ if (sample_addr_correlates_sym(attr)) {
1319
+ thread__resolve(thread, &addr_al, sample);
1320
+ if (addr_al.sym)
1321
+ name = addr_al.sym->name;
1322
+ else
1323
+ *ip = sample->addr;
1324
+ } else {
1325
+ *ip = sample->addr;
1326
+ }
1327
+ } else if (sample->flags & (PERF_IP_FLAG_RETURN | PERF_IP_FLAG_TRACE_END)) {
1328
+ if (al->sym)
1329
+ name = al->sym->name;
1330
+ else
1331
+ *ip = sample->ip;
1332
+ }
1333
+ return name;
1334
+}
1335
+
11111336 static int perf_sample__fprintf_callindent(struct perf_sample *sample,
1112
- struct perf_evsel *evsel,
1337
+ struct evsel *evsel,
11131338 struct thread *thread,
11141339 struct addr_location *al, FILE *fp)
11151340 {
1116
- struct perf_event_attr *attr = &evsel->attr;
1117
- size_t depth = thread_stack__depth(thread);
1118
- struct addr_location addr_al;
1341
+ struct perf_event_attr *attr = &evsel->core.attr;
1342
+ size_t depth = thread_stack__depth(thread, sample->cpu);
11191343 const char *name = NULL;
11201344 static int spacing;
11211345 int len = 0;
1346
+ int dlen = 0;
11221347 u64 ip = 0;
11231348
11241349 /*
....@@ -1128,21 +1353,12 @@
11281353 if (thread->ts && sample->flags & PERF_IP_FLAG_RETURN)
11291354 depth += 1;
11301355
1131
- if (sample->flags & (PERF_IP_FLAG_CALL | PERF_IP_FLAG_TRACE_BEGIN)) {
1132
- if (sample_addr_correlates_sym(attr)) {
1133
- thread__resolve(thread, &addr_al, sample);
1134
- if (addr_al.sym)
1135
- name = addr_al.sym->name;
1136
- else
1137
- ip = sample->addr;
1138
- } else {
1139
- ip = sample->addr;
1140
- }
1141
- } else if (sample->flags & (PERF_IP_FLAG_RETURN | PERF_IP_FLAG_TRACE_END)) {
1142
- if (al->sym)
1143
- name = al->sym->name;
1144
- else
1145
- ip = sample->ip;
1356
+ name = resolve_branch_sym(sample, evsel, thread, al, &ip);
1357
+
1358
+ if (PRINT_FIELD(DSO) && !(PRINT_FIELD(IP) || PRINT_FIELD(ADDR))) {
1359
+ dlen += fprintf(fp, "(");
1360
+ dlen += map__fprintf_dsoname(al->map, fp);
1361
+ dlen += fprintf(fp, ")\t");
11461362 }
11471363
11481364 if (name)
....@@ -1163,7 +1379,13 @@
11631379 if (len < spacing)
11641380 len += fprintf(fp, "%*s", spacing - len, "");
11651381
1166
- return len;
1382
+ return len + dlen;
1383
+}
1384
+
1385
+__weak void arch_fetch_insn(struct perf_sample *sample __maybe_unused,
1386
+ struct thread *thread __maybe_unused,
1387
+ struct machine *machine __maybe_unused)
1388
+{
11671389 }
11681390
11691391 static int perf_sample__fprintf_insn(struct perf_sample *sample,
....@@ -1173,9 +1395,12 @@
11731395 {
11741396 int printed = 0;
11751397
1398
+ if (sample->insn_len == 0 && native_arch)
1399
+ arch_fetch_insn(sample, thread, machine);
1400
+
11761401 if (PRINT_FIELD(INSNLEN))
11771402 printed += fprintf(fp, " ilen: %d", sample->insn_len);
1178
- if (PRINT_FIELD(INSN)) {
1403
+ if (PRINT_FIELD(INSN) && sample->insn_len) {
11791404 int i;
11801405
11811406 printed += fprintf(fp, " insn:");
....@@ -1188,13 +1413,27 @@
11881413 return printed;
11891414 }
11901415
1416
+static int perf_sample__fprintf_ipc(struct perf_sample *sample,
1417
+ struct perf_event_attr *attr, FILE *fp)
1418
+{
1419
+ unsigned int ipc;
1420
+
1421
+ if (!PRINT_FIELD(IPC) || !sample->cyc_cnt || !sample->insn_cnt)
1422
+ return 0;
1423
+
1424
+ ipc = (sample->insn_cnt * 100) / sample->cyc_cnt;
1425
+
1426
+ return fprintf(fp, " \t IPC: %u.%02u (%" PRIu64 "/%" PRIu64 ") ",
1427
+ ipc / 100, ipc % 100, sample->insn_cnt, sample->cyc_cnt);
1428
+}
1429
+
11911430 static int perf_sample__fprintf_bts(struct perf_sample *sample,
1192
- struct perf_evsel *evsel,
1431
+ struct evsel *evsel,
11931432 struct thread *thread,
11941433 struct addr_location *al,
11951434 struct machine *machine, FILE *fp)
11961435 {
1197
- struct perf_event_attr *attr = &evsel->attr;
1436
+ struct perf_event_attr *attr = &evsel->core.attr;
11981437 unsigned int type = output_type(attr->type);
11991438 bool print_srcline_last = false;
12001439 int printed = 0;
....@@ -1221,22 +1460,34 @@
12211460 } else
12221461 printed += fprintf(fp, "\n");
12231462
1224
- printed += sample__fprintf_sym(sample, al, 0, print_opts, cursor, fp);
1463
+ printed += sample__fprintf_sym(sample, al, 0, print_opts, cursor,
1464
+ symbol_conf.bt_stop_list, fp);
12251465 }
12261466
12271467 /* print branch_to information */
12281468 if (PRINT_FIELD(ADDR) ||
1229
- ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) &&
1469
+ ((evsel->core.attr.sample_type & PERF_SAMPLE_ADDR) &&
12301470 !output[type].user_set)) {
12311471 printed += fprintf(fp, " => ");
12321472 printed += perf_sample__fprintf_addr(sample, thread, attr, fp);
12331473 }
12341474
1475
+ printed += perf_sample__fprintf_ipc(sample, attr, fp);
1476
+
12351477 if (print_srcline_last)
12361478 printed += map__fprintf_srcline(al->map, al->addr, "\n ", fp);
12371479
12381480 printed += perf_sample__fprintf_insn(sample, attr, thread, machine, fp);
1239
- return printed + fprintf(fp, "\n");
1481
+ printed += fprintf(fp, "\n");
1482
+ if (PRINT_FIELD(SRCCODE)) {
1483
+ int ret = map__fprintf_srccode(al->map, al->addr, stdout,
1484
+ &thread->srccode_state);
1485
+ if (ret) {
1486
+ printed += ret;
1487
+ printed += printf("\n");
1488
+ }
1489
+ }
1490
+ return printed;
12401491 }
12411492
12421493 static struct {
....@@ -1259,6 +1510,18 @@
12591510 {0, NULL}
12601511 };
12611512
1513
+static const char *sample_flags_to_name(u32 flags)
1514
+{
1515
+ int i;
1516
+
1517
+ for (i = 0; sample_flags[i].name ; i++) {
1518
+ if (sample_flags[i].flags == flags)
1519
+ return sample_flags[i].name;
1520
+ }
1521
+
1522
+ return NULL;
1523
+}
1524
+
12621525 static int perf_sample__fprintf_flags(u32 flags, FILE *fp)
12631526 {
12641527 const char *chars = PERF_IP_FLAG_CHARS;
....@@ -1268,11 +1531,20 @@
12681531 char str[33];
12691532 int i, pos = 0;
12701533
1271
- for (i = 0; sample_flags[i].name ; i++) {
1272
- if (sample_flags[i].flags == (flags & ~PERF_IP_FLAG_IN_TX)) {
1273
- name = sample_flags[i].name;
1274
- break;
1275
- }
1534
+ name = sample_flags_to_name(flags & ~PERF_IP_FLAG_IN_TX);
1535
+ if (name)
1536
+ return fprintf(fp, " %-15s%4s ", name, in_tx ? "(x)" : "");
1537
+
1538
+ if (flags & PERF_IP_FLAG_TRACE_BEGIN) {
1539
+ name = sample_flags_to_name(flags & ~(PERF_IP_FLAG_IN_TX | PERF_IP_FLAG_TRACE_BEGIN));
1540
+ if (name)
1541
+ return fprintf(fp, " tr strt %-7s%4s ", name, in_tx ? "(x)" : "");
1542
+ }
1543
+
1544
+ if (flags & PERF_IP_FLAG_TRACE_END) {
1545
+ name = sample_flags_to_name(flags & ~(PERF_IP_FLAG_IN_TX | PERF_IP_FLAG_TRACE_END));
1546
+ if (name)
1547
+ return fprintf(fp, " tr end %-7s%4s ", name, in_tx ? "(x)" : "");
12761548 }
12771549
12781550 for (i = 0; i < n; i++, flags >>= 1) {
....@@ -1285,10 +1557,7 @@
12851557 }
12861558 str[pos] = 0;
12871559
1288
- if (name)
1289
- return fprintf(fp, " %-7s%4s ", name, in_tx ? "(x)" : "");
1290
-
1291
- return fprintf(fp, " %-11s ", str);
1560
+ return fprintf(fp, " %-19s ", str);
12921561 }
12931562
12941563 struct printer_data {
....@@ -1468,9 +1737,9 @@
14681737 }
14691738
14701739 static int perf_sample__fprintf_synth(struct perf_sample *sample,
1471
- struct perf_evsel *evsel, FILE *fp)
1740
+ struct evsel *evsel, FILE *fp)
14721741 {
1473
- switch (evsel->attr.config) {
1742
+ switch (evsel->core.attr.config) {
14741743 case PERF_SYNTH_INTEL_PTWRITE:
14751744 return perf_sample__fprintf_synth_ptwrite(sample, fp);
14761745 case PERF_SYNTH_INTEL_MWAIT:
....@@ -1490,33 +1759,13 @@
14901759 return 0;
14911760 }
14921761
1493
-struct perf_script {
1494
- struct perf_tool tool;
1495
- struct perf_session *session;
1496
- bool show_task_events;
1497
- bool show_mmap_events;
1498
- bool show_switch_events;
1499
- bool show_namespace_events;
1500
- bool show_lost_events;
1501
- bool show_round_events;
1502
- bool allocated;
1503
- bool per_event_dump;
1504
- struct cpu_map *cpus;
1505
- struct thread_map *threads;
1506
- int name_width;
1507
- const char *time_str;
1508
- struct perf_time_interval *ptime_range;
1509
- int range_size;
1510
- int range_num;
1511
-};
1512
-
1513
-static int perf_evlist__max_name_len(struct perf_evlist *evlist)
1762
+static int evlist__max_name_len(struct evlist *evlist)
15141763 {
1515
- struct perf_evsel *evsel;
1764
+ struct evsel *evsel;
15161765 int max = 0;
15171766
15181767 evlist__for_each_entry(evlist, evsel) {
1519
- int len = strlen(perf_evsel__name(evsel));
1768
+ int len = strlen(evsel__name(evsel));
15201769
15211770 max = MAX(len, max);
15221771 }
....@@ -1544,11 +1793,12 @@
15441793 struct metric_ctx {
15451794 struct perf_sample *sample;
15461795 struct thread *thread;
1547
- struct perf_evsel *evsel;
1796
+ struct evsel *evsel;
15481797 FILE *fp;
15491798 };
15501799
1551
-static void script_print_metric(void *ctx, const char *color,
1800
+static void script_print_metric(struct perf_stat_config *config __maybe_unused,
1801
+ void *ctx, const char *color,
15521802 const char *fmt,
15531803 const char *unit, double val)
15541804 {
....@@ -1556,7 +1806,7 @@
15561806
15571807 if (!fmt)
15581808 return;
1559
- perf_sample__fprintf_start(mctx->sample, mctx->thread, mctx->evsel,
1809
+ perf_sample__fprintf_start(NULL, mctx->sample, mctx->thread, mctx->evsel,
15601810 PERF_RECORD_SAMPLE, mctx->fp);
15611811 fputs("\tmetric: ", mctx->fp);
15621812 if (color)
....@@ -1566,18 +1816,19 @@
15661816 fprintf(mctx->fp, " %s\n", unit);
15671817 }
15681818
1569
-static void script_new_line(void *ctx)
1819
+static void script_new_line(struct perf_stat_config *config __maybe_unused,
1820
+ void *ctx)
15701821 {
15711822 struct metric_ctx *mctx = ctx;
15721823
1573
- perf_sample__fprintf_start(mctx->sample, mctx->thread, mctx->evsel,
1824
+ perf_sample__fprintf_start(NULL, mctx->sample, mctx->thread, mctx->evsel,
15741825 PERF_RECORD_SAMPLE, mctx->fp);
15751826 fputs("\tmetric: ", mctx->fp);
15761827 }
15771828
15781829 static void perf_sample__fprint_metric(struct perf_script *script,
15791830 struct thread *thread,
1580
- struct perf_evsel *evsel,
1831
+ struct evsel *evsel,
15811832 struct perf_sample *sample,
15821833 FILE *fp)
15831834 {
....@@ -1592,7 +1843,7 @@
15921843 },
15931844 .force_header = false,
15941845 };
1595
- struct perf_evsel *ev2;
1846
+ struct evsel *ev2;
15961847 u64 val;
15971848
15981849 if (!evsel->stats)
....@@ -1605,9 +1856,9 @@
16051856 sample->cpu,
16061857 &rt_stat);
16071858 evsel_script(evsel)->val = val;
1608
- if (evsel_script(evsel->leader)->gnum == evsel->leader->nr_members) {
1859
+ if (evsel_script(evsel->leader)->gnum == evsel->leader->core.nr_members) {
16091860 for_each_group_member (ev2, evsel->leader) {
1610
- perf_stat__print_shadow_stats(ev2,
1861
+ perf_stat__print_shadow_stats(&stat_config, ev2,
16111862 evsel_script(ev2)->val,
16121863 sample->cpu,
16131864 &ctx,
....@@ -1618,33 +1869,80 @@
16181869 }
16191870 }
16201871
1872
+static bool show_event(struct perf_sample *sample,
1873
+ struct evsel *evsel,
1874
+ struct thread *thread,
1875
+ struct addr_location *al)
1876
+{
1877
+ int depth = thread_stack__depth(thread, sample->cpu);
1878
+
1879
+ if (!symbol_conf.graph_function)
1880
+ return true;
1881
+
1882
+ if (thread->filter) {
1883
+ if (depth <= thread->filter_entry_depth) {
1884
+ thread->filter = false;
1885
+ return false;
1886
+ }
1887
+ return true;
1888
+ } else {
1889
+ const char *s = symbol_conf.graph_function;
1890
+ u64 ip;
1891
+ const char *name = resolve_branch_sym(sample, evsel, thread, al,
1892
+ &ip);
1893
+ unsigned nlen;
1894
+
1895
+ if (!name)
1896
+ return false;
1897
+ nlen = strlen(name);
1898
+ while (*s) {
1899
+ unsigned len = strcspn(s, ",");
1900
+ if (nlen == len && !strncmp(name, s, len)) {
1901
+ thread->filter = true;
1902
+ thread->filter_entry_depth = depth;
1903
+ return true;
1904
+ }
1905
+ s += len;
1906
+ if (*s == ',')
1907
+ s++;
1908
+ }
1909
+ return false;
1910
+ }
1911
+}
1912
+
16211913 static void process_event(struct perf_script *script,
1622
- struct perf_sample *sample, struct perf_evsel *evsel,
1914
+ struct perf_sample *sample, struct evsel *evsel,
16231915 struct addr_location *al,
16241916 struct machine *machine)
16251917 {
16261918 struct thread *thread = al->thread;
1627
- struct perf_event_attr *attr = &evsel->attr;
1919
+ struct perf_event_attr *attr = &evsel->core.attr;
16281920 unsigned int type = output_type(attr->type);
1629
- struct perf_evsel_script *es = evsel->priv;
1921
+ struct evsel_script *es = evsel->priv;
16301922 FILE *fp = es->fp;
16311923
16321924 if (output[type].fields == 0)
16331925 return;
16341926
1927
+ if (!show_event(sample, evsel, thread, al))
1928
+ return;
1929
+
1930
+ if (evswitch__discard(&script->evswitch, evsel))
1931
+ return;
1932
+
16351933 ++es->samples;
16361934
1637
- perf_sample__fprintf_start(sample, thread, evsel,
1935
+ perf_sample__fprintf_start(script, sample, thread, evsel,
16381936 PERF_RECORD_SAMPLE, fp);
16391937
16401938 if (PRINT_FIELD(PERIOD))
16411939 fprintf(fp, "%10" PRIu64 " ", sample->period);
16421940
16431941 if (PRINT_FIELD(EVNAME)) {
1644
- const char *evname = perf_evsel__name(evsel);
1942
+ const char *evname = evsel__name(evsel);
16451943
16461944 if (!script->name_width)
1647
- script->name_width = perf_evlist__max_name_len(script->session->evlist);
1945
+ script->name_width = evlist__max_name_len(script->session->evlist);
16481946
16491947 fprintf(fp, "%*s: ", script->name_width, evname ?: "[unknown]");
16501948 }
....@@ -1677,13 +1975,17 @@
16771975 if (PRINT_FIELD(IP)) {
16781976 struct callchain_cursor *cursor = NULL;
16791977
1978
+ if (script->stitch_lbr)
1979
+ al->thread->lbr_stitch_enable = true;
1980
+
16801981 if (symbol_conf.use_callchain && sample->callchain &&
16811982 thread__resolve_callchain(al->thread, &callchain_cursor, evsel,
16821983 sample, NULL, NULL, scripting_max_stack) == 0)
16831984 cursor = &callchain_cursor;
16841985
16851986 fputc(cursor ? '\n' : ' ', fp);
1686
- sample__fprintf_sym(sample, al, 0, output[type].print_ip_opts, cursor, fp);
1987
+ sample__fprintf_sym(sample, al, 0, output[type].print_ip_opts, cursor,
1988
+ symbol_conf.bt_stop_list, fp);
16871989 }
16881990
16891991 if (PRINT_FIELD(IREGS))
....@@ -1699,28 +2001,40 @@
16992001 else if (PRINT_FIELD(BRSTACKOFF))
17002002 perf_sample__fprintf_brstackoff(sample, thread, attr, fp);
17012003
1702
- if (perf_evsel__is_bpf_output(evsel) && PRINT_FIELD(BPF_OUTPUT))
2004
+ if (evsel__is_bpf_output(evsel) && PRINT_FIELD(BPF_OUTPUT))
17032005 perf_sample__fprintf_bpf_output(sample, fp);
17042006 perf_sample__fprintf_insn(sample, attr, thread, machine, fp);
17052007
17062008 if (PRINT_FIELD(PHYS_ADDR))
17072009 fprintf(fp, "%16" PRIx64, sample->phys_addr);
2010
+
2011
+ perf_sample__fprintf_ipc(sample, attr, fp);
2012
+
17082013 fprintf(fp, "\n");
2014
+
2015
+ if (PRINT_FIELD(SRCCODE)) {
2016
+ if (map__fprintf_srccode(al->map, al->addr, stdout,
2017
+ &thread->srccode_state))
2018
+ printf("\n");
2019
+ }
17092020
17102021 if (PRINT_FIELD(METRIC))
17112022 perf_sample__fprint_metric(script, thread, evsel, sample, fp);
2023
+
2024
+ if (verbose)
2025
+ fflush(fp);
17122026 }
17132027
17142028 static struct scripting_ops *scripting_ops;
17152029
1716
-static void __process_stat(struct perf_evsel *counter, u64 tstamp)
2030
+static void __process_stat(struct evsel *counter, u64 tstamp)
17172031 {
1718
- int nthreads = thread_map__nr(counter->threads);
1719
- int ncpus = perf_evsel__nr_cpus(counter);
2032
+ int nthreads = perf_thread_map__nr(counter->core.threads);
2033
+ int ncpus = evsel__nr_cpus(counter);
17202034 int cpu, thread;
17212035 static int header_printed;
17222036
1723
- if (counter->system_wide)
2037
+ if (counter->core.system_wide)
17242038 nthreads = 1;
17252039
17262040 if (!header_printed) {
....@@ -1736,18 +2050,18 @@
17362050 counts = perf_counts(counter->counts, cpu, thread);
17372051
17382052 printf("%3d %8d %15" PRIu64 " %15" PRIu64 " %15" PRIu64 " %15" PRIu64 " %s\n",
1739
- counter->cpus->map[cpu],
1740
- thread_map__pid(counter->threads, thread),
2053
+ counter->core.cpus->map[cpu],
2054
+ perf_thread_map__pid(counter->core.threads, thread),
17412055 counts->val,
17422056 counts->ena,
17432057 counts->run,
17442058 tstamp,
1745
- perf_evsel__name(counter));
2059
+ evsel__name(counter));
17462060 }
17472061 }
17482062 }
17492063
1750
-static void process_stat(struct perf_evsel *counter, u64 tstamp)
2064
+static void process_stat(struct evsel *counter, u64 tstamp)
17512065 {
17522066 if (scripting_ops && scripting_ops->process_stat)
17532067 scripting_ops->process_stat(&stat_config, counter, tstamp);
....@@ -1779,10 +2093,17 @@
17792093 return scripting_ops ? scripting_ops->stop_script() : 0;
17802094 }
17812095
2096
+static bool filter_cpu(struct perf_sample *sample)
2097
+{
2098
+ if (cpu_list && sample->cpu != (u32)-1)
2099
+ return !test_bit(sample->cpu, cpu_bitmap);
2100
+ return false;
2101
+}
2102
+
17822103 static int process_sample_event(struct perf_tool *tool,
17832104 union perf_event *event,
17842105 struct perf_sample *sample,
1785
- struct perf_evsel *evsel,
2106
+ struct evsel *evsel,
17862107 struct machine *machine)
17872108 {
17882109 struct perf_script *scr = container_of(tool, struct perf_script, tool);
....@@ -1813,7 +2134,7 @@
18132134 if (al.filtered)
18142135 goto out_put;
18152136
1816
- if (cpu_list && !test_bit(sample->cpu, cpu_bitmap))
2137
+ if (filter_cpu(sample))
18172138 goto out_put;
18182139
18192140 if (scripting_ops)
....@@ -1827,20 +2148,21 @@
18272148 }
18282149
18292150 static int process_attr(struct perf_tool *tool, union perf_event *event,
1830
- struct perf_evlist **pevlist)
2151
+ struct evlist **pevlist)
18312152 {
18322153 struct perf_script *scr = container_of(tool, struct perf_script, tool);
1833
- struct perf_evlist *evlist;
1834
- struct perf_evsel *evsel, *pos;
2154
+ struct evlist *evlist;
2155
+ struct evsel *evsel, *pos;
2156
+ u64 sample_type;
18352157 int err;
1836
- static struct perf_evsel_script *es;
2158
+ static struct evsel_script *es;
18372159
18382160 err = perf_event__process_attr(tool, event, pevlist);
18392161 if (err)
18402162 return err;
18412163
18422164 evlist = *pevlist;
1843
- evsel = perf_evlist__last(*pevlist);
2165
+ evsel = evlist__last(*pevlist);
18442166
18452167 if (!evsel->priv) {
18462168 if (scr->per_event_dump) {
....@@ -1855,21 +2177,86 @@
18552177 }
18562178 }
18572179
1858
- if (evsel->attr.type >= PERF_TYPE_MAX &&
1859
- evsel->attr.type != PERF_TYPE_SYNTH)
2180
+ if (evsel->core.attr.type >= PERF_TYPE_MAX &&
2181
+ evsel->core.attr.type != PERF_TYPE_SYNTH)
18602182 return 0;
18612183
18622184 evlist__for_each_entry(evlist, pos) {
1863
- if (pos->attr.type == evsel->attr.type && pos != evsel)
2185
+ if (pos->core.attr.type == evsel->core.attr.type && pos != evsel)
18642186 return 0;
18652187 }
18662188
1867
- set_print_ip_opts(&evsel->attr);
2189
+ if (evsel->core.attr.sample_type) {
2190
+ err = evsel__check_attr(evsel, scr->session);
2191
+ if (err)
2192
+ return err;
2193
+ }
18682194
1869
- if (evsel->attr.sample_type)
1870
- err = perf_evsel__check_attr(evsel, scr->session);
2195
+ /*
2196
+ * Check if we need to enable callchains based
2197
+ * on events sample_type.
2198
+ */
2199
+ sample_type = evlist__combined_sample_type(evlist);
2200
+ callchain_param_setup(sample_type);
18712201
1872
- return err;
2202
+ /* Enable fields for callchain entries */
2203
+ if (symbol_conf.use_callchain &&
2204
+ (sample_type & PERF_SAMPLE_CALLCHAIN ||
2205
+ sample_type & PERF_SAMPLE_BRANCH_STACK ||
2206
+ (sample_type & PERF_SAMPLE_REGS_USER &&
2207
+ sample_type & PERF_SAMPLE_STACK_USER))) {
2208
+ int type = output_type(evsel->core.attr.type);
2209
+
2210
+ if (!(output[type].user_unset_fields & PERF_OUTPUT_IP))
2211
+ output[type].fields |= PERF_OUTPUT_IP;
2212
+ if (!(output[type].user_unset_fields & PERF_OUTPUT_SYM))
2213
+ output[type].fields |= PERF_OUTPUT_SYM;
2214
+ }
2215
+ set_print_ip_opts(&evsel->core.attr);
2216
+ return 0;
2217
+}
2218
+
2219
+static int print_event_with_time(struct perf_tool *tool,
2220
+ union perf_event *event,
2221
+ struct perf_sample *sample,
2222
+ struct machine *machine,
2223
+ pid_t pid, pid_t tid, u64 timestamp)
2224
+{
2225
+ struct perf_script *script = container_of(tool, struct perf_script, tool);
2226
+ struct perf_session *session = script->session;
2227
+ struct evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
2228
+ struct thread *thread = NULL;
2229
+
2230
+ if (evsel && !evsel->core.attr.sample_id_all) {
2231
+ sample->cpu = 0;
2232
+ sample->time = timestamp;
2233
+ sample->pid = pid;
2234
+ sample->tid = tid;
2235
+ }
2236
+
2237
+ if (filter_cpu(sample))
2238
+ return 0;
2239
+
2240
+ if (tid != -1)
2241
+ thread = machine__findnew_thread(machine, pid, tid);
2242
+
2243
+ if (evsel) {
2244
+ perf_sample__fprintf_start(script, sample, thread, evsel,
2245
+ event->header.type, stdout);
2246
+ }
2247
+
2248
+ perf_event__fprintf(event, machine, stdout);
2249
+
2250
+ thread__put(thread);
2251
+
2252
+ return 0;
2253
+}
2254
+
2255
+static int print_event(struct perf_tool *tool, union perf_event *event,
2256
+ struct perf_sample *sample, struct machine *machine,
2257
+ pid_t pid, pid_t tid)
2258
+{
2259
+ return print_event_with_time(tool, event, sample, machine, pid, tid, 0);
18732260 }
18742261
18752262 static int process_comm_event(struct perf_tool *tool,
....@@ -1877,34 +2264,11 @@
18772264 struct perf_sample *sample,
18782265 struct machine *machine)
18792266 {
1880
- struct thread *thread;
1881
- struct perf_script *script = container_of(tool, struct perf_script, tool);
1882
- struct perf_session *session = script->session;
1883
- struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
1884
- int ret = -1;
1885
-
1886
- thread = machine__findnew_thread(machine, event->comm.pid, event->comm.tid);
1887
- if (thread == NULL) {
1888
- pr_debug("problem processing COMM event, skipping it.\n");
1889
- return -1;
1890
- }
1891
-
18922267 if (perf_event__process_comm(tool, event, sample, machine) < 0)
1893
- goto out;
2268
+ return -1;
18942269
1895
- if (!evsel->attr.sample_id_all) {
1896
- sample->cpu = 0;
1897
- sample->time = 0;
1898
- sample->tid = event->comm.tid;
1899
- sample->pid = event->comm.pid;
1900
- }
1901
- perf_sample__fprintf_start(sample, thread, evsel,
1902
- PERF_RECORD_COMM, stdout);
1903
- perf_event__fprintf(event, stdout);
1904
- ret = 0;
1905
-out:
1906
- thread__put(thread);
1907
- return ret;
2270
+ return print_event(tool, event, sample, machine, event->comm.pid,
2271
+ event->comm.tid);
19082272 }
19092273
19102274 static int process_namespaces_event(struct perf_tool *tool,
....@@ -1912,35 +2276,23 @@
19122276 struct perf_sample *sample,
19132277 struct machine *machine)
19142278 {
1915
- struct thread *thread;
1916
- struct perf_script *script = container_of(tool, struct perf_script, tool);
1917
- struct perf_session *session = script->session;
1918
- struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
1919
- int ret = -1;
1920
-
1921
- thread = machine__findnew_thread(machine, event->namespaces.pid,
1922
- event->namespaces.tid);
1923
- if (thread == NULL) {
1924
- pr_debug("problem processing NAMESPACES event, skipping it.\n");
1925
- return -1;
1926
- }
1927
-
19282279 if (perf_event__process_namespaces(tool, event, sample, machine) < 0)
1929
- goto out;
2280
+ return -1;
19302281
1931
- if (!evsel->attr.sample_id_all) {
1932
- sample->cpu = 0;
1933
- sample->time = 0;
1934
- sample->tid = event->namespaces.tid;
1935
- sample->pid = event->namespaces.pid;
1936
- }
1937
- perf_sample__fprintf_start(sample, thread, evsel,
1938
- PERF_RECORD_NAMESPACES, stdout);
1939
- perf_event__fprintf(event, stdout);
1940
- ret = 0;
1941
-out:
1942
- thread__put(thread);
1943
- return ret;
2282
+ return print_event(tool, event, sample, machine, event->namespaces.pid,
2283
+ event->namespaces.tid);
2284
+}
2285
+
2286
+static int process_cgroup_event(struct perf_tool *tool,
2287
+ union perf_event *event,
2288
+ struct perf_sample *sample,
2289
+ struct machine *machine)
2290
+{
2291
+ if (perf_event__process_cgroup(tool, event, sample, machine) < 0)
2292
+ return -1;
2293
+
2294
+ return print_event(tool, event, sample, machine, sample->pid,
2295
+ sample->tid);
19442296 }
19452297
19462298 static int process_fork_event(struct perf_tool *tool,
....@@ -1948,65 +2300,24 @@
19482300 struct perf_sample *sample,
19492301 struct machine *machine)
19502302 {
1951
- struct thread *thread;
1952
- struct perf_script *script = container_of(tool, struct perf_script, tool);
1953
- struct perf_session *session = script->session;
1954
- struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
1955
-
19562303 if (perf_event__process_fork(tool, event, sample, machine) < 0)
19572304 return -1;
19582305
1959
- thread = machine__findnew_thread(machine, event->fork.pid, event->fork.tid);
1960
- if (thread == NULL) {
1961
- pr_debug("problem processing FORK event, skipping it.\n");
1962
- return -1;
1963
- }
1964
-
1965
- if (!evsel->attr.sample_id_all) {
1966
- sample->cpu = 0;
1967
- sample->time = event->fork.time;
1968
- sample->tid = event->fork.tid;
1969
- sample->pid = event->fork.pid;
1970
- }
1971
- perf_sample__fprintf_start(sample, thread, evsel,
1972
- PERF_RECORD_FORK, stdout);
1973
- perf_event__fprintf(event, stdout);
1974
- thread__put(thread);
1975
-
1976
- return 0;
2306
+ return print_event_with_time(tool, event, sample, machine,
2307
+ event->fork.pid, event->fork.tid,
2308
+ event->fork.time);
19772309 }
19782310 static int process_exit_event(struct perf_tool *tool,
19792311 union perf_event *event,
19802312 struct perf_sample *sample,
19812313 struct machine *machine)
19822314 {
1983
- int err = 0;
1984
- struct thread *thread;
1985
- struct perf_script *script = container_of(tool, struct perf_script, tool);
1986
- struct perf_session *session = script->session;
1987
- struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
1988
-
1989
- thread = machine__findnew_thread(machine, event->fork.pid, event->fork.tid);
1990
- if (thread == NULL) {
1991
- pr_debug("problem processing EXIT event, skipping it.\n");
2315
+ /* Print before 'exit' deletes anything */
2316
+ if (print_event_with_time(tool, event, sample, machine, event->fork.pid,
2317
+ event->fork.tid, event->fork.time))
19922318 return -1;
1993
- }
19942319
1995
- if (!evsel->attr.sample_id_all) {
1996
- sample->cpu = 0;
1997
- sample->time = 0;
1998
- sample->tid = event->fork.tid;
1999
- sample->pid = event->fork.pid;
2000
- }
2001
- perf_sample__fprintf_start(sample, thread, evsel,
2002
- PERF_RECORD_EXIT, stdout);
2003
- perf_event__fprintf(event, stdout);
2004
-
2005
- if (perf_event__process_exit(tool, event, sample, machine) < 0)
2006
- err = -1;
2007
-
2008
- thread__put(thread);
2009
- return err;
2320
+ return perf_event__process_exit(tool, event, sample, machine);
20102321 }
20112322
20122323 static int process_mmap_event(struct perf_tool *tool,
....@@ -2014,31 +2325,11 @@
20142325 struct perf_sample *sample,
20152326 struct machine *machine)
20162327 {
2017
- struct thread *thread;
2018
- struct perf_script *script = container_of(tool, struct perf_script, tool);
2019
- struct perf_session *session = script->session;
2020
- struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
2021
-
20222328 if (perf_event__process_mmap(tool, event, sample, machine) < 0)
20232329 return -1;
20242330
2025
- thread = machine__findnew_thread(machine, event->mmap.pid, event->mmap.tid);
2026
- if (thread == NULL) {
2027
- pr_debug("problem processing MMAP event, skipping it.\n");
2028
- return -1;
2029
- }
2030
-
2031
- if (!evsel->attr.sample_id_all) {
2032
- sample->cpu = 0;
2033
- sample->time = 0;
2034
- sample->tid = event->mmap.tid;
2035
- sample->pid = event->mmap.pid;
2036
- }
2037
- perf_sample__fprintf_start(sample, thread, evsel,
2038
- PERF_RECORD_MMAP, stdout);
2039
- perf_event__fprintf(event, stdout);
2040
- thread__put(thread);
2041
- return 0;
2331
+ return print_event(tool, event, sample, machine, event->mmap.pid,
2332
+ event->mmap.tid);
20422333 }
20432334
20442335 static int process_mmap2_event(struct perf_tool *tool,
....@@ -2046,31 +2337,11 @@
20462337 struct perf_sample *sample,
20472338 struct machine *machine)
20482339 {
2049
- struct thread *thread;
2050
- struct perf_script *script = container_of(tool, struct perf_script, tool);
2051
- struct perf_session *session = script->session;
2052
- struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
2053
-
20542340 if (perf_event__process_mmap2(tool, event, sample, machine) < 0)
20552341 return -1;
20562342
2057
- thread = machine__findnew_thread(machine, event->mmap2.pid, event->mmap2.tid);
2058
- if (thread == NULL) {
2059
- pr_debug("problem processing MMAP2 event, skipping it.\n");
2060
- return -1;
2061
- }
2062
-
2063
- if (!evsel->attr.sample_id_all) {
2064
- sample->cpu = 0;
2065
- sample->time = 0;
2066
- sample->tid = event->mmap2.tid;
2067
- sample->pid = event->mmap2.pid;
2068
- }
2069
- perf_sample__fprintf_start(sample, thread, evsel,
2070
- PERF_RECORD_MMAP2, stdout);
2071
- perf_event__fprintf(event, stdout);
2072
- thread__put(thread);
2073
- return 0;
2343
+ return print_event(tool, event, sample, machine, event->mmap2.pid,
2344
+ event->mmap2.tid);
20742345 }
20752346
20762347 static int process_switch_event(struct perf_tool *tool,
....@@ -2078,26 +2349,19 @@
20782349 struct perf_sample *sample,
20792350 struct machine *machine)
20802351 {
2081
- struct thread *thread;
20822352 struct perf_script *script = container_of(tool, struct perf_script, tool);
2083
- struct perf_session *session = script->session;
2084
- struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
20852353
20862354 if (perf_event__process_switch(tool, event, sample, machine) < 0)
20872355 return -1;
20882356
2089
- thread = machine__findnew_thread(machine, sample->pid,
2090
- sample->tid);
2091
- if (thread == NULL) {
2092
- pr_debug("problem processing SWITCH event, skipping it.\n");
2093
- return -1;
2094
- }
2357
+ if (scripting_ops && scripting_ops->process_switch && !filter_cpu(sample))
2358
+ scripting_ops->process_switch(event, sample, machine);
20952359
2096
- perf_sample__fprintf_start(sample, thread, evsel,
2097
- PERF_RECORD_SWITCH, stdout);
2098
- perf_event__fprintf(event, stdout);
2099
- thread__put(thread);
2100
- return 0;
2360
+ if (!script->show_switch_events)
2361
+ return 0;
2362
+
2363
+ return print_event(tool, event, sample, machine, sample->pid,
2364
+ sample->tid);
21012365 }
21022366
21032367 static int
....@@ -2106,21 +2370,8 @@
21062370 struct perf_sample *sample,
21072371 struct machine *machine)
21082372 {
2109
- struct perf_script *script = container_of(tool, struct perf_script, tool);
2110
- struct perf_session *session = script->session;
2111
- struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
2112
- struct thread *thread;
2113
-
2114
- thread = machine__findnew_thread(machine, sample->pid,
2115
- sample->tid);
2116
- if (thread == NULL)
2117
- return -1;
2118
-
2119
- perf_sample__fprintf_start(sample, thread, evsel,
2120
- PERF_RECORD_LOST, stdout);
2121
- perf_event__fprintf(event, stdout);
2122
- thread__put(thread);
2123
- return 0;
2373
+ return print_event(tool, event, sample, machine, sample->pid,
2374
+ sample->tid);
21242375 }
21252376
21262377 static int
....@@ -2129,8 +2380,33 @@
21292380 struct ordered_events *oe __maybe_unused)
21302381
21312382 {
2132
- perf_event__fprintf(event, stdout);
2383
+ perf_event__fprintf(event, NULL, stdout);
21332384 return 0;
2385
+}
2386
+
2387
+static int
2388
+process_bpf_events(struct perf_tool *tool __maybe_unused,
2389
+ union perf_event *event,
2390
+ struct perf_sample *sample,
2391
+ struct machine *machine)
2392
+{
2393
+ if (machine__process_ksymbol(machine, event, sample) < 0)
2394
+ return -1;
2395
+
2396
+ return print_event(tool, event, sample, machine, sample->pid,
2397
+ sample->tid);
2398
+}
2399
+
2400
+static int process_text_poke_events(struct perf_tool *tool,
2401
+ union perf_event *event,
2402
+ struct perf_sample *sample,
2403
+ struct machine *machine)
2404
+{
2405
+ if (perf_event__process_text_poke(tool, event, sample, machine) < 0)
2406
+ return -1;
2407
+
2408
+ return print_event(tool, event, sample, machine, sample->pid,
2409
+ sample->tid);
21342410 }
21352411
21362412 static void sig_handler(int sig __maybe_unused)
....@@ -2140,8 +2416,8 @@
21402416
21412417 static void perf_script__fclose_per_event_dump(struct perf_script *script)
21422418 {
2143
- struct perf_evlist *evlist = script->session->evlist;
2144
- struct perf_evsel *evsel;
2419
+ struct evlist *evlist = script->session->evlist;
2420
+ struct evsel *evsel;
21452421
21462422 evlist__for_each_entry(evlist, evsel) {
21472423 if (!evsel->priv)
....@@ -2153,7 +2429,7 @@
21532429
21542430 static int perf_script__fopen_per_event_dump(struct perf_script *script)
21552431 {
2156
- struct perf_evsel *evsel;
2432
+ struct evsel *evsel;
21572433
21582434 evlist__for_each_entry(script->session->evlist, evsel) {
21592435 /*
....@@ -2180,8 +2456,8 @@
21802456
21812457 static int perf_script__setup_per_event_dump(struct perf_script *script)
21822458 {
2183
- struct perf_evsel *evsel;
2184
- static struct perf_evsel_script es_stdout;
2459
+ struct evsel *evsel;
2460
+ static struct evsel_script es_stdout;
21852461
21862462 if (script->per_event_dump)
21872463 return perf_script__fopen_per_event_dump(script);
....@@ -2196,15 +2472,21 @@
21962472
21972473 static void perf_script__exit_per_event_dump_stats(struct perf_script *script)
21982474 {
2199
- struct perf_evsel *evsel;
2475
+ struct evsel *evsel;
22002476
22012477 evlist__for_each_entry(script->session->evlist, evsel) {
2202
- struct perf_evsel_script *es = evsel->priv;
2478
+ struct evsel_script *es = evsel->priv;
22032479
22042480 perf_evsel_script__fprintf(es, stdout);
22052481 perf_evsel_script__delete(es);
22062482 evsel->priv = NULL;
22072483 }
2484
+}
2485
+
2486
+static void perf_script__exit(struct perf_script *script)
2487
+{
2488
+ perf_thread_map__put(script->threads);
2489
+ perf_cpu_map__put(script->cpus);
22082490 }
22092491
22102492 static int __cmd_script(struct perf_script *script)
....@@ -2225,15 +2507,25 @@
22252507 script->tool.mmap = process_mmap_event;
22262508 script->tool.mmap2 = process_mmap2_event;
22272509 }
2228
- if (script->show_switch_events)
2510
+ if (script->show_switch_events || (scripting_ops && scripting_ops->process_switch))
22292511 script->tool.context_switch = process_switch_event;
22302512 if (script->show_namespace_events)
22312513 script->tool.namespaces = process_namespaces_event;
2514
+ if (script->show_cgroup_events)
2515
+ script->tool.cgroup = process_cgroup_event;
22322516 if (script->show_lost_events)
22332517 script->tool.lost = process_lost_event;
22342518 if (script->show_round_events) {
22352519 script->tool.ordered_events = false;
22362520 script->tool.finished_round = process_finished_round_event;
2521
+ }
2522
+ if (script->show_bpf_events) {
2523
+ script->tool.ksymbol = process_bpf_events;
2524
+ script->tool.bpf = process_bpf_events;
2525
+ }
2526
+ if (script->show_text_poke_events) {
2527
+ script->tool.ksymbol = process_bpf_events;
2528
+ script->tool.text_poke = process_text_poke_events;
22372529 }
22382530
22392531 if (perf_script__setup_per_event_dump(script)) {
....@@ -2255,7 +2547,7 @@
22552547 struct script_spec {
22562548 struct list_head node;
22572549 struct scripting_ops *ops;
2258
- char spec[0];
2550
+ char spec[];
22592551 };
22602552
22612553 static LIST_HEAD(script_specs);
....@@ -2418,6 +2710,10 @@
24182710 pr_warning("Overriding previous field request for %s events.\n",
24192711 event_type(type));
24202712
2713
+ /* Don't override defaults for +- */
2714
+ if (strchr(tok, '+') || strchr(tok, '-'))
2715
+ goto parse;
2716
+
24212717 output[type].fields = 0;
24222718 output[type].user_set = true;
24232719 output[type].wildcard_set = false;
....@@ -2486,10 +2782,17 @@
24862782 pr_warning("\'%s\' not valid for %s events. Ignoring.\n",
24872783 all_output_options[i].str, event_type(j));
24882784 } else {
2489
- if (change == REMOVE)
2785
+ if (change == REMOVE) {
24902786 output[j].fields &= ~all_output_options[i].field;
2491
- else
2787
+ output[j].user_set_fields &= ~all_output_options[i].field;
2788
+ output[j].user_unset_fields |= all_output_options[i].field;
2789
+ } else {
24922790 output[j].fields |= all_output_options[i].field;
2791
+ output[j].user_set_fields |= all_output_options[i].field;
2792
+ output[j].user_unset_fields &= ~all_output_options[i].field;
2793
+ }
2794
+ output[j].user_set = true;
2795
+ output[j].wildcard_set = true;
24932796 }
24942797 }
24952798 } else {
....@@ -2500,7 +2803,12 @@
25002803 rc = -EINVAL;
25012804 goto out;
25022805 }
2503
- output[type].fields |= all_output_options[i].field;
2806
+ if (change == REMOVE)
2807
+ output[type].fields &= ~all_output_options[i].field;
2808
+ else
2809
+ output[type].fields |= all_output_options[i].field;
2810
+ output[type].user_set = true;
2811
+ output[type].wildcard_set = true;
25042812 }
25052813 }
25062814
....@@ -2620,7 +2928,7 @@
26202928 return -1;
26212929
26222930 while (fgets(line, sizeof(line), fp)) {
2623
- p = ltrim(line);
2931
+ p = skip_spaces(line);
26242932 if (strlen(p) == 0)
26252933 continue;
26262934 if (*p != '#')
....@@ -2629,19 +2937,19 @@
26292937 if (strlen(p) && *p == '!')
26302938 continue;
26312939
2632
- p = ltrim(p);
2940
+ p = skip_spaces(p);
26332941 if (strlen(p) && p[strlen(p) - 1] == '\n')
26342942 p[strlen(p) - 1] = '\0';
26352943
26362944 if (!strncmp(p, "description:", strlen("description:"))) {
26372945 p += strlen("description:");
2638
- desc->half_liner = strdup(ltrim(p));
2946
+ desc->half_liner = strdup(skip_spaces(p));
26392947 continue;
26402948 }
26412949
26422950 if (!strncmp(p, "args:", strlen("args:"))) {
26432951 p += strlen("args:");
2644
- desc->args = strdup(ltrim(p));
2952
+ desc->args = strdup(skip_spaces(p));
26452953 continue;
26462954 }
26472955 }
....@@ -2737,7 +3045,7 @@
27373045 {
27383046 char filename[MAXPATHLEN], evname[128];
27393047 char line[BUFSIZ], *p;
2740
- struct perf_evsel *pos;
3048
+ struct evsel *pos;
27413049 int match, len;
27423050 FILE *fp;
27433051
....@@ -2748,7 +3056,7 @@
27483056 return -1;
27493057
27503058 while (fgets(line, sizeof(line), fp)) {
2751
- p = ltrim(line);
3059
+ p = skip_spaces(line);
27523060 if (*p == '#')
27533061 continue;
27543062
....@@ -2758,7 +3066,7 @@
27583066 break;
27593067
27603068 p += 2;
2761
- p = ltrim(p);
3069
+ p = skip_spaces(p);
27623070 len = strcspn(p, " \t");
27633071 if (!len)
27643072 break;
....@@ -2767,7 +3075,7 @@
27673075
27683076 match = 0;
27693077 evlist__for_each_entry(session->evlist, pos) {
2770
- if (!strcmp(perf_evsel__name(pos), evname)) {
3078
+ if (!strcmp(evsel__name(pos), evname)) {
27713079 match = 1;
27723080 break;
27733081 }
....@@ -2791,24 +3099,23 @@
27913099 * will list all statically runnable scripts, select one, execute it and
27923100 * show the output in a perf browser.
27933101 */
2794
-int find_scripts(char **scripts_array, char **scripts_path_array)
3102
+int find_scripts(char **scripts_array, char **scripts_path_array, int num,
3103
+ int pathlen)
27953104 {
27963105 struct dirent *script_dirent, *lang_dirent;
27973106 char scripts_path[MAXPATHLEN], lang_path[MAXPATHLEN];
27983107 DIR *scripts_dir, *lang_dir;
27993108 struct perf_session *session;
28003109 struct perf_data data = {
2801
- .file = {
2802
- .path = input_name,
2803
- },
2804
- .mode = PERF_DATA_MODE_READ,
3110
+ .path = input_name,
3111
+ .mode = PERF_DATA_MODE_READ,
28053112 };
28063113 char *temp;
28073114 int i = 0;
28083115
28093116 session = perf_session__new(&data, false, NULL);
2810
- if (!session)
2811
- return -1;
3117
+ if (IS_ERR(session))
3118
+ return PTR_ERR(session);
28123119
28133120 snprintf(scripts_path, MAXPATHLEN, "%s/scripts", get_argv_exec_path());
28143121
....@@ -2838,7 +3145,10 @@
28383145 /* Skip those real time scripts: xxxtop.p[yl] */
28393146 if (strstr(script_dirent->d_name, "top."))
28403147 continue;
2841
- sprintf(scripts_path_array[i], "%s/%s", lang_path,
3148
+ if (i >= num)
3149
+ break;
3150
+ snprintf(scripts_path_array[i], pathlen, "%s/%s",
3151
+ lang_path,
28423152 script_dirent->d_name);
28433153 temp = strchr(script_dirent->d_name, '.');
28443154 snprintf(scripts_array[i],
....@@ -2885,10 +3195,10 @@
28853195 __script_root = get_script_root(script_dirent, suffix);
28863196 if (__script_root && !strcmp(script_root, __script_root)) {
28873197 free(__script_root);
2888
- closedir(lang_dir);
28893198 closedir(scripts_dir);
28903199 scnprintf(script_path, MAXPATHLEN, "%s/%s",
28913200 lang_path, script_dirent->d_name);
3201
+ closedir(lang_dir);
28923202 return strdup(script_path);
28933203 }
28943204 free(__script_root);
....@@ -2950,7 +3260,7 @@
29503260 static void script__setup_sample_type(struct perf_script *script)
29513261 {
29523262 struct perf_session *session = script->session;
2953
- u64 sample_type = perf_evlist__combined_sample_type(session->evlist);
3263
+ u64 sample_type = evlist__combined_sample_type(session->evlist);
29543264
29553265 if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain) {
29563266 if ((sample_type & PERF_SAMPLE_REGS_USER) &&
....@@ -2962,14 +3272,19 @@
29623272 else
29633273 callchain_param.record_mode = CALLCHAIN_FP;
29643274 }
3275
+
3276
+ if (script->stitch_lbr && (callchain_param.record_mode != CALLCHAIN_LBR)) {
3277
+ pr_warning("Can't find LBR callchain. Switch off --stitch-lbr.\n"
3278
+ "Please apply --call-graph lbr when recording.\n");
3279
+ script->stitch_lbr = false;
3280
+ }
29653281 }
29663282
2967
-static int process_stat_round_event(struct perf_tool *tool __maybe_unused,
2968
- union perf_event *event,
2969
- struct perf_session *session)
3283
+static int process_stat_round_event(struct perf_session *session,
3284
+ union perf_event *event)
29703285 {
2971
- struct stat_round_event *round = &event->stat_round;
2972
- struct perf_evsel *counter;
3286
+ struct perf_record_stat_round *round = &event->stat_round;
3287
+ struct evsel *counter;
29733288
29743289 evlist__for_each_entry(session->evlist, counter) {
29753290 perf_stat_process_counter(&stat_config, counter);
....@@ -2980,9 +3295,8 @@
29803295 return 0;
29813296 }
29823297
2983
-static int process_stat_config_event(struct perf_tool *tool __maybe_unused,
2984
- union perf_event *event,
2985
- struct perf_session *session __maybe_unused)
3298
+static int process_stat_config_event(struct perf_session *session __maybe_unused,
3299
+ union perf_event *event)
29863300 {
29873301 perf_event__read_stat_config(&stat_config, &event->stat_config);
29883302 return 0;
....@@ -2990,7 +3304,7 @@
29903304
29913305 static int set_maps(struct perf_script *script)
29923306 {
2993
- struct perf_evlist *evlist = script->session->evlist;
3307
+ struct evlist *evlist = script->session->evlist;
29943308
29953309 if (!script->cpus || !script->threads)
29963310 return 0;
....@@ -2998,7 +3312,7 @@
29983312 if (WARN_ONCE(script->allocated, "stats double allocation\n"))
29993313 return -EINVAL;
30003314
3001
- perf_evlist__set_maps(evlist, script->cpus, script->threads);
3315
+ perf_evlist__set_maps(&evlist->core, script->cpus, script->threads);
30023316
30033317 if (perf_evlist__alloc_stats(evlist, true))
30043318 return -ENOMEM;
....@@ -3008,10 +3322,10 @@
30083322 }
30093323
30103324 static
3011
-int process_thread_map_event(struct perf_tool *tool,
3012
- union perf_event *event,
3013
- struct perf_session *session __maybe_unused)
3325
+int process_thread_map_event(struct perf_session *session,
3326
+ union perf_event *event)
30143327 {
3328
+ struct perf_tool *tool = session->tool;
30153329 struct perf_script *script = container_of(tool, struct perf_script, tool);
30163330
30173331 if (script->threads) {
....@@ -3027,10 +3341,10 @@
30273341 }
30283342
30293343 static
3030
-int process_cpu_map_event(struct perf_tool *tool __maybe_unused,
3031
- union perf_event *event,
3032
- struct perf_session *session __maybe_unused)
3344
+int process_cpu_map_event(struct perf_session *session,
3345
+ union perf_event *event)
30333346 {
3347
+ struct perf_tool *tool = session->tool;
30343348 struct perf_script *script = container_of(tool, struct perf_script, tool);
30353349
30363350 if (script->cpus) {
....@@ -3045,21 +3359,21 @@
30453359 return set_maps(script);
30463360 }
30473361
3048
-static int process_feature_event(struct perf_tool *tool,
3049
- union perf_event *event,
3050
- struct perf_session *session)
3362
+static int process_feature_event(struct perf_session *session,
3363
+ union perf_event *event)
30513364 {
30523365 if (event->feat.feat_id < HEADER_LAST_FEATURE)
3053
- return perf_event__process_feature(tool, event, session);
3366
+ return perf_event__process_feature(session, event);
30543367 return 0;
30553368 }
30563369
30573370 #ifdef HAVE_AUXTRACE_SUPPORT
3058
-static int perf_script__process_auxtrace_info(struct perf_tool *tool,
3059
- union perf_event *event,
3060
- struct perf_session *session)
3371
+static int perf_script__process_auxtrace_info(struct perf_session *session,
3372
+ union perf_event *event)
30613373 {
3062
- int ret = perf_event__process_auxtrace_info(tool, event, session);
3374
+ struct perf_tool *tool = session->tool;
3375
+
3376
+ int ret = perf_event__process_auxtrace_info(session, event);
30633377
30643378 if (ret == 0) {
30653379 struct perf_script *script = container_of(tool, struct perf_script, tool);
....@@ -3073,6 +3387,48 @@
30733387 #define perf_script__process_auxtrace_info 0
30743388 #endif
30753389
3390
+static int parse_insn_trace(const struct option *opt __maybe_unused,
3391
+ const char *str __maybe_unused,
3392
+ int unset __maybe_unused)
3393
+{
3394
+ parse_output_fields(NULL, "+insn,-event,-period", 0);
3395
+ itrace_parse_synth_opts(opt, "i0ns", 0);
3396
+ symbol_conf.nanosecs = true;
3397
+ return 0;
3398
+}
3399
+
3400
+static int parse_xed(const struct option *opt __maybe_unused,
3401
+ const char *str __maybe_unused,
3402
+ int unset __maybe_unused)
3403
+{
3404
+ if (isatty(1))
3405
+ force_pager("xed -F insn: -A -64 | less");
3406
+ else
3407
+ force_pager("xed -F insn: -A -64");
3408
+ return 0;
3409
+}
3410
+
3411
+static int parse_call_trace(const struct option *opt __maybe_unused,
3412
+ const char *str __maybe_unused,
3413
+ int unset __maybe_unused)
3414
+{
3415
+ parse_output_fields(NULL, "-ip,-addr,-event,-period,+callindent", 0);
3416
+ itrace_parse_synth_opts(opt, "cewp", 0);
3417
+ symbol_conf.nanosecs = true;
3418
+ symbol_conf.pad_output_len_dso = 50;
3419
+ return 0;
3420
+}
3421
+
3422
+static int parse_callret_trace(const struct option *opt __maybe_unused,
3423
+ const char *str __maybe_unused,
3424
+ int unset __maybe_unused)
3425
+{
3426
+ parse_output_fields(NULL, "-ip,-addr,-event,-period,+callindent,+flags", 0);
3427
+ itrace_parse_synth_opts(opt, "crewp", 0);
3428
+ symbol_conf.nanosecs = true;
3429
+ return 0;
3430
+}
3431
+
30763432 int cmd_script(int argc, const char **argv)
30773433 {
30783434 bool show_full_info = false;
....@@ -3082,7 +3438,11 @@
30823438 char *rec_script_path = NULL;
30833439 char *rep_script_path = NULL;
30843440 struct perf_session *session;
3085
- struct itrace_synth_opts itrace_synth_opts = { .set = false, };
3441
+ struct itrace_synth_opts itrace_synth_opts = {
3442
+ .set = false,
3443
+ .default_no_sample = true,
3444
+ };
3445
+ struct utsname uts;
30863446 char *script_path = NULL;
30873447 const char **__argv;
30883448 int i, j, err = 0;
....@@ -3093,6 +3453,7 @@
30933453 .mmap2 = perf_event__process_mmap2,
30943454 .comm = perf_event__process_comm,
30953455 .namespaces = perf_event__process_namespaces,
3456
+ .cgroup = perf_event__process_cgroup,
30963457 .exit = perf_event__process_exit,
30973458 .fork = perf_event__process_fork,
30983459 .attr = process_attr,
....@@ -3151,12 +3512,22 @@
31513512 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,"
31523513 "addr,symoff,srcline,period,iregs,uregs,brstack,"
31533514 "brstacksym,flags,bpf-output,brstackinsn,brstackoff,"
3154
- "callindent,insn,insnlen,synth,phys_addr,metric,misc",
3515
+ "callindent,insn,insnlen,synth,phys_addr,metric,misc,ipc,tod",
31553516 parse_output_fields),
31563517 OPT_BOOLEAN('a', "all-cpus", &system_wide,
31573518 "system-wide collection from all CPUs"),
31583519 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
31593520 "only consider these symbols"),
3521
+ OPT_CALLBACK_OPTARG(0, "insn-trace", &itrace_synth_opts, NULL, NULL,
3522
+ "Decode instructions from itrace", parse_insn_trace),
3523
+ OPT_CALLBACK_OPTARG(0, "xed", NULL, NULL, NULL,
3524
+ "Run xed disassembler on output", parse_xed),
3525
+ OPT_CALLBACK_OPTARG(0, "call-trace", &itrace_synth_opts, NULL, NULL,
3526
+ "Decode calls from from itrace", parse_call_trace),
3527
+ OPT_CALLBACK_OPTARG(0, "call-ret-trace", &itrace_synth_opts, NULL, NULL,
3528
+ "Decode calls and returns from itrace", parse_callret_trace),
3529
+ OPT_STRING(0, "graph-function", &symbol_conf.graph_function, "symbol[,symbol...]",
3530
+ "Only print symbols and callees with --call-trace/--call-ret-trace"),
31603531 OPT_STRING(0, "stop-bt", &symbol_conf.bt_stop_list_str, "symbol[,symbol...]",
31613532 "Stop display of callgraph at these symbols"),
31623533 OPT_STRING('C', "cpu", &cpu_list, "cpu", "list of cpus to profile"),
....@@ -3170,6 +3541,8 @@
31703541 "Set the maximum stack depth when parsing the callchain, "
31713542 "anything beyond the specified depth will be ignored. "
31723543 "Default: kernel.perf_event_max_stack or " __stringify(PERF_MAX_STACK_DEPTH)),
3544
+ OPT_BOOLEAN(0, "reltime", &reltime, "Show time stamps relative to start"),
3545
+ OPT_BOOLEAN(0, "deltatime", &deltatime, "Show time stamps relative to previous event"),
31733546 OPT_BOOLEAN('I', "show-info", &show_full_info,
31743547 "display extended information from perf.data file"),
31753548 OPT_BOOLEAN('\0', "show-kernel-path", &symbol_conf.show_kernel_path,
....@@ -3182,19 +3555,25 @@
31823555 "Show context switch events (if recorded)"),
31833556 OPT_BOOLEAN('\0', "show-namespace-events", &script.show_namespace_events,
31843557 "Show namespace events (if recorded)"),
3558
+ OPT_BOOLEAN('\0', "show-cgroup-events", &script.show_cgroup_events,
3559
+ "Show cgroup events (if recorded)"),
31853560 OPT_BOOLEAN('\0', "show-lost-events", &script.show_lost_events,
31863561 "Show lost events (if recorded)"),
31873562 OPT_BOOLEAN('\0', "show-round-events", &script.show_round_events,
31883563 "Show round events (if recorded)"),
3564
+ OPT_BOOLEAN('\0', "show-bpf-events", &script.show_bpf_events,
3565
+ "Show bpf related events (if recorded)"),
3566
+ OPT_BOOLEAN('\0', "show-text-poke-events", &script.show_text_poke_events,
3567
+ "Show text poke related events (if recorded)"),
31893568 OPT_BOOLEAN('\0', "per-event-dump", &script.per_event_dump,
31903569 "Dump trace output to files named by the monitored events"),
31913570 OPT_BOOLEAN('f', "force", &symbol_conf.force, "don't complain, do it"),
31923571 OPT_INTEGER(0, "max-blocks", &max_blocks,
31933572 "Maximum number of code blocks to dump with brstackinsn"),
3194
- OPT_BOOLEAN(0, "ns", &nanosecs,
3573
+ OPT_BOOLEAN(0, "ns", &symbol_conf.nanosecs,
31953574 "Use 9 decimal places when displaying time"),
31963575 OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts",
3197
- "Instruction Tracing options",
3576
+ "Instruction Tracing options\n" ITRACE_HELP,
31983577 itrace_parse_synth_opts),
31993578 OPT_BOOLEAN(0, "full-source-path", &srcline_full_filename,
32003579 "Show full source file name path for source lines"),
....@@ -3206,6 +3585,18 @@
32063585 "Time span of interest (start,stop)"),
32073586 OPT_BOOLEAN(0, "inline", &symbol_conf.inline_name,
32083587 "Show inline function"),
3588
+ OPT_STRING(0, "guestmount", &symbol_conf.guestmount, "directory",
3589
+ "guest mount directory under which every guest os"
3590
+ " instance has a subdir"),
3591
+ OPT_STRING(0, "guestvmlinux", &symbol_conf.default_guest_vmlinux_name,
3592
+ "file", "file saving guest os vmlinux"),
3593
+ OPT_STRING(0, "guestkallsyms", &symbol_conf.default_guest_kallsyms,
3594
+ "file", "file saving guest os /proc/kallsyms"),
3595
+ OPT_STRING(0, "guestmodules", &symbol_conf.default_guest_modules,
3596
+ "file", "file saving guest os /proc/modules"),
3597
+ OPT_BOOLEAN('\0', "stitch-lbr", &script.stitch_lbr,
3598
+ "Enable LBR callgraph stitching approach"),
3599
+ OPTS_EVSWITCH(&script.evswitch),
32093600 OPT_END()
32103601 };
32113602 const char * const script_subcommands[] = { "record", "report", NULL };
....@@ -3225,8 +3616,18 @@
32253616 argc = parse_options_subcommand(argc, argv, options, script_subcommands, script_usage,
32263617 PARSE_OPT_STOP_AT_NON_OPTION);
32273618
3228
- data.file.path = input_name;
3229
- data.force = symbol_conf.force;
3619
+ if (symbol_conf.guestmount ||
3620
+ symbol_conf.default_guest_vmlinux_name ||
3621
+ symbol_conf.default_guest_kallsyms ||
3622
+ symbol_conf.default_guest_modules) {
3623
+ /*
3624
+ * Enable guest sample processing.
3625
+ */
3626
+ perf_guest = true;
3627
+ }
3628
+
3629
+ data.path = input_name;
3630
+ data.force = symbol_conf.force;
32303631
32313632 if (argc > 1 && !strncmp(argv[0], "rec", strlen("rec"))) {
32323633 rec_script_path = get_script_path(argv[1], RECORD_SUFFIX);
....@@ -3244,7 +3645,14 @@
32443645 }
32453646 }
32463647
3247
- if (itrace_synth_opts.callchain &&
3648
+ if (reltime && deltatime) {
3649
+ fprintf(stderr,
3650
+ "reltime and deltatime - the two don't get along well. "
3651
+ "Please limit to --reltime or --deltatime.\n");
3652
+ return -1;
3653
+ }
3654
+
3655
+ if ((itrace_synth_opts.callchain || itrace_synth_opts.add_callchain) &&
32483656 itrace_synth_opts.callchain_sz > scripting_max_stack)
32493657 scripting_max_stack = itrace_synth_opts.callchain_sz;
32503658
....@@ -3390,12 +3798,14 @@
33903798 exit(-1);
33913799 }
33923800
3393
- if (!script_name)
3801
+ if (!script_name) {
33943802 setup_pager();
3803
+ use_browser = 0;
3804
+ }
33953805
33963806 session = perf_session__new(&data, false, &script.tool);
3397
- if (session == NULL)
3398
- return -1;
3807
+ if (IS_ERR(session))
3808
+ return PTR_ERR(session);
33993809
34003810 if (header || header_only) {
34013811 script.tool.show_feat_hdr = SHOW_FEAT_HEADER;
....@@ -3409,10 +3819,22 @@
34093819 if (symbol__init(&session->header.env) < 0)
34103820 goto out_delete;
34113821
3822
+ uname(&uts);
3823
+ if (data.is_pipe) { /* Assume pipe_mode indicates native_arch */
3824
+ native_arch = true;
3825
+ } else if (session->header.env.arch) {
3826
+ if (!strcmp(uts.machine, session->header.env.arch))
3827
+ native_arch = true;
3828
+ else if (!strcmp(uts.machine, "x86_64") &&
3829
+ !strcmp(session->header.env.arch, "i386"))
3830
+ native_arch = true;
3831
+ }
3832
+
34123833 script.session = session;
34133834 script__setup_sample_type(&script);
34143835
3415
- if (output[PERF_TYPE_HARDWARE].fields & PERF_OUTPUT_CALLINDENT)
3836
+ if ((output[PERF_TYPE_HARDWARE].fields & PERF_OUTPUT_CALLINDENT) ||
3837
+ symbol_conf.graph_function)
34163838 itrace_synth_opts.thread_stack = true;
34173839
34183840 session->itrace_synth_opts = &itrace_synth_opts;
....@@ -3449,7 +3871,7 @@
34493871 goto out_delete;
34503872 }
34513873
3452
- input = open(data.file.path, O_RDONLY); /* input_name */
3874
+ input = open(data.path, O_RDONLY); /* input_name */
34533875 if (input < 0) {
34543876 err = -errno;
34553877 perror("failed to open file");
....@@ -3492,48 +3914,40 @@
34923914 if (err < 0)
34933915 goto out_delete;
34943916
3495
- script.ptime_range = perf_time__range_alloc(script.time_str,
3496
- &script.range_size);
3497
- if (!script.ptime_range) {
3498
- err = -ENOMEM;
3917
+ if (script.time_str) {
3918
+ err = perf_time__parse_for_ranges_reltime(script.time_str, session,
3919
+ &script.ptime_range,
3920
+ &script.range_size,
3921
+ &script.range_num,
3922
+ reltime);
3923
+ if (err < 0)
3924
+ goto out_delete;
3925
+
3926
+ itrace_synth_opts__set_time_range(&itrace_synth_opts,
3927
+ script.ptime_range,
3928
+ script.range_num);
3929
+ }
3930
+
3931
+ err = evswitch__init(&script.evswitch, session->evlist, stderr);
3932
+ if (err)
34993933 goto out_delete;
3500
- }
35013934
3502
- /* needs to be parsed after looking up reference time */
3503
- if (perf_time__parse_str(script.ptime_range, script.time_str) != 0) {
3504
- if (session->evlist->first_sample_time == 0 &&
3505
- session->evlist->last_sample_time == 0) {
3506
- pr_err("HINT: no first/last sample time found in perf data.\n"
3507
- "Please use latest perf binary to execute 'perf record'\n"
3508
- "(if '--buildid-all' is enabled, please set '--timestamp-boundary').\n");
3509
- err = -EINVAL;
3510
- goto out_delete;
3511
- }
3512
-
3513
- script.range_num = perf_time__percent_parse_str(
3514
- script.ptime_range, script.range_size,
3515
- script.time_str,
3516
- session->evlist->first_sample_time,
3517
- session->evlist->last_sample_time);
3518
-
3519
- if (script.range_num < 0) {
3520
- pr_err("Invalid time string\n");
3521
- err = -EINVAL;
3522
- goto out_delete;
3523
- }
3524
- } else {
3525
- script.range_num = 1;
3526
- }
3935
+ if (zstd_init(&(session->zstd_data), 0) < 0)
3936
+ pr_warning("Decompression initialization failed. Reported data may be incomplete.\n");
35273937
35283938 err = __cmd_script(&script);
35293939
35303940 flush_scripting();
35313941
35323942 out_delete:
3533
- zfree(&script.ptime_range);
3943
+ if (script.ptime_range) {
3944
+ itrace_synth_opts__clear_time_range(&itrace_synth_opts);
3945
+ zfree(&script.ptime_range);
3946
+ }
35343947
35353948 perf_evlist__free_stats(session->evlist);
35363949 perf_session__delete(session);
3950
+ perf_script__exit(&script);
35373951
35383952 if (script_started)
35393953 cleanup_scripting();