hc
2024-05-10 37f49e37ab4cb5d0bc4c60eb5c6d4dd57db767bb
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,17 @@
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,
249
- struct perf_data *data)
298
+static struct evsel_script *evsel_script__new(struct evsel *evsel, struct perf_data *data)
250299 {
251
- struct perf_evsel_script *es = zalloc(sizeof(*es));
300
+ struct evsel_script *es = zalloc(sizeof(*es));
252301
253302 if (es != NULL) {
254
- if (asprintf(&es->filename, "%s.%s.dump", data->file.path, perf_evsel__name(evsel)) < 0)
303
+ if (asprintf(&es->filename, "%s.%s.dump", data->file.path, evsel__name(evsel)) < 0)
255304 goto out_free;
256305 es->fp = fopen(es->filename, "w");
257306 if (es->fp == NULL)
....@@ -266,7 +315,7 @@
266315 return NULL;
267316 }
268317
269
-static void perf_evsel_script__delete(struct perf_evsel_script *es)
318
+static void evsel_script__delete(struct evsel_script *es)
270319 {
271320 zfree(&es->filename);
272321 fclose(es->fp);
....@@ -274,7 +323,7 @@
274323 free(es);
275324 }
276325
277
-static int perf_evsel_script__fprintf(struct perf_evsel_script *es, FILE *fp)
326
+static int evsel_script__fprintf(struct evsel_script *es, FILE *fp)
278327 {
279328 struct stat st;
280329
....@@ -329,22 +378,20 @@
329378
330379 #define PRINT_FIELD(x) (output[output_type(attr->type)].fields & PERF_OUTPUT_##x)
331380
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)
381
+static int evsel__do_check_stype(struct evsel *evsel, u64 sample_type, const char *sample_msg,
382
+ enum perf_output_field field, bool allow_user_set)
336383 {
337
- struct perf_event_attr *attr = &evsel->attr;
384
+ struct perf_event_attr *attr = &evsel->core.attr;
338385 int type = output_type(attr->type);
339386 const char *evname;
340387
341388 if (attr->sample_type & sample_type)
342389 return 0;
343390
344
- if (output[type].user_set) {
391
+ if (output[type].user_set_fields & field) {
345392 if (allow_user_set)
346393 return 0;
347
- evname = perf_evsel__name(evsel);
394
+ evname = evsel__name(evsel);
348395 pr_err("Samples for '%s' event do not have %s attribute set. "
349396 "Cannot print '%s' field.\n",
350397 evname, sample_msg, output_field2str(field));
....@@ -353,7 +400,7 @@
353400
354401 /* user did not ask for it explicitly so remove from the default list */
355402 output[type].fields &= ~field;
356
- evname = perf_evsel__name(evsel);
403
+ evname = evsel__name(evsel);
357404 pr_debug("Samples for '%s' event do not have %s attribute set. "
358405 "Skipping '%s' field.\n",
359406 evname, sample_msg, output_field2str(field));
....@@ -361,18 +408,15 @@
361408 return 0;
362409 }
363410
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)
411
+static int evsel__check_stype(struct evsel *evsel, u64 sample_type, const char *sample_msg,
412
+ enum perf_output_field field)
367413 {
368
- return perf_evsel__do_check_stype(evsel, sample_type, sample_msg, field,
369
- false);
414
+ return evsel__do_check_stype(evsel, sample_type, sample_msg, field, false);
370415 }
371416
372
-static int perf_evsel__check_attr(struct perf_evsel *evsel,
373
- struct perf_session *session)
417
+static int evsel__check_attr(struct evsel *evsel, struct perf_session *session)
374418 {
375
- struct perf_event_attr *attr = &evsel->attr;
419
+ struct perf_event_attr *attr = &evsel->core.attr;
376420 bool allow_user_set;
377421
378422 if (perf_header__has_feat(&session->header, HEADER_STAT))
....@@ -382,33 +426,30 @@
382426 HEADER_AUXTRACE);
383427
384428 if (PRINT_FIELD(TRACE) &&
385
- !perf_session__has_traces(session, "record -R"))
429
+ !perf_session__has_traces(session, "record -R"))
386430 return -EINVAL;
387431
388432 if (PRINT_FIELD(IP)) {
389
- if (perf_evsel__check_stype(evsel, PERF_SAMPLE_IP, "IP",
390
- PERF_OUTPUT_IP))
433
+ if (evsel__check_stype(evsel, PERF_SAMPLE_IP, "IP", PERF_OUTPUT_IP))
391434 return -EINVAL;
392435 }
393436
394437 if (PRINT_FIELD(ADDR) &&
395
- perf_evsel__do_check_stype(evsel, PERF_SAMPLE_ADDR, "ADDR",
396
- PERF_OUTPUT_ADDR, allow_user_set))
438
+ evsel__do_check_stype(evsel, PERF_SAMPLE_ADDR, "ADDR", PERF_OUTPUT_ADDR, allow_user_set))
397439 return -EINVAL;
398440
399441 if (PRINT_FIELD(DATA_SRC) &&
400
- perf_evsel__check_stype(evsel, PERF_SAMPLE_DATA_SRC, "DATA_SRC",
401
- PERF_OUTPUT_DATA_SRC))
442
+ evsel__check_stype(evsel, PERF_SAMPLE_DATA_SRC, "DATA_SRC", PERF_OUTPUT_DATA_SRC))
402443 return -EINVAL;
403444
404445 if (PRINT_FIELD(WEIGHT) &&
405
- perf_evsel__check_stype(evsel, PERF_SAMPLE_WEIGHT, "WEIGHT",
406
- PERF_OUTPUT_WEIGHT))
446
+ evsel__check_stype(evsel, PERF_SAMPLE_WEIGHT, "WEIGHT", PERF_OUTPUT_WEIGHT))
407447 return -EINVAL;
408448
409
- if (PRINT_FIELD(SYM) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) {
449
+ if (PRINT_FIELD(SYM) &&
450
+ !(evsel->core.attr.sample_type & (PERF_SAMPLE_IP|PERF_SAMPLE_ADDR))) {
410451 pr_err("Display of symbols requested but neither sample IP nor "
411
- "sample address\nis selected. Hence, no addresses to convert "
452
+ "sample address\navailable. Hence, no addresses to convert "
412453 "to symbols.\n");
413454 return -EINVAL;
414455 }
....@@ -417,52 +458,44 @@
417458 "selected.\n");
418459 return -EINVAL;
419460 }
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");
461
+ if (PRINT_FIELD(DSO) &&
462
+ !(evsel->core.attr.sample_type & (PERF_SAMPLE_IP|PERF_SAMPLE_ADDR))) {
463
+ pr_err("Display of DSO requested but no address to convert.\n");
424464 return -EINVAL;
425465 }
426
- if (PRINT_FIELD(SRCLINE) && !PRINT_FIELD(IP)) {
466
+ if ((PRINT_FIELD(SRCLINE) || PRINT_FIELD(SRCCODE)) && !PRINT_FIELD(IP)) {
427467 pr_err("Display of source line number requested but sample IP is not\n"
428468 "selected. Hence, no address to lookup the source line number.\n");
429469 return -EINVAL;
430470 }
431471 if (PRINT_FIELD(BRSTACKINSN) && !allow_user_set &&
432
- !(perf_evlist__combined_branch_type(session->evlist) &
433
- PERF_SAMPLE_BRANCH_ANY)) {
472
+ !(evlist__combined_branch_type(session->evlist) & PERF_SAMPLE_BRANCH_ANY)) {
434473 pr_err("Display of branch stack assembler requested, but non all-branch filter set\n"
435474 "Hint: run 'perf record -b ...'\n");
436475 return -EINVAL;
437476 }
438477 if ((PRINT_FIELD(PID) || PRINT_FIELD(TID)) &&
439
- perf_evsel__check_stype(evsel, PERF_SAMPLE_TID, "TID",
440
- PERF_OUTPUT_TID|PERF_OUTPUT_PID))
478
+ evsel__check_stype(evsel, PERF_SAMPLE_TID, "TID", PERF_OUTPUT_TID|PERF_OUTPUT_PID))
441479 return -EINVAL;
442480
443481 if (PRINT_FIELD(TIME) &&
444
- perf_evsel__check_stype(evsel, PERF_SAMPLE_TIME, "TIME",
445
- PERF_OUTPUT_TIME))
482
+ evsel__check_stype(evsel, PERF_SAMPLE_TIME, "TIME", PERF_OUTPUT_TIME))
446483 return -EINVAL;
447484
448485 if (PRINT_FIELD(CPU) &&
449
- perf_evsel__do_check_stype(evsel, PERF_SAMPLE_CPU, "CPU",
450
- PERF_OUTPUT_CPU, allow_user_set))
486
+ evsel__do_check_stype(evsel, PERF_SAMPLE_CPU, "CPU", PERF_OUTPUT_CPU, allow_user_set))
451487 return -EINVAL;
452488
453489 if (PRINT_FIELD(IREGS) &&
454
- perf_evsel__check_stype(evsel, PERF_SAMPLE_REGS_INTR, "IREGS",
455
- PERF_OUTPUT_IREGS))
490
+ evsel__do_check_stype(evsel, PERF_SAMPLE_REGS_INTR, "IREGS", PERF_OUTPUT_IREGS, allow_user_set))
456491 return -EINVAL;
457492
458493 if (PRINT_FIELD(UREGS) &&
459
- perf_evsel__check_stype(evsel, PERF_SAMPLE_REGS_USER, "UREGS",
460
- PERF_OUTPUT_UREGS))
494
+ evsel__check_stype(evsel, PERF_SAMPLE_REGS_USER, "UREGS", PERF_OUTPUT_UREGS))
461495 return -EINVAL;
462496
463497 if (PRINT_FIELD(PHYS_ADDR) &&
464
- perf_evsel__check_stype(evsel, PERF_SAMPLE_PHYS_ADDR, "PHYS_ADDR",
465
- PERF_OUTPUT_PHYS_ADDR))
498
+ evsel__check_stype(evsel, PERF_SAMPLE_PHYS_ADDR, "PHYS_ADDR", PERF_OUTPUT_PHYS_ADDR))
466499 return -EINVAL;
467500
468501 return 0;
....@@ -495,8 +528,9 @@
495528 */
496529 static int perf_session__check_output_opt(struct perf_session *session)
497530 {
531
+ bool tod = false;
498532 unsigned int j;
499
- struct perf_evsel *evsel;
533
+ struct evsel *evsel;
500534
501535 for (j = 0; j < OUTPUT_TYPE_MAX; ++j) {
502536 evsel = perf_session__find_first_evtype(session, attr_type(j));
....@@ -514,13 +548,14 @@
514548 }
515549
516550 if (evsel && output[j].fields &&
517
- perf_evsel__check_attr(evsel, session))
551
+ evsel__check_attr(evsel, session))
518552 return -1;
519553
520554 if (evsel == NULL)
521555 continue;
522556
523
- set_print_ip_opts(&evsel->attr);
557
+ set_print_ip_opts(&evsel->core.attr);
558
+ tod |= output[j].fields & PERF_OUTPUT_TOD;
524559 }
525560
526561 if (!no_callchain) {
....@@ -547,7 +582,7 @@
547582 j = PERF_TYPE_TRACEPOINT;
548583
549584 evlist__for_each_entry(session->evlist, evsel) {
550
- if (evsel->attr.type != j)
585
+ if (evsel->core.attr.type != j)
551586 continue;
552587
553588 if (evsel__has_callchain(evsel)) {
....@@ -555,40 +590,24 @@
555590 output[j].fields |= PERF_OUTPUT_SYM;
556591 output[j].fields |= PERF_OUTPUT_SYMOFFSET;
557592 output[j].fields |= PERF_OUTPUT_DSO;
558
- set_print_ip_opts(&evsel->attr);
593
+ set_print_ip_opts(&evsel->core.attr);
559594 goto out;
560595 }
561596 }
562597 }
563598
599
+ if (tod && !session->header.env.clock.enabled) {
600
+ pr_err("Can't provide 'tod' time, missing clock data. "
601
+ "Please record with -k/--clockid option.\n");
602
+ return -1;
603
+ }
564604 out:
565605 return 0;
566606 }
567607
568
-static int perf_sample__fprintf_iregs(struct perf_sample *sample,
569
- struct perf_event_attr *attr, FILE *fp)
608
+static int perf_sample__fprintf_regs(struct regs_dump *regs, uint64_t mask,
609
+ FILE *fp)
570610 {
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;
592611 unsigned i = 0, r;
593612 int printed = 0;
594613
....@@ -605,23 +624,91 @@
605624 return printed;
606625 }
607626
608
-static int perf_sample__fprintf_start(struct perf_sample *sample,
627
+#define DEFAULT_TOD_FMT "%F %H:%M:%S"
628
+
629
+static char*
630
+tod_scnprintf(struct perf_script *script, char *buf, int buflen,
631
+ u64 timestamp)
632
+{
633
+ u64 tod_ns, clockid_ns;
634
+ struct perf_env *env;
635
+ unsigned long nsec;
636
+ struct tm ltime;
637
+ char date[64];
638
+ time_t sec;
639
+
640
+ buf[0] = '\0';
641
+ if (buflen < 64 || !script)
642
+ return buf;
643
+
644
+ env = &script->session->header.env;
645
+ if (!env->clock.enabled) {
646
+ scnprintf(buf, buflen, "disabled");
647
+ return buf;
648
+ }
649
+
650
+ clockid_ns = env->clock.clockid_ns;
651
+ tod_ns = env->clock.tod_ns;
652
+
653
+ if (timestamp > clockid_ns)
654
+ tod_ns += timestamp - clockid_ns;
655
+ else
656
+ tod_ns -= clockid_ns - timestamp;
657
+
658
+ sec = (time_t) (tod_ns / NSEC_PER_SEC);
659
+ nsec = tod_ns - sec * NSEC_PER_SEC;
660
+
661
+ if (localtime_r(&sec, &ltime) == NULL) {
662
+ scnprintf(buf, buflen, "failed");
663
+ } else {
664
+ strftime(date, sizeof(date), DEFAULT_TOD_FMT, &ltime);
665
+
666
+ if (symbol_conf.nanosecs) {
667
+ snprintf(buf, buflen, "%s.%09lu", date, nsec);
668
+ } else {
669
+ snprintf(buf, buflen, "%s.%06lu",
670
+ date, nsec / NSEC_PER_USEC);
671
+ }
672
+ }
673
+
674
+ return buf;
675
+}
676
+
677
+static int perf_sample__fprintf_iregs(struct perf_sample *sample,
678
+ struct perf_event_attr *attr, FILE *fp)
679
+{
680
+ return perf_sample__fprintf_regs(&sample->intr_regs,
681
+ attr->sample_regs_intr, fp);
682
+}
683
+
684
+static int perf_sample__fprintf_uregs(struct perf_sample *sample,
685
+ struct perf_event_attr *attr, FILE *fp)
686
+{
687
+ return perf_sample__fprintf_regs(&sample->user_regs,
688
+ attr->sample_regs_user, fp);
689
+}
690
+
691
+static int perf_sample__fprintf_start(struct perf_script *script,
692
+ struct perf_sample *sample,
609693 struct thread *thread,
610
- struct perf_evsel *evsel,
694
+ struct evsel *evsel,
611695 u32 type, FILE *fp)
612696 {
613
- struct perf_event_attr *attr = &evsel->attr;
697
+ struct perf_event_attr *attr = &evsel->core.attr;
614698 unsigned long secs;
615699 unsigned long long nsecs;
616700 int printed = 0;
701
+ char tstr[128];
617702
618703 if (PRINT_FIELD(COMM)) {
704
+ const char *comm = thread ? thread__comm_str(thread) : ":-1";
705
+
619706 if (latency_format)
620
- printed += fprintf(fp, "%8.8s ", thread__comm_str(thread));
707
+ printed += fprintf(fp, "%8.8s ", comm);
621708 else if (PRINT_FIELD(IP) && evsel__has_callchain(evsel) && symbol_conf.use_callchain)
622
- printed += fprintf(fp, "%s ", thread__comm_str(thread));
709
+ printed += fprintf(fp, "%s ", comm);
623710 else
624
- printed += fprintf(fp, "%16s ", thread__comm_str(thread));
711
+ printed += fprintf(fp, "%16s ", comm);
625712 }
626713
627714 if (PRINT_FIELD(PID) && PRINT_FIELD(TID))
....@@ -682,16 +769,34 @@
682769 printed += ret;
683770 }
684771
772
+ if (PRINT_FIELD(TOD)) {
773
+ tod_scnprintf(script, tstr, sizeof(tstr), sample->time);
774
+ printed += fprintf(fp, "%s ", tstr);
775
+ }
776
+
685777 if (PRINT_FIELD(TIME)) {
686
- nsecs = sample->time;
778
+ u64 t = sample->time;
779
+ if (reltime) {
780
+ if (!initial_time)
781
+ initial_time = sample->time;
782
+ t = sample->time - initial_time;
783
+ } else if (deltatime) {
784
+ if (previous_time)
785
+ t = sample->time - previous_time;
786
+ else {
787
+ t = 0;
788
+ }
789
+ previous_time = sample->time;
790
+ }
791
+ nsecs = t;
687792 secs = nsecs / NSEC_PER_SEC;
688793 nsecs -= secs * NSEC_PER_SEC;
689794
690
- if (nanosecs)
795
+ if (symbol_conf.nanosecs)
691796 printed += fprintf(fp, "%5lu.%09llu: ", secs, nsecs);
692797 else {
693798 char sample_time[32];
694
- timestamp__scnprintf_usec(sample->time, sample_time, sizeof(sample_time));
799
+ timestamp__scnprintf_usec(t, sample_time, sizeof(sample_time));
695800 printed += fprintf(fp, "%12s: ", sample_time);
696801 }
697802 }
....@@ -713,6 +818,7 @@
713818 struct perf_event_attr *attr, FILE *fp)
714819 {
715820 struct branch_stack *br = sample->branch_stack;
821
+ struct branch_entry *entries = perf_sample__branch_entries(sample);
716822 struct addr_location alf, alt;
717823 u64 i, from, to;
718824 int printed = 0;
....@@ -721,8 +827,8 @@
721827 return 0;
722828
723829 for (i = 0; i < br->nr; i++) {
724
- from = br->entries[i].from;
725
- to = br->entries[i].to;
830
+ from = entries[i].from;
831
+ to = entries[i].to;
726832
727833 if (PRINT_FIELD(DSO)) {
728834 memset(&alf, 0, sizeof(alf));
....@@ -746,10 +852,10 @@
746852 }
747853
748854 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);
855
+ mispred_str(entries + i),
856
+ entries[i].flags.in_tx ? 'X' : '-',
857
+ entries[i].flags.abort ? 'A' : '-',
858
+ entries[i].flags.cycles);
753859 }
754860
755861 return printed;
....@@ -760,6 +866,7 @@
760866 struct perf_event_attr *attr, FILE *fp)
761867 {
762868 struct branch_stack *br = sample->branch_stack;
869
+ struct branch_entry *entries = perf_sample__branch_entries(sample);
763870 struct addr_location alf, alt;
764871 u64 i, from, to;
765872 int printed = 0;
....@@ -771,8 +878,8 @@
771878
772879 memset(&alf, 0, sizeof(alf));
773880 memset(&alt, 0, sizeof(alt));
774
- from = br->entries[i].from;
775
- to = br->entries[i].to;
881
+ from = entries[i].from;
882
+ to = entries[i].to;
776883
777884 thread__find_symbol_fb(thread, sample->cpumode, from, &alf);
778885 thread__find_symbol_fb(thread, sample->cpumode, to, &alt);
....@@ -791,10 +898,10 @@
791898 printed += fprintf(fp, ")");
792899 }
793900 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);
901
+ mispred_str(entries + i),
902
+ entries[i].flags.in_tx ? 'X' : '-',
903
+ entries[i].flags.abort ? 'A' : '-',
904
+ entries[i].flags.cycles);
798905 }
799906
800907 return printed;
....@@ -805,6 +912,7 @@
805912 struct perf_event_attr *attr, FILE *fp)
806913 {
807914 struct branch_stack *br = sample->branch_stack;
915
+ struct branch_entry *entries = perf_sample__branch_entries(sample);
808916 struct addr_location alf, alt;
809917 u64 i, from, to;
810918 int printed = 0;
....@@ -816,8 +924,8 @@
816924
817925 memset(&alf, 0, sizeof(alf));
818926 memset(&alt, 0, sizeof(alt));
819
- from = br->entries[i].from;
820
- to = br->entries[i].to;
927
+ from = entries[i].from;
928
+ to = entries[i].to;
821929
822930 if (thread__find_map_fb(thread, sample->cpumode, from, &alf) &&
823931 !alf.map->dso->adjust_symbols)
....@@ -840,10 +948,10 @@
840948 printed += fprintf(fp, ")");
841949 }
842950 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);
951
+ mispred_str(entries + i),
952
+ entries[i].flags.in_tx ? 'X' : '-',
953
+ entries[i].flags.abort ? 'A' : '-',
954
+ entries[i].flags.cycles);
847955 }
848956
849957 return printed;
....@@ -910,9 +1018,67 @@
9101018 return len;
9111019 }
9121020
1021
+static int map__fprintf_srccode(struct map *map, u64 addr, FILE *fp, struct srccode_state *state)
1022
+{
1023
+ char *srcfile;
1024
+ int ret = 0;
1025
+ unsigned line;
1026
+ int len;
1027
+ char *srccode;
1028
+
1029
+ if (!map || !map->dso)
1030
+ return 0;
1031
+ srcfile = get_srcline_split(map->dso,
1032
+ map__rip_2objdump(map, addr),
1033
+ &line);
1034
+ if (!srcfile)
1035
+ return 0;
1036
+
1037
+ /* Avoid redundant printing */
1038
+ if (state &&
1039
+ state->srcfile &&
1040
+ !strcmp(state->srcfile, srcfile) &&
1041
+ state->line == line) {
1042
+ free(srcfile);
1043
+ return 0;
1044
+ }
1045
+
1046
+ srccode = find_sourceline(srcfile, line, &len);
1047
+ if (!srccode)
1048
+ goto out_free_line;
1049
+
1050
+ ret = fprintf(fp, "|%-8d %.*s", line, len, srccode);
1051
+
1052
+ if (state) {
1053
+ state->srcfile = srcfile;
1054
+ state->line = line;
1055
+ }
1056
+ return ret;
1057
+
1058
+out_free_line:
1059
+ free(srcfile);
1060
+ return ret;
1061
+}
1062
+
1063
+static int print_srccode(struct thread *thread, u8 cpumode, uint64_t addr)
1064
+{
1065
+ struct addr_location al;
1066
+ int ret = 0;
1067
+
1068
+ memset(&al, 0, sizeof(al));
1069
+ thread__find_map(thread, cpumode, addr, &al);
1070
+ if (!al.map)
1071
+ return 0;
1072
+ ret = map__fprintf_srccode(al.map, al.addr, stdout,
1073
+ &thread->srccode_state);
1074
+ if (ret)
1075
+ ret += printf("\n");
1076
+ return ret;
1077
+}
1078
+
9131079 static int ip__fprintf_jump(uint64_t ip, struct branch_entry *en,
9141080 struct perf_insn *x, u8 *inbuf, int len,
915
- int insn, FILE *fp)
1081
+ int insn, FILE *fp, int *total_cycles)
9161082 {
9171083 int printed = fprintf(fp, "\t%016" PRIx64 "\t%-30s\t#%s%s%s%s", ip,
9181084 dump_insn(x, ip, inbuf, len, NULL),
....@@ -921,7 +1087,8 @@
9211087 en->flags.in_tx ? " INTX" : "",
9221088 en->flags.abort ? " ABORT" : "");
9231089 if (en->flags.cycles) {
924
- printed += fprintf(fp, " %d cycles", en->flags.cycles);
1090
+ *total_cycles += en->flags.cycles;
1091
+ printed += fprintf(fp, " %d cycles [%d]", en->flags.cycles, *total_cycles);
9251092 if (insn)
9261093 printed += fprintf(fp, " %.2f IPC", (float)insn / en->flags.cycles);
9271094 }
....@@ -972,12 +1139,14 @@
9721139 struct machine *machine, FILE *fp)
9731140 {
9741141 struct branch_stack *br = sample->branch_stack;
1142
+ struct branch_entry *entries = perf_sample__branch_entries(sample);
9751143 u64 start, end;
9761144 int i, insn, len, nr, ilen, printed = 0;
9771145 struct perf_insn x;
9781146 u8 buffer[MAXBB];
9791147 unsigned off;
9801148 struct symbol *lastsym = NULL;
1149
+ int total_cycles = 0;
9811150
9821151 if (!(br && br->nr))
9831152 return 0;
....@@ -991,29 +1160,31 @@
9911160 printed += fprintf(fp, "%c", '\n');
9921161
9931162 /* 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,
1163
+ len = grab_bb(buffer, entries[nr-1].from,
1164
+ entries[nr-1].from,
9961165 machine, thread, &x.is64bit, &x.cpumode, false);
9971166 if (len > 0) {
998
- printed += ip__fprintf_sym(br->entries[nr - 1].from, thread,
1167
+ printed += ip__fprintf_sym(entries[nr - 1].from, thread,
9991168 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);
1169
+ printed += ip__fprintf_jump(entries[nr - 1].from, &entries[nr - 1],
1170
+ &x, buffer, len, 0, fp, &total_cycles);
1171
+ if (PRINT_FIELD(SRCCODE))
1172
+ printed += print_srccode(thread, x.cpumode, entries[nr - 1].from);
10021173 }
10031174
10041175 /* Print all blocks */
10051176 for (i = nr - 2; i >= 0; i--) {
1006
- if (br->entries[i].from || br->entries[i].to)
1177
+ if (entries[i].from || entries[i].to)
10071178 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;
1179
+ entries[i].from,
1180
+ entries[i].to);
1181
+ start = entries[i + 1].to;
1182
+ end = entries[i].from;
10121183
10131184 len = grab_bb(buffer, start, end, machine, thread, &x.is64bit, &x.cpumode, false);
10141185 /* Patch up missing kernel transfers due to ring filters */
10151186 if (len == -ENXIO && i > 0) {
1016
- end = br->entries[--i].from;
1187
+ end = entries[--i].from;
10171188 pr_debug("\tpatching up to %" PRIx64 "-%" PRIx64 "\n", start, end);
10181189 len = grab_bb(buffer, start, end, machine, thread, &x.is64bit, &x.cpumode, false);
10191190 }
....@@ -1026,7 +1197,10 @@
10261197
10271198 printed += ip__fprintf_sym(ip, thread, x.cpumode, x.cpu, &lastsym, attr, fp);
10281199 if (ip == end) {
1029
- printed += ip__fprintf_jump(ip, &br->entries[i], &x, buffer + off, len - off, insn, fp);
1200
+ printed += ip__fprintf_jump(ip, &entries[i], &x, buffer + off, len - off, ++insn, fp,
1201
+ &total_cycles);
1202
+ if (PRINT_FIELD(SRCCODE))
1203
+ printed += print_srccode(thread, x.cpumode, ip);
10301204 break;
10311205 } else {
10321206 ilen = 0;
....@@ -1034,6 +1208,8 @@
10341208 dump_insn(&x, ip, buffer + off, len - off, &ilen));
10351209 if (ilen == 0)
10361210 break;
1211
+ if (PRINT_FIELD(SRCCODE))
1212
+ print_srccode(thread, x.cpumode, ip);
10371213 insn++;
10381214 }
10391215 }
....@@ -1045,16 +1221,25 @@
10451221 * Hit the branch? In this case we are already done, and the target
10461222 * has not been executed yet.
10471223 */
1048
- if (br->entries[0].from == sample->ip)
1224
+ if (entries[0].from == sample->ip)
10491225 goto out;
1050
- if (br->entries[0].flags.abort)
1226
+ if (entries[0].flags.abort)
10511227 goto out;
10521228
10531229 /*
10541230 * Print final block upto sample
1231
+ *
1232
+ * Due to pipeline delays the LBRs might be missing a branch
1233
+ * or two, which can result in very large or negative blocks
1234
+ * between final branch and sample. When this happens just
1235
+ * continue walking after the last TO until we hit a branch.
10551236 */
1056
- start = br->entries[0].to;
1237
+ start = entries[0].to;
10571238 end = sample->ip;
1239
+ if (end < start) {
1240
+ /* Missing jump. Scan 128 bytes for the next branch */
1241
+ end = start + 128;
1242
+ }
10581243 len = grab_bb(buffer, start, end, machine, thread, &x.is64bit, &x.cpumode, true);
10591244 printed += ip__fprintf_sym(start, thread, x.cpumode, x.cpu, &lastsym, attr, fp);
10601245 if (len <= 0) {
....@@ -1063,9 +1248,10 @@
10631248 machine, thread, &x.is64bit, &x.cpumode, false);
10641249 if (len <= 0)
10651250 goto out;
1066
-
10671251 printed += fprintf(fp, "\t%016" PRIx64 "\t%s\n", sample->ip,
10681252 dump_insn(&x, sample->ip, buffer, len, NULL));
1253
+ if (PRINT_FIELD(SRCCODE))
1254
+ print_srccode(thread, x.cpumode, sample->ip);
10691255 goto out;
10701256 }
10711257 for (off = 0; off <= end - start; off += ilen) {
....@@ -1074,6 +1260,15 @@
10741260 dump_insn(&x, start + off, buffer + off, len - off, &ilen));
10751261 if (ilen == 0)
10761262 break;
1263
+ if (arch_is_branch(buffer + off, len - off, x.is64bit) && start + off != sample->ip) {
1264
+ /*
1265
+ * Hit a missing branch. Just stop.
1266
+ */
1267
+ printed += fprintf(fp, "\t... not reaching sample ...\n");
1268
+ break;
1269
+ }
1270
+ if (PRINT_FIELD(SRCCODE))
1271
+ print_srccode(thread, x.cpumode, start + off);
10771272 }
10781273 out:
10791274 return printed;
....@@ -1108,17 +1303,46 @@
11081303 return printed;
11091304 }
11101305
1306
+static const char *resolve_branch_sym(struct perf_sample *sample,
1307
+ struct evsel *evsel,
1308
+ struct thread *thread,
1309
+ struct addr_location *al,
1310
+ u64 *ip)
1311
+{
1312
+ struct addr_location addr_al;
1313
+ struct perf_event_attr *attr = &evsel->core.attr;
1314
+ const char *name = NULL;
1315
+
1316
+ if (sample->flags & (PERF_IP_FLAG_CALL | PERF_IP_FLAG_TRACE_BEGIN)) {
1317
+ if (sample_addr_correlates_sym(attr)) {
1318
+ thread__resolve(thread, &addr_al, sample);
1319
+ if (addr_al.sym)
1320
+ name = addr_al.sym->name;
1321
+ else
1322
+ *ip = sample->addr;
1323
+ } else {
1324
+ *ip = sample->addr;
1325
+ }
1326
+ } else if (sample->flags & (PERF_IP_FLAG_RETURN | PERF_IP_FLAG_TRACE_END)) {
1327
+ if (al->sym)
1328
+ name = al->sym->name;
1329
+ else
1330
+ *ip = sample->ip;
1331
+ }
1332
+ return name;
1333
+}
1334
+
11111335 static int perf_sample__fprintf_callindent(struct perf_sample *sample,
1112
- struct perf_evsel *evsel,
1336
+ struct evsel *evsel,
11131337 struct thread *thread,
11141338 struct addr_location *al, FILE *fp)
11151339 {
1116
- struct perf_event_attr *attr = &evsel->attr;
1117
- size_t depth = thread_stack__depth(thread);
1118
- struct addr_location addr_al;
1340
+ struct perf_event_attr *attr = &evsel->core.attr;
1341
+ size_t depth = thread_stack__depth(thread, sample->cpu);
11191342 const char *name = NULL;
11201343 static int spacing;
11211344 int len = 0;
1345
+ int dlen = 0;
11221346 u64 ip = 0;
11231347
11241348 /*
....@@ -1128,21 +1352,12 @@
11281352 if (thread->ts && sample->flags & PERF_IP_FLAG_RETURN)
11291353 depth += 1;
11301354
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;
1355
+ name = resolve_branch_sym(sample, evsel, thread, al, &ip);
1356
+
1357
+ if (PRINT_FIELD(DSO) && !(PRINT_FIELD(IP) || PRINT_FIELD(ADDR))) {
1358
+ dlen += fprintf(fp, "(");
1359
+ dlen += map__fprintf_dsoname(al->map, fp);
1360
+ dlen += fprintf(fp, ")\t");
11461361 }
11471362
11481363 if (name)
....@@ -1163,7 +1378,13 @@
11631378 if (len < spacing)
11641379 len += fprintf(fp, "%*s", spacing - len, "");
11651380
1166
- return len;
1381
+ return len + dlen;
1382
+}
1383
+
1384
+__weak void arch_fetch_insn(struct perf_sample *sample __maybe_unused,
1385
+ struct thread *thread __maybe_unused,
1386
+ struct machine *machine __maybe_unused)
1387
+{
11671388 }
11681389
11691390 static int perf_sample__fprintf_insn(struct perf_sample *sample,
....@@ -1173,9 +1394,12 @@
11731394 {
11741395 int printed = 0;
11751396
1397
+ if (sample->insn_len == 0 && native_arch)
1398
+ arch_fetch_insn(sample, thread, machine);
1399
+
11761400 if (PRINT_FIELD(INSNLEN))
11771401 printed += fprintf(fp, " ilen: %d", sample->insn_len);
1178
- if (PRINT_FIELD(INSN)) {
1402
+ if (PRINT_FIELD(INSN) && sample->insn_len) {
11791403 int i;
11801404
11811405 printed += fprintf(fp, " insn:");
....@@ -1188,13 +1412,27 @@
11881412 return printed;
11891413 }
11901414
1415
+static int perf_sample__fprintf_ipc(struct perf_sample *sample,
1416
+ struct perf_event_attr *attr, FILE *fp)
1417
+{
1418
+ unsigned int ipc;
1419
+
1420
+ if (!PRINT_FIELD(IPC) || !sample->cyc_cnt || !sample->insn_cnt)
1421
+ return 0;
1422
+
1423
+ ipc = (sample->insn_cnt * 100) / sample->cyc_cnt;
1424
+
1425
+ return fprintf(fp, " \t IPC: %u.%02u (%" PRIu64 "/%" PRIu64 ") ",
1426
+ ipc / 100, ipc % 100, sample->insn_cnt, sample->cyc_cnt);
1427
+}
1428
+
11911429 static int perf_sample__fprintf_bts(struct perf_sample *sample,
1192
- struct perf_evsel *evsel,
1430
+ struct evsel *evsel,
11931431 struct thread *thread,
11941432 struct addr_location *al,
11951433 struct machine *machine, FILE *fp)
11961434 {
1197
- struct perf_event_attr *attr = &evsel->attr;
1435
+ struct perf_event_attr *attr = &evsel->core.attr;
11981436 unsigned int type = output_type(attr->type);
11991437 bool print_srcline_last = false;
12001438 int printed = 0;
....@@ -1221,22 +1459,34 @@
12211459 } else
12221460 printed += fprintf(fp, "\n");
12231461
1224
- printed += sample__fprintf_sym(sample, al, 0, print_opts, cursor, fp);
1462
+ printed += sample__fprintf_sym(sample, al, 0, print_opts, cursor,
1463
+ symbol_conf.bt_stop_list, fp);
12251464 }
12261465
12271466 /* print branch_to information */
12281467 if (PRINT_FIELD(ADDR) ||
1229
- ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) &&
1468
+ ((evsel->core.attr.sample_type & PERF_SAMPLE_ADDR) &&
12301469 !output[type].user_set)) {
12311470 printed += fprintf(fp, " => ");
12321471 printed += perf_sample__fprintf_addr(sample, thread, attr, fp);
12331472 }
12341473
1474
+ printed += perf_sample__fprintf_ipc(sample, attr, fp);
1475
+
12351476 if (print_srcline_last)
12361477 printed += map__fprintf_srcline(al->map, al->addr, "\n ", fp);
12371478
12381479 printed += perf_sample__fprintf_insn(sample, attr, thread, machine, fp);
1239
- return printed + fprintf(fp, "\n");
1480
+ printed += fprintf(fp, "\n");
1481
+ if (PRINT_FIELD(SRCCODE)) {
1482
+ int ret = map__fprintf_srccode(al->map, al->addr, stdout,
1483
+ &thread->srccode_state);
1484
+ if (ret) {
1485
+ printed += ret;
1486
+ printed += printf("\n");
1487
+ }
1488
+ }
1489
+ return printed;
12401490 }
12411491
12421492 static struct {
....@@ -1259,6 +1509,18 @@
12591509 {0, NULL}
12601510 };
12611511
1512
+static const char *sample_flags_to_name(u32 flags)
1513
+{
1514
+ int i;
1515
+
1516
+ for (i = 0; sample_flags[i].name ; i++) {
1517
+ if (sample_flags[i].flags == flags)
1518
+ return sample_flags[i].name;
1519
+ }
1520
+
1521
+ return NULL;
1522
+}
1523
+
12621524 static int perf_sample__fprintf_flags(u32 flags, FILE *fp)
12631525 {
12641526 const char *chars = PERF_IP_FLAG_CHARS;
....@@ -1268,11 +1530,20 @@
12681530 char str[33];
12691531 int i, pos = 0;
12701532
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
- }
1533
+ name = sample_flags_to_name(flags & ~PERF_IP_FLAG_IN_TX);
1534
+ if (name)
1535
+ return fprintf(fp, " %-15s%4s ", name, in_tx ? "(x)" : "");
1536
+
1537
+ if (flags & PERF_IP_FLAG_TRACE_BEGIN) {
1538
+ name = sample_flags_to_name(flags & ~(PERF_IP_FLAG_IN_TX | PERF_IP_FLAG_TRACE_BEGIN));
1539
+ if (name)
1540
+ return fprintf(fp, " tr strt %-7s%4s ", name, in_tx ? "(x)" : "");
1541
+ }
1542
+
1543
+ if (flags & PERF_IP_FLAG_TRACE_END) {
1544
+ name = sample_flags_to_name(flags & ~(PERF_IP_FLAG_IN_TX | PERF_IP_FLAG_TRACE_END));
1545
+ if (name)
1546
+ return fprintf(fp, " tr end %-7s%4s ", name, in_tx ? "(x)" : "");
12761547 }
12771548
12781549 for (i = 0; i < n; i++, flags >>= 1) {
....@@ -1285,10 +1556,7 @@
12851556 }
12861557 str[pos] = 0;
12871558
1288
- if (name)
1289
- return fprintf(fp, " %-7s%4s ", name, in_tx ? "(x)" : "");
1290
-
1291
- return fprintf(fp, " %-11s ", str);
1559
+ return fprintf(fp, " %-19s ", str);
12921560 }
12931561
12941562 struct printer_data {
....@@ -1468,9 +1736,9 @@
14681736 }
14691737
14701738 static int perf_sample__fprintf_synth(struct perf_sample *sample,
1471
- struct perf_evsel *evsel, FILE *fp)
1739
+ struct evsel *evsel, FILE *fp)
14721740 {
1473
- switch (evsel->attr.config) {
1741
+ switch (evsel->core.attr.config) {
14741742 case PERF_SYNTH_INTEL_PTWRITE:
14751743 return perf_sample__fprintf_synth_ptwrite(sample, fp);
14761744 case PERF_SYNTH_INTEL_MWAIT:
....@@ -1490,33 +1758,13 @@
14901758 return 0;
14911759 }
14921760
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)
1761
+static int evlist__max_name_len(struct evlist *evlist)
15141762 {
1515
- struct perf_evsel *evsel;
1763
+ struct evsel *evsel;
15161764 int max = 0;
15171765
15181766 evlist__for_each_entry(evlist, evsel) {
1519
- int len = strlen(perf_evsel__name(evsel));
1767
+ int len = strlen(evsel__name(evsel));
15201768
15211769 max = MAX(len, max);
15221770 }
....@@ -1544,11 +1792,12 @@
15441792 struct metric_ctx {
15451793 struct perf_sample *sample;
15461794 struct thread *thread;
1547
- struct perf_evsel *evsel;
1795
+ struct evsel *evsel;
15481796 FILE *fp;
15491797 };
15501798
1551
-static void script_print_metric(void *ctx, const char *color,
1799
+static void script_print_metric(struct perf_stat_config *config __maybe_unused,
1800
+ void *ctx, const char *color,
15521801 const char *fmt,
15531802 const char *unit, double val)
15541803 {
....@@ -1556,7 +1805,7 @@
15561805
15571806 if (!fmt)
15581807 return;
1559
- perf_sample__fprintf_start(mctx->sample, mctx->thread, mctx->evsel,
1808
+ perf_sample__fprintf_start(NULL, mctx->sample, mctx->thread, mctx->evsel,
15601809 PERF_RECORD_SAMPLE, mctx->fp);
15611810 fputs("\tmetric: ", mctx->fp);
15621811 if (color)
....@@ -1566,18 +1815,19 @@
15661815 fprintf(mctx->fp, " %s\n", unit);
15671816 }
15681817
1569
-static void script_new_line(void *ctx)
1818
+static void script_new_line(struct perf_stat_config *config __maybe_unused,
1819
+ void *ctx)
15701820 {
15711821 struct metric_ctx *mctx = ctx;
15721822
1573
- perf_sample__fprintf_start(mctx->sample, mctx->thread, mctx->evsel,
1823
+ perf_sample__fprintf_start(NULL, mctx->sample, mctx->thread, mctx->evsel,
15741824 PERF_RECORD_SAMPLE, mctx->fp);
15751825 fputs("\tmetric: ", mctx->fp);
15761826 }
15771827
15781828 static void perf_sample__fprint_metric(struct perf_script *script,
15791829 struct thread *thread,
1580
- struct perf_evsel *evsel,
1830
+ struct evsel *evsel,
15811831 struct perf_sample *sample,
15821832 FILE *fp)
15831833 {
....@@ -1592,7 +1842,7 @@
15921842 },
15931843 .force_header = false,
15941844 };
1595
- struct perf_evsel *ev2;
1845
+ struct evsel *ev2;
15961846 u64 val;
15971847
15981848 if (!evsel->stats)
....@@ -1605,9 +1855,9 @@
16051855 sample->cpu,
16061856 &rt_stat);
16071857 evsel_script(evsel)->val = val;
1608
- if (evsel_script(evsel->leader)->gnum == evsel->leader->nr_members) {
1858
+ if (evsel_script(evsel->leader)->gnum == evsel->leader->core.nr_members) {
16091859 for_each_group_member (ev2, evsel->leader) {
1610
- perf_stat__print_shadow_stats(ev2,
1860
+ perf_stat__print_shadow_stats(&stat_config, ev2,
16111861 evsel_script(ev2)->val,
16121862 sample->cpu,
16131863 &ctx,
....@@ -1618,33 +1868,80 @@
16181868 }
16191869 }
16201870
1871
+static bool show_event(struct perf_sample *sample,
1872
+ struct evsel *evsel,
1873
+ struct thread *thread,
1874
+ struct addr_location *al)
1875
+{
1876
+ int depth = thread_stack__depth(thread, sample->cpu);
1877
+
1878
+ if (!symbol_conf.graph_function)
1879
+ return true;
1880
+
1881
+ if (thread->filter) {
1882
+ if (depth <= thread->filter_entry_depth) {
1883
+ thread->filter = false;
1884
+ return false;
1885
+ }
1886
+ return true;
1887
+ } else {
1888
+ const char *s = symbol_conf.graph_function;
1889
+ u64 ip;
1890
+ const char *name = resolve_branch_sym(sample, evsel, thread, al,
1891
+ &ip);
1892
+ unsigned nlen;
1893
+
1894
+ if (!name)
1895
+ return false;
1896
+ nlen = strlen(name);
1897
+ while (*s) {
1898
+ unsigned len = strcspn(s, ",");
1899
+ if (nlen == len && !strncmp(name, s, len)) {
1900
+ thread->filter = true;
1901
+ thread->filter_entry_depth = depth;
1902
+ return true;
1903
+ }
1904
+ s += len;
1905
+ if (*s == ',')
1906
+ s++;
1907
+ }
1908
+ return false;
1909
+ }
1910
+}
1911
+
16211912 static void process_event(struct perf_script *script,
1622
- struct perf_sample *sample, struct perf_evsel *evsel,
1913
+ struct perf_sample *sample, struct evsel *evsel,
16231914 struct addr_location *al,
16241915 struct machine *machine)
16251916 {
16261917 struct thread *thread = al->thread;
1627
- struct perf_event_attr *attr = &evsel->attr;
1918
+ struct perf_event_attr *attr = &evsel->core.attr;
16281919 unsigned int type = output_type(attr->type);
1629
- struct perf_evsel_script *es = evsel->priv;
1920
+ struct evsel_script *es = evsel->priv;
16301921 FILE *fp = es->fp;
16311922
16321923 if (output[type].fields == 0)
16331924 return;
16341925
1926
+ if (!show_event(sample, evsel, thread, al))
1927
+ return;
1928
+
1929
+ if (evswitch__discard(&script->evswitch, evsel))
1930
+ return;
1931
+
16351932 ++es->samples;
16361933
1637
- perf_sample__fprintf_start(sample, thread, evsel,
1934
+ perf_sample__fprintf_start(script, sample, thread, evsel,
16381935 PERF_RECORD_SAMPLE, fp);
16391936
16401937 if (PRINT_FIELD(PERIOD))
16411938 fprintf(fp, "%10" PRIu64 " ", sample->period);
16421939
16431940 if (PRINT_FIELD(EVNAME)) {
1644
- const char *evname = perf_evsel__name(evsel);
1941
+ const char *evname = evsel__name(evsel);
16451942
16461943 if (!script->name_width)
1647
- script->name_width = perf_evlist__max_name_len(script->session->evlist);
1944
+ script->name_width = evlist__max_name_len(script->session->evlist);
16481945
16491946 fprintf(fp, "%*s: ", script->name_width, evname ?: "[unknown]");
16501947 }
....@@ -1677,13 +1974,17 @@
16771974 if (PRINT_FIELD(IP)) {
16781975 struct callchain_cursor *cursor = NULL;
16791976
1977
+ if (script->stitch_lbr)
1978
+ al->thread->lbr_stitch_enable = true;
1979
+
16801980 if (symbol_conf.use_callchain && sample->callchain &&
16811981 thread__resolve_callchain(al->thread, &callchain_cursor, evsel,
16821982 sample, NULL, NULL, scripting_max_stack) == 0)
16831983 cursor = &callchain_cursor;
16841984
16851985 fputc(cursor ? '\n' : ' ', fp);
1686
- sample__fprintf_sym(sample, al, 0, output[type].print_ip_opts, cursor, fp);
1986
+ sample__fprintf_sym(sample, al, 0, output[type].print_ip_opts, cursor,
1987
+ symbol_conf.bt_stop_list, fp);
16871988 }
16881989
16891990 if (PRINT_FIELD(IREGS))
....@@ -1699,28 +2000,40 @@
16992000 else if (PRINT_FIELD(BRSTACKOFF))
17002001 perf_sample__fprintf_brstackoff(sample, thread, attr, fp);
17012002
1702
- if (perf_evsel__is_bpf_output(evsel) && PRINT_FIELD(BPF_OUTPUT))
2003
+ if (evsel__is_bpf_output(evsel) && PRINT_FIELD(BPF_OUTPUT))
17032004 perf_sample__fprintf_bpf_output(sample, fp);
17042005 perf_sample__fprintf_insn(sample, attr, thread, machine, fp);
17052006
17062007 if (PRINT_FIELD(PHYS_ADDR))
17072008 fprintf(fp, "%16" PRIx64, sample->phys_addr);
2009
+
2010
+ perf_sample__fprintf_ipc(sample, attr, fp);
2011
+
17082012 fprintf(fp, "\n");
2013
+
2014
+ if (PRINT_FIELD(SRCCODE)) {
2015
+ if (map__fprintf_srccode(al->map, al->addr, stdout,
2016
+ &thread->srccode_state))
2017
+ printf("\n");
2018
+ }
17092019
17102020 if (PRINT_FIELD(METRIC))
17112021 perf_sample__fprint_metric(script, thread, evsel, sample, fp);
2022
+
2023
+ if (verbose)
2024
+ fflush(fp);
17122025 }
17132026
17142027 static struct scripting_ops *scripting_ops;
17152028
1716
-static void __process_stat(struct perf_evsel *counter, u64 tstamp)
2029
+static void __process_stat(struct evsel *counter, u64 tstamp)
17172030 {
1718
- int nthreads = thread_map__nr(counter->threads);
1719
- int ncpus = perf_evsel__nr_cpus(counter);
2031
+ int nthreads = perf_thread_map__nr(counter->core.threads);
2032
+ int ncpus = evsel__nr_cpus(counter);
17202033 int cpu, thread;
17212034 static int header_printed;
17222035
1723
- if (counter->system_wide)
2036
+ if (counter->core.system_wide)
17242037 nthreads = 1;
17252038
17262039 if (!header_printed) {
....@@ -1736,18 +2049,18 @@
17362049 counts = perf_counts(counter->counts, cpu, thread);
17372050
17382051 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),
2052
+ counter->core.cpus->map[cpu],
2053
+ perf_thread_map__pid(counter->core.threads, thread),
17412054 counts->val,
17422055 counts->ena,
17432056 counts->run,
17442057 tstamp,
1745
- perf_evsel__name(counter));
2058
+ evsel__name(counter));
17462059 }
17472060 }
17482061 }
17492062
1750
-static void process_stat(struct perf_evsel *counter, u64 tstamp)
2063
+static void process_stat(struct evsel *counter, u64 tstamp)
17512064 {
17522065 if (scripting_ops && scripting_ops->process_stat)
17532066 scripting_ops->process_stat(&stat_config, counter, tstamp);
....@@ -1779,10 +2092,17 @@
17792092 return scripting_ops ? scripting_ops->stop_script() : 0;
17802093 }
17812094
2095
+static bool filter_cpu(struct perf_sample *sample)
2096
+{
2097
+ if (cpu_list && sample->cpu != (u32)-1)
2098
+ return !test_bit(sample->cpu, cpu_bitmap);
2099
+ return false;
2100
+}
2101
+
17822102 static int process_sample_event(struct perf_tool *tool,
17832103 union perf_event *event,
17842104 struct perf_sample *sample,
1785
- struct perf_evsel *evsel,
2105
+ struct evsel *evsel,
17862106 struct machine *machine)
17872107 {
17882108 struct perf_script *scr = container_of(tool, struct perf_script, tool);
....@@ -1813,7 +2133,7 @@
18132133 if (al.filtered)
18142134 goto out_put;
18152135
1816
- if (cpu_list && !test_bit(sample->cpu, cpu_bitmap))
2136
+ if (filter_cpu(sample))
18172137 goto out_put;
18182138
18192139 if (scripting_ops)
....@@ -1826,50 +2146,116 @@
18262146 return 0;
18272147 }
18282148
2149
+// Used when scr->per_event_dump is not set
2150
+static struct evsel_script es_stdout;
2151
+
18292152 static int process_attr(struct perf_tool *tool, union perf_event *event,
1830
- struct perf_evlist **pevlist)
2153
+ struct evlist **pevlist)
18312154 {
18322155 struct perf_script *scr = container_of(tool, struct perf_script, tool);
1833
- struct perf_evlist *evlist;
1834
- struct perf_evsel *evsel, *pos;
2156
+ struct evlist *evlist;
2157
+ struct evsel *evsel, *pos;
2158
+ u64 sample_type;
18352159 int err;
1836
- static struct perf_evsel_script *es;
18372160
18382161 err = perf_event__process_attr(tool, event, pevlist);
18392162 if (err)
18402163 return err;
18412164
18422165 evlist = *pevlist;
1843
- evsel = perf_evlist__last(*pevlist);
2166
+ evsel = evlist__last(*pevlist);
18442167
18452168 if (!evsel->priv) {
1846
- if (scr->per_event_dump) {
1847
- evsel->priv = perf_evsel_script__new(evsel,
1848
- scr->session->data);
1849
- } else {
1850
- es = zalloc(sizeof(*es));
1851
- if (!es)
2169
+ if (scr->per_event_dump) {
2170
+ evsel->priv = evsel_script__new(evsel, scr->session->data);
2171
+ if (!evsel->priv)
18522172 return -ENOMEM;
1853
- es->fp = stdout;
1854
- evsel->priv = es;
2173
+ } else { // Replicate what is done in perf_script__setup_per_event_dump()
2174
+ es_stdout.fp = stdout;
2175
+ evsel->priv = &es_stdout;
18552176 }
18562177 }
18572178
1858
- if (evsel->attr.type >= PERF_TYPE_MAX &&
1859
- evsel->attr.type != PERF_TYPE_SYNTH)
2179
+ if (evsel->core.attr.type >= PERF_TYPE_MAX &&
2180
+ evsel->core.attr.type != PERF_TYPE_SYNTH)
18602181 return 0;
18612182
18622183 evlist__for_each_entry(evlist, pos) {
1863
- if (pos->attr.type == evsel->attr.type && pos != evsel)
2184
+ if (pos->core.attr.type == evsel->core.attr.type && pos != evsel)
18642185 return 0;
18652186 }
18662187
1867
- set_print_ip_opts(&evsel->attr);
2188
+ if (evsel->core.attr.sample_type) {
2189
+ err = evsel__check_attr(evsel, scr->session);
2190
+ if (err)
2191
+ return err;
2192
+ }
18682193
1869
- if (evsel->attr.sample_type)
1870
- err = perf_evsel__check_attr(evsel, scr->session);
2194
+ /*
2195
+ * Check if we need to enable callchains based
2196
+ * on events sample_type.
2197
+ */
2198
+ sample_type = evlist__combined_sample_type(evlist);
2199
+ callchain_param_setup(sample_type);
18712200
1872
- return err;
2201
+ /* Enable fields for callchain entries */
2202
+ if (symbol_conf.use_callchain &&
2203
+ (sample_type & PERF_SAMPLE_CALLCHAIN ||
2204
+ sample_type & PERF_SAMPLE_BRANCH_STACK ||
2205
+ (sample_type & PERF_SAMPLE_REGS_USER &&
2206
+ sample_type & PERF_SAMPLE_STACK_USER))) {
2207
+ int type = output_type(evsel->core.attr.type);
2208
+
2209
+ if (!(output[type].user_unset_fields & PERF_OUTPUT_IP))
2210
+ output[type].fields |= PERF_OUTPUT_IP;
2211
+ if (!(output[type].user_unset_fields & PERF_OUTPUT_SYM))
2212
+ output[type].fields |= PERF_OUTPUT_SYM;
2213
+ }
2214
+ set_print_ip_opts(&evsel->core.attr);
2215
+ return 0;
2216
+}
2217
+
2218
+static int print_event_with_time(struct perf_tool *tool,
2219
+ union perf_event *event,
2220
+ struct perf_sample *sample,
2221
+ struct machine *machine,
2222
+ pid_t pid, pid_t tid, u64 timestamp)
2223
+{
2224
+ struct perf_script *script = container_of(tool, struct perf_script, tool);
2225
+ struct perf_session *session = script->session;
2226
+ struct evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
2227
+ struct thread *thread = NULL;
2228
+
2229
+ if (evsel && !evsel->core.attr.sample_id_all) {
2230
+ sample->cpu = 0;
2231
+ sample->time = timestamp;
2232
+ sample->pid = pid;
2233
+ sample->tid = tid;
2234
+ }
2235
+
2236
+ if (filter_cpu(sample))
2237
+ return 0;
2238
+
2239
+ if (tid != -1)
2240
+ thread = machine__findnew_thread(machine, pid, tid);
2241
+
2242
+ if (evsel) {
2243
+ perf_sample__fprintf_start(script, sample, thread, evsel,
2244
+ event->header.type, stdout);
2245
+ }
2246
+
2247
+ perf_event__fprintf(event, machine, stdout);
2248
+
2249
+ thread__put(thread);
2250
+
2251
+ return 0;
2252
+}
2253
+
2254
+static int print_event(struct perf_tool *tool, union perf_event *event,
2255
+ struct perf_sample *sample, struct machine *machine,
2256
+ pid_t pid, pid_t tid)
2257
+{
2258
+ return print_event_with_time(tool, event, sample, machine, pid, tid, 0);
18732259 }
18742260
18752261 static int process_comm_event(struct perf_tool *tool,
....@@ -1877,34 +2263,11 @@
18772263 struct perf_sample *sample,
18782264 struct machine *machine)
18792265 {
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
-
18922266 if (perf_event__process_comm(tool, event, sample, machine) < 0)
1893
- goto out;
2267
+ return -1;
18942268
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;
2269
+ return print_event(tool, event, sample, machine, event->comm.pid,
2270
+ event->comm.tid);
19082271 }
19092272
19102273 static int process_namespaces_event(struct perf_tool *tool,
....@@ -1912,35 +2275,23 @@
19122275 struct perf_sample *sample,
19132276 struct machine *machine)
19142277 {
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
-
19282278 if (perf_event__process_namespaces(tool, event, sample, machine) < 0)
1929
- goto out;
2279
+ return -1;
19302280
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;
2281
+ return print_event(tool, event, sample, machine, event->namespaces.pid,
2282
+ event->namespaces.tid);
2283
+}
2284
+
2285
+static int process_cgroup_event(struct perf_tool *tool,
2286
+ union perf_event *event,
2287
+ struct perf_sample *sample,
2288
+ struct machine *machine)
2289
+{
2290
+ if (perf_event__process_cgroup(tool, event, sample, machine) < 0)
2291
+ return -1;
2292
+
2293
+ return print_event(tool, event, sample, machine, sample->pid,
2294
+ sample->tid);
19442295 }
19452296
19462297 static int process_fork_event(struct perf_tool *tool,
....@@ -1948,65 +2299,24 @@
19482299 struct perf_sample *sample,
19492300 struct machine *machine)
19502301 {
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
-
19562302 if (perf_event__process_fork(tool, event, sample, machine) < 0)
19572303 return -1;
19582304
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;
2305
+ return print_event_with_time(tool, event, sample, machine,
2306
+ event->fork.pid, event->fork.tid,
2307
+ event->fork.time);
19772308 }
19782309 static int process_exit_event(struct perf_tool *tool,
19792310 union perf_event *event,
19802311 struct perf_sample *sample,
19812312 struct machine *machine)
19822313 {
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");
2314
+ /* Print before 'exit' deletes anything */
2315
+ if (print_event_with_time(tool, event, sample, machine, event->fork.pid,
2316
+ event->fork.tid, event->fork.time))
19922317 return -1;
1993
- }
19942318
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;
2319
+ return perf_event__process_exit(tool, event, sample, machine);
20102320 }
20112321
20122322 static int process_mmap_event(struct perf_tool *tool,
....@@ -2014,31 +2324,11 @@
20142324 struct perf_sample *sample,
20152325 struct machine *machine)
20162326 {
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
-
20222327 if (perf_event__process_mmap(tool, event, sample, machine) < 0)
20232328 return -1;
20242329
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;
2330
+ return print_event(tool, event, sample, machine, event->mmap.pid,
2331
+ event->mmap.tid);
20422332 }
20432333
20442334 static int process_mmap2_event(struct perf_tool *tool,
....@@ -2046,31 +2336,11 @@
20462336 struct perf_sample *sample,
20472337 struct machine *machine)
20482338 {
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
-
20542339 if (perf_event__process_mmap2(tool, event, sample, machine) < 0)
20552340 return -1;
20562341
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;
2342
+ return print_event(tool, event, sample, machine, event->mmap2.pid,
2343
+ event->mmap2.tid);
20742344 }
20752345
20762346 static int process_switch_event(struct perf_tool *tool,
....@@ -2078,26 +2348,19 @@
20782348 struct perf_sample *sample,
20792349 struct machine *machine)
20802350 {
2081
- struct thread *thread;
20822351 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);
20852352
20862353 if (perf_event__process_switch(tool, event, sample, machine) < 0)
20872354 return -1;
20882355
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
- }
2356
+ if (scripting_ops && scripting_ops->process_switch && !filter_cpu(sample))
2357
+ scripting_ops->process_switch(event, sample, machine);
20952358
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;
2359
+ if (!script->show_switch_events)
2360
+ return 0;
2361
+
2362
+ return print_event(tool, event, sample, machine, sample->pid,
2363
+ sample->tid);
21012364 }
21022365
21032366 static int
....@@ -2106,21 +2369,8 @@
21062369 struct perf_sample *sample,
21072370 struct machine *machine)
21082371 {
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;
2372
+ return print_event(tool, event, sample, machine, sample->pid,
2373
+ sample->tid);
21242374 }
21252375
21262376 static int
....@@ -2129,8 +2379,33 @@
21292379 struct ordered_events *oe __maybe_unused)
21302380
21312381 {
2132
- perf_event__fprintf(event, stdout);
2382
+ perf_event__fprintf(event, NULL, stdout);
21332383 return 0;
2384
+}
2385
+
2386
+static int
2387
+process_bpf_events(struct perf_tool *tool __maybe_unused,
2388
+ union perf_event *event,
2389
+ struct perf_sample *sample,
2390
+ struct machine *machine)
2391
+{
2392
+ if (machine__process_ksymbol(machine, event, sample) < 0)
2393
+ return -1;
2394
+
2395
+ return print_event(tool, event, sample, machine, sample->pid,
2396
+ sample->tid);
2397
+}
2398
+
2399
+static int process_text_poke_events(struct perf_tool *tool,
2400
+ union perf_event *event,
2401
+ struct perf_sample *sample,
2402
+ struct machine *machine)
2403
+{
2404
+ if (perf_event__process_text_poke(tool, event, sample, machine) < 0)
2405
+ return -1;
2406
+
2407
+ return print_event(tool, event, sample, machine, sample->pid,
2408
+ sample->tid);
21342409 }
21352410
21362411 static void sig_handler(int sig __maybe_unused)
....@@ -2140,20 +2415,20 @@
21402415
21412416 static void perf_script__fclose_per_event_dump(struct perf_script *script)
21422417 {
2143
- struct perf_evlist *evlist = script->session->evlist;
2144
- struct perf_evsel *evsel;
2418
+ struct evlist *evlist = script->session->evlist;
2419
+ struct evsel *evsel;
21452420
21462421 evlist__for_each_entry(evlist, evsel) {
21472422 if (!evsel->priv)
21482423 break;
2149
- perf_evsel_script__delete(evsel->priv);
2424
+ evsel_script__delete(evsel->priv);
21502425 evsel->priv = NULL;
21512426 }
21522427 }
21532428
21542429 static int perf_script__fopen_per_event_dump(struct perf_script *script)
21552430 {
2156
- struct perf_evsel *evsel;
2431
+ struct evsel *evsel;
21572432
21582433 evlist__for_each_entry(script->session->evlist, evsel) {
21592434 /*
....@@ -2166,7 +2441,7 @@
21662441 if (evsel->priv != NULL)
21672442 continue;
21682443
2169
- evsel->priv = perf_evsel_script__new(evsel, script->session->data);
2444
+ evsel->priv = evsel_script__new(evsel, script->session->data);
21702445 if (evsel->priv == NULL)
21712446 goto out_err_fclose;
21722447 }
....@@ -2180,8 +2455,7 @@
21802455
21812456 static int perf_script__setup_per_event_dump(struct perf_script *script)
21822457 {
2183
- struct perf_evsel *evsel;
2184
- static struct perf_evsel_script es_stdout;
2458
+ struct evsel *evsel;
21852459
21862460 if (script->per_event_dump)
21872461 return perf_script__fopen_per_event_dump(script);
....@@ -2196,15 +2470,21 @@
21962470
21972471 static void perf_script__exit_per_event_dump_stats(struct perf_script *script)
21982472 {
2199
- struct perf_evsel *evsel;
2473
+ struct evsel *evsel;
22002474
22012475 evlist__for_each_entry(script->session->evlist, evsel) {
2202
- struct perf_evsel_script *es = evsel->priv;
2476
+ struct evsel_script *es = evsel->priv;
22032477
2204
- perf_evsel_script__fprintf(es, stdout);
2205
- perf_evsel_script__delete(es);
2478
+ evsel_script__fprintf(es, stdout);
2479
+ evsel_script__delete(es);
22062480 evsel->priv = NULL;
22072481 }
2482
+}
2483
+
2484
+static void perf_script__exit(struct perf_script *script)
2485
+{
2486
+ perf_thread_map__put(script->threads);
2487
+ perf_cpu_map__put(script->cpus);
22082488 }
22092489
22102490 static int __cmd_script(struct perf_script *script)
....@@ -2225,15 +2505,25 @@
22252505 script->tool.mmap = process_mmap_event;
22262506 script->tool.mmap2 = process_mmap2_event;
22272507 }
2228
- if (script->show_switch_events)
2508
+ if (script->show_switch_events || (scripting_ops && scripting_ops->process_switch))
22292509 script->tool.context_switch = process_switch_event;
22302510 if (script->show_namespace_events)
22312511 script->tool.namespaces = process_namespaces_event;
2512
+ if (script->show_cgroup_events)
2513
+ script->tool.cgroup = process_cgroup_event;
22322514 if (script->show_lost_events)
22332515 script->tool.lost = process_lost_event;
22342516 if (script->show_round_events) {
22352517 script->tool.ordered_events = false;
22362518 script->tool.finished_round = process_finished_round_event;
2519
+ }
2520
+ if (script->show_bpf_events) {
2521
+ script->tool.ksymbol = process_bpf_events;
2522
+ script->tool.bpf = process_bpf_events;
2523
+ }
2524
+ if (script->show_text_poke_events) {
2525
+ script->tool.ksymbol = process_bpf_events;
2526
+ script->tool.text_poke = process_text_poke_events;
22372527 }
22382528
22392529 if (perf_script__setup_per_event_dump(script)) {
....@@ -2255,7 +2545,7 @@
22552545 struct script_spec {
22562546 struct list_head node;
22572547 struct scripting_ops *ops;
2258
- char spec[0];
2548
+ char spec[];
22592549 };
22602550
22612551 static LIST_HEAD(script_specs);
....@@ -2418,6 +2708,10 @@
24182708 pr_warning("Overriding previous field request for %s events.\n",
24192709 event_type(type));
24202710
2711
+ /* Don't override defaults for +- */
2712
+ if (strchr(tok, '+') || strchr(tok, '-'))
2713
+ goto parse;
2714
+
24212715 output[type].fields = 0;
24222716 output[type].user_set = true;
24232717 output[type].wildcard_set = false;
....@@ -2486,10 +2780,17 @@
24862780 pr_warning("\'%s\' not valid for %s events. Ignoring.\n",
24872781 all_output_options[i].str, event_type(j));
24882782 } else {
2489
- if (change == REMOVE)
2783
+ if (change == REMOVE) {
24902784 output[j].fields &= ~all_output_options[i].field;
2491
- else
2785
+ output[j].user_set_fields &= ~all_output_options[i].field;
2786
+ output[j].user_unset_fields |= all_output_options[i].field;
2787
+ } else {
24922788 output[j].fields |= all_output_options[i].field;
2789
+ output[j].user_set_fields |= all_output_options[i].field;
2790
+ output[j].user_unset_fields &= ~all_output_options[i].field;
2791
+ }
2792
+ output[j].user_set = true;
2793
+ output[j].wildcard_set = true;
24932794 }
24942795 }
24952796 } else {
....@@ -2500,7 +2801,12 @@
25002801 rc = -EINVAL;
25012802 goto out;
25022803 }
2503
- output[type].fields |= all_output_options[i].field;
2804
+ if (change == REMOVE)
2805
+ output[type].fields &= ~all_output_options[i].field;
2806
+ else
2807
+ output[type].fields |= all_output_options[i].field;
2808
+ output[type].user_set = true;
2809
+ output[type].wildcard_set = true;
25042810 }
25052811 }
25062812
....@@ -2620,7 +2926,7 @@
26202926 return -1;
26212927
26222928 while (fgets(line, sizeof(line), fp)) {
2623
- p = ltrim(line);
2929
+ p = skip_spaces(line);
26242930 if (strlen(p) == 0)
26252931 continue;
26262932 if (*p != '#')
....@@ -2629,19 +2935,19 @@
26292935 if (strlen(p) && *p == '!')
26302936 continue;
26312937
2632
- p = ltrim(p);
2938
+ p = skip_spaces(p);
26332939 if (strlen(p) && p[strlen(p) - 1] == '\n')
26342940 p[strlen(p) - 1] = '\0';
26352941
26362942 if (!strncmp(p, "description:", strlen("description:"))) {
26372943 p += strlen("description:");
2638
- desc->half_liner = strdup(ltrim(p));
2944
+ desc->half_liner = strdup(skip_spaces(p));
26392945 continue;
26402946 }
26412947
26422948 if (!strncmp(p, "args:", strlen("args:"))) {
26432949 p += strlen("args:");
2644
- desc->args = strdup(ltrim(p));
2950
+ desc->args = strdup(skip_spaces(p));
26452951 continue;
26462952 }
26472953 }
....@@ -2737,7 +3043,7 @@
27373043 {
27383044 char filename[MAXPATHLEN], evname[128];
27393045 char line[BUFSIZ], *p;
2740
- struct perf_evsel *pos;
3046
+ struct evsel *pos;
27413047 int match, len;
27423048 FILE *fp;
27433049
....@@ -2748,7 +3054,7 @@
27483054 return -1;
27493055
27503056 while (fgets(line, sizeof(line), fp)) {
2751
- p = ltrim(line);
3057
+ p = skip_spaces(line);
27523058 if (*p == '#')
27533059 continue;
27543060
....@@ -2758,7 +3064,7 @@
27583064 break;
27593065
27603066 p += 2;
2761
- p = ltrim(p);
3067
+ p = skip_spaces(p);
27623068 len = strcspn(p, " \t");
27633069 if (!len)
27643070 break;
....@@ -2767,7 +3073,7 @@
27673073
27683074 match = 0;
27693075 evlist__for_each_entry(session->evlist, pos) {
2770
- if (!strcmp(perf_evsel__name(pos), evname)) {
3076
+ if (!strcmp(evsel__name(pos), evname)) {
27713077 match = 1;
27723078 break;
27733079 }
....@@ -2791,24 +3097,23 @@
27913097 * will list all statically runnable scripts, select one, execute it and
27923098 * show the output in a perf browser.
27933099 */
2794
-int find_scripts(char **scripts_array, char **scripts_path_array)
3100
+int find_scripts(char **scripts_array, char **scripts_path_array, int num,
3101
+ int pathlen)
27953102 {
27963103 struct dirent *script_dirent, *lang_dirent;
27973104 char scripts_path[MAXPATHLEN], lang_path[MAXPATHLEN];
27983105 DIR *scripts_dir, *lang_dir;
27993106 struct perf_session *session;
28003107 struct perf_data data = {
2801
- .file = {
2802
- .path = input_name,
2803
- },
2804
- .mode = PERF_DATA_MODE_READ,
3108
+ .path = input_name,
3109
+ .mode = PERF_DATA_MODE_READ,
28053110 };
28063111 char *temp;
28073112 int i = 0;
28083113
28093114 session = perf_session__new(&data, false, NULL);
2810
- if (!session)
2811
- return -1;
3115
+ if (IS_ERR(session))
3116
+ return PTR_ERR(session);
28123117
28133118 snprintf(scripts_path, MAXPATHLEN, "%s/scripts", get_argv_exec_path());
28143119
....@@ -2838,7 +3143,10 @@
28383143 /* Skip those real time scripts: xxxtop.p[yl] */
28393144 if (strstr(script_dirent->d_name, "top."))
28403145 continue;
2841
- sprintf(scripts_path_array[i], "%s/%s", lang_path,
3146
+ if (i >= num)
3147
+ break;
3148
+ snprintf(scripts_path_array[i], pathlen, "%s/%s",
3149
+ lang_path,
28423150 script_dirent->d_name);
28433151 temp = strchr(script_dirent->d_name, '.');
28443152 snprintf(scripts_array[i],
....@@ -2885,10 +3193,10 @@
28853193 __script_root = get_script_root(script_dirent, suffix);
28863194 if (__script_root && !strcmp(script_root, __script_root)) {
28873195 free(__script_root);
2888
- closedir(lang_dir);
28893196 closedir(scripts_dir);
28903197 scnprintf(script_path, MAXPATHLEN, "%s/%s",
28913198 lang_path, script_dirent->d_name);
3199
+ closedir(lang_dir);
28923200 return strdup(script_path);
28933201 }
28943202 free(__script_root);
....@@ -2950,7 +3258,7 @@
29503258 static void script__setup_sample_type(struct perf_script *script)
29513259 {
29523260 struct perf_session *session = script->session;
2953
- u64 sample_type = perf_evlist__combined_sample_type(session->evlist);
3261
+ u64 sample_type = evlist__combined_sample_type(session->evlist);
29543262
29553263 if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain) {
29563264 if ((sample_type & PERF_SAMPLE_REGS_USER) &&
....@@ -2962,14 +3270,19 @@
29623270 else
29633271 callchain_param.record_mode = CALLCHAIN_FP;
29643272 }
3273
+
3274
+ if (script->stitch_lbr && (callchain_param.record_mode != CALLCHAIN_LBR)) {
3275
+ pr_warning("Can't find LBR callchain. Switch off --stitch-lbr.\n"
3276
+ "Please apply --call-graph lbr when recording.\n");
3277
+ script->stitch_lbr = false;
3278
+ }
29653279 }
29663280
2967
-static int process_stat_round_event(struct perf_tool *tool __maybe_unused,
2968
- union perf_event *event,
2969
- struct perf_session *session)
3281
+static int process_stat_round_event(struct perf_session *session,
3282
+ union perf_event *event)
29703283 {
2971
- struct stat_round_event *round = &event->stat_round;
2972
- struct perf_evsel *counter;
3284
+ struct perf_record_stat_round *round = &event->stat_round;
3285
+ struct evsel *counter;
29733286
29743287 evlist__for_each_entry(session->evlist, counter) {
29753288 perf_stat_process_counter(&stat_config, counter);
....@@ -2980,9 +3293,8 @@
29803293 return 0;
29813294 }
29823295
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)
3296
+static int process_stat_config_event(struct perf_session *session __maybe_unused,
3297
+ union perf_event *event)
29863298 {
29873299 perf_event__read_stat_config(&stat_config, &event->stat_config);
29883300 return 0;
....@@ -2990,7 +3302,7 @@
29903302
29913303 static int set_maps(struct perf_script *script)
29923304 {
2993
- struct perf_evlist *evlist = script->session->evlist;
3305
+ struct evlist *evlist = script->session->evlist;
29943306
29953307 if (!script->cpus || !script->threads)
29963308 return 0;
....@@ -2998,7 +3310,7 @@
29983310 if (WARN_ONCE(script->allocated, "stats double allocation\n"))
29993311 return -EINVAL;
30003312
3001
- perf_evlist__set_maps(evlist, script->cpus, script->threads);
3313
+ perf_evlist__set_maps(&evlist->core, script->cpus, script->threads);
30023314
30033315 if (perf_evlist__alloc_stats(evlist, true))
30043316 return -ENOMEM;
....@@ -3008,10 +3320,10 @@
30083320 }
30093321
30103322 static
3011
-int process_thread_map_event(struct perf_tool *tool,
3012
- union perf_event *event,
3013
- struct perf_session *session __maybe_unused)
3323
+int process_thread_map_event(struct perf_session *session,
3324
+ union perf_event *event)
30143325 {
3326
+ struct perf_tool *tool = session->tool;
30153327 struct perf_script *script = container_of(tool, struct perf_script, tool);
30163328
30173329 if (script->threads) {
....@@ -3027,10 +3339,10 @@
30273339 }
30283340
30293341 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)
3342
+int process_cpu_map_event(struct perf_session *session,
3343
+ union perf_event *event)
30333344 {
3345
+ struct perf_tool *tool = session->tool;
30343346 struct perf_script *script = container_of(tool, struct perf_script, tool);
30353347
30363348 if (script->cpus) {
....@@ -3045,21 +3357,21 @@
30453357 return set_maps(script);
30463358 }
30473359
3048
-static int process_feature_event(struct perf_tool *tool,
3049
- union perf_event *event,
3050
- struct perf_session *session)
3360
+static int process_feature_event(struct perf_session *session,
3361
+ union perf_event *event)
30513362 {
30523363 if (event->feat.feat_id < HEADER_LAST_FEATURE)
3053
- return perf_event__process_feature(tool, event, session);
3364
+ return perf_event__process_feature(session, event);
30543365 return 0;
30553366 }
30563367
30573368 #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)
3369
+static int perf_script__process_auxtrace_info(struct perf_session *session,
3370
+ union perf_event *event)
30613371 {
3062
- int ret = perf_event__process_auxtrace_info(tool, event, session);
3372
+ struct perf_tool *tool = session->tool;
3373
+
3374
+ int ret = perf_event__process_auxtrace_info(session, event);
30633375
30643376 if (ret == 0) {
30653377 struct perf_script *script = container_of(tool, struct perf_script, tool);
....@@ -3073,6 +3385,48 @@
30733385 #define perf_script__process_auxtrace_info 0
30743386 #endif
30753387
3388
+static int parse_insn_trace(const struct option *opt __maybe_unused,
3389
+ const char *str __maybe_unused,
3390
+ int unset __maybe_unused)
3391
+{
3392
+ parse_output_fields(NULL, "+insn,-event,-period", 0);
3393
+ itrace_parse_synth_opts(opt, "i0ns", 0);
3394
+ symbol_conf.nanosecs = true;
3395
+ return 0;
3396
+}
3397
+
3398
+static int parse_xed(const struct option *opt __maybe_unused,
3399
+ const char *str __maybe_unused,
3400
+ int unset __maybe_unused)
3401
+{
3402
+ if (isatty(1))
3403
+ force_pager("xed -F insn: -A -64 | less");
3404
+ else
3405
+ force_pager("xed -F insn: -A -64");
3406
+ return 0;
3407
+}
3408
+
3409
+static int parse_call_trace(const struct option *opt __maybe_unused,
3410
+ const char *str __maybe_unused,
3411
+ int unset __maybe_unused)
3412
+{
3413
+ parse_output_fields(NULL, "-ip,-addr,-event,-period,+callindent", 0);
3414
+ itrace_parse_synth_opts(opt, "cewp", 0);
3415
+ symbol_conf.nanosecs = true;
3416
+ symbol_conf.pad_output_len_dso = 50;
3417
+ return 0;
3418
+}
3419
+
3420
+static int parse_callret_trace(const struct option *opt __maybe_unused,
3421
+ const char *str __maybe_unused,
3422
+ int unset __maybe_unused)
3423
+{
3424
+ parse_output_fields(NULL, "-ip,-addr,-event,-period,+callindent,+flags", 0);
3425
+ itrace_parse_synth_opts(opt, "crewp", 0);
3426
+ symbol_conf.nanosecs = true;
3427
+ return 0;
3428
+}
3429
+
30763430 int cmd_script(int argc, const char **argv)
30773431 {
30783432 bool show_full_info = false;
....@@ -3082,7 +3436,11 @@
30823436 char *rec_script_path = NULL;
30833437 char *rep_script_path = NULL;
30843438 struct perf_session *session;
3085
- struct itrace_synth_opts itrace_synth_opts = { .set = false, };
3439
+ struct itrace_synth_opts itrace_synth_opts = {
3440
+ .set = false,
3441
+ .default_no_sample = true,
3442
+ };
3443
+ struct utsname uts;
30863444 char *script_path = NULL;
30873445 const char **__argv;
30883446 int i, j, err = 0;
....@@ -3093,6 +3451,7 @@
30933451 .mmap2 = perf_event__process_mmap2,
30943452 .comm = perf_event__process_comm,
30953453 .namespaces = perf_event__process_namespaces,
3454
+ .cgroup = perf_event__process_cgroup,
30963455 .exit = perf_event__process_exit,
30973456 .fork = perf_event__process_fork,
30983457 .attr = process_attr,
....@@ -3151,12 +3510,22 @@
31513510 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,"
31523511 "addr,symoff,srcline,period,iregs,uregs,brstack,"
31533512 "brstacksym,flags,bpf-output,brstackinsn,brstackoff,"
3154
- "callindent,insn,insnlen,synth,phys_addr,metric,misc",
3513
+ "callindent,insn,insnlen,synth,phys_addr,metric,misc,ipc,tod",
31553514 parse_output_fields),
31563515 OPT_BOOLEAN('a', "all-cpus", &system_wide,
31573516 "system-wide collection from all CPUs"),
31583517 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
31593518 "only consider these symbols"),
3519
+ OPT_CALLBACK_OPTARG(0, "insn-trace", &itrace_synth_opts, NULL, NULL,
3520
+ "Decode instructions from itrace", parse_insn_trace),
3521
+ OPT_CALLBACK_OPTARG(0, "xed", NULL, NULL, NULL,
3522
+ "Run xed disassembler on output", parse_xed),
3523
+ OPT_CALLBACK_OPTARG(0, "call-trace", &itrace_synth_opts, NULL, NULL,
3524
+ "Decode calls from from itrace", parse_call_trace),
3525
+ OPT_CALLBACK_OPTARG(0, "call-ret-trace", &itrace_synth_opts, NULL, NULL,
3526
+ "Decode calls and returns from itrace", parse_callret_trace),
3527
+ OPT_STRING(0, "graph-function", &symbol_conf.graph_function, "symbol[,symbol...]",
3528
+ "Only print symbols and callees with --call-trace/--call-ret-trace"),
31603529 OPT_STRING(0, "stop-bt", &symbol_conf.bt_stop_list_str, "symbol[,symbol...]",
31613530 "Stop display of callgraph at these symbols"),
31623531 OPT_STRING('C', "cpu", &cpu_list, "cpu", "list of cpus to profile"),
....@@ -3170,6 +3539,8 @@
31703539 "Set the maximum stack depth when parsing the callchain, "
31713540 "anything beyond the specified depth will be ignored. "
31723541 "Default: kernel.perf_event_max_stack or " __stringify(PERF_MAX_STACK_DEPTH)),
3542
+ OPT_BOOLEAN(0, "reltime", &reltime, "Show time stamps relative to start"),
3543
+ OPT_BOOLEAN(0, "deltatime", &deltatime, "Show time stamps relative to previous event"),
31733544 OPT_BOOLEAN('I', "show-info", &show_full_info,
31743545 "display extended information from perf.data file"),
31753546 OPT_BOOLEAN('\0', "show-kernel-path", &symbol_conf.show_kernel_path,
....@@ -3182,19 +3553,25 @@
31823553 "Show context switch events (if recorded)"),
31833554 OPT_BOOLEAN('\0', "show-namespace-events", &script.show_namespace_events,
31843555 "Show namespace events (if recorded)"),
3556
+ OPT_BOOLEAN('\0', "show-cgroup-events", &script.show_cgroup_events,
3557
+ "Show cgroup events (if recorded)"),
31853558 OPT_BOOLEAN('\0', "show-lost-events", &script.show_lost_events,
31863559 "Show lost events (if recorded)"),
31873560 OPT_BOOLEAN('\0', "show-round-events", &script.show_round_events,
31883561 "Show round events (if recorded)"),
3562
+ OPT_BOOLEAN('\0', "show-bpf-events", &script.show_bpf_events,
3563
+ "Show bpf related events (if recorded)"),
3564
+ OPT_BOOLEAN('\0', "show-text-poke-events", &script.show_text_poke_events,
3565
+ "Show text poke related events (if recorded)"),
31893566 OPT_BOOLEAN('\0', "per-event-dump", &script.per_event_dump,
31903567 "Dump trace output to files named by the monitored events"),
31913568 OPT_BOOLEAN('f', "force", &symbol_conf.force, "don't complain, do it"),
31923569 OPT_INTEGER(0, "max-blocks", &max_blocks,
31933570 "Maximum number of code blocks to dump with brstackinsn"),
3194
- OPT_BOOLEAN(0, "ns", &nanosecs,
3571
+ OPT_BOOLEAN(0, "ns", &symbol_conf.nanosecs,
31953572 "Use 9 decimal places when displaying time"),
31963573 OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts",
3197
- "Instruction Tracing options",
3574
+ "Instruction Tracing options\n" ITRACE_HELP,
31983575 itrace_parse_synth_opts),
31993576 OPT_BOOLEAN(0, "full-source-path", &srcline_full_filename,
32003577 "Show full source file name path for source lines"),
....@@ -3206,6 +3583,18 @@
32063583 "Time span of interest (start,stop)"),
32073584 OPT_BOOLEAN(0, "inline", &symbol_conf.inline_name,
32083585 "Show inline function"),
3586
+ OPT_STRING(0, "guestmount", &symbol_conf.guestmount, "directory",
3587
+ "guest mount directory under which every guest os"
3588
+ " instance has a subdir"),
3589
+ OPT_STRING(0, "guestvmlinux", &symbol_conf.default_guest_vmlinux_name,
3590
+ "file", "file saving guest os vmlinux"),
3591
+ OPT_STRING(0, "guestkallsyms", &symbol_conf.default_guest_kallsyms,
3592
+ "file", "file saving guest os /proc/kallsyms"),
3593
+ OPT_STRING(0, "guestmodules", &symbol_conf.default_guest_modules,
3594
+ "file", "file saving guest os /proc/modules"),
3595
+ OPT_BOOLEAN('\0', "stitch-lbr", &script.stitch_lbr,
3596
+ "Enable LBR callgraph stitching approach"),
3597
+ OPTS_EVSWITCH(&script.evswitch),
32093598 OPT_END()
32103599 };
32113600 const char * const script_subcommands[] = { "record", "report", NULL };
....@@ -3225,8 +3614,18 @@
32253614 argc = parse_options_subcommand(argc, argv, options, script_subcommands, script_usage,
32263615 PARSE_OPT_STOP_AT_NON_OPTION);
32273616
3228
- data.file.path = input_name;
3229
- data.force = symbol_conf.force;
3617
+ if (symbol_conf.guestmount ||
3618
+ symbol_conf.default_guest_vmlinux_name ||
3619
+ symbol_conf.default_guest_kallsyms ||
3620
+ symbol_conf.default_guest_modules) {
3621
+ /*
3622
+ * Enable guest sample processing.
3623
+ */
3624
+ perf_guest = true;
3625
+ }
3626
+
3627
+ data.path = input_name;
3628
+ data.force = symbol_conf.force;
32303629
32313630 if (argc > 1 && !strncmp(argv[0], "rec", strlen("rec"))) {
32323631 rec_script_path = get_script_path(argv[1], RECORD_SUFFIX);
....@@ -3244,7 +3643,14 @@
32443643 }
32453644 }
32463645
3247
- if (itrace_synth_opts.callchain &&
3646
+ if (reltime && deltatime) {
3647
+ fprintf(stderr,
3648
+ "reltime and deltatime - the two don't get along well. "
3649
+ "Please limit to --reltime or --deltatime.\n");
3650
+ return -1;
3651
+ }
3652
+
3653
+ if ((itrace_synth_opts.callchain || itrace_synth_opts.add_callchain) &&
32483654 itrace_synth_opts.callchain_sz > scripting_max_stack)
32493655 scripting_max_stack = itrace_synth_opts.callchain_sz;
32503656
....@@ -3390,12 +3796,14 @@
33903796 exit(-1);
33913797 }
33923798
3393
- if (!script_name)
3799
+ if (!script_name) {
33943800 setup_pager();
3801
+ use_browser = 0;
3802
+ }
33953803
33963804 session = perf_session__new(&data, false, &script.tool);
3397
- if (session == NULL)
3398
- return -1;
3805
+ if (IS_ERR(session))
3806
+ return PTR_ERR(session);
33993807
34003808 if (header || header_only) {
34013809 script.tool.show_feat_hdr = SHOW_FEAT_HEADER;
....@@ -3409,10 +3817,22 @@
34093817 if (symbol__init(&session->header.env) < 0)
34103818 goto out_delete;
34113819
3820
+ uname(&uts);
3821
+ if (data.is_pipe) { /* Assume pipe_mode indicates native_arch */
3822
+ native_arch = true;
3823
+ } else if (session->header.env.arch) {
3824
+ if (!strcmp(uts.machine, session->header.env.arch))
3825
+ native_arch = true;
3826
+ else if (!strcmp(uts.machine, "x86_64") &&
3827
+ !strcmp(session->header.env.arch, "i386"))
3828
+ native_arch = true;
3829
+ }
3830
+
34123831 script.session = session;
34133832 script__setup_sample_type(&script);
34143833
3415
- if (output[PERF_TYPE_HARDWARE].fields & PERF_OUTPUT_CALLINDENT)
3834
+ if ((output[PERF_TYPE_HARDWARE].fields & PERF_OUTPUT_CALLINDENT) ||
3835
+ symbol_conf.graph_function)
34163836 itrace_synth_opts.thread_stack = true;
34173837
34183838 session->itrace_synth_opts = &itrace_synth_opts;
....@@ -3449,7 +3869,7 @@
34493869 goto out_delete;
34503870 }
34513871
3452
- input = open(data.file.path, O_RDONLY); /* input_name */
3872
+ input = open(data.path, O_RDONLY); /* input_name */
34533873 if (input < 0) {
34543874 err = -errno;
34553875 perror("failed to open file");
....@@ -3492,48 +3912,40 @@
34923912 if (err < 0)
34933913 goto out_delete;
34943914
3495
- script.ptime_range = perf_time__range_alloc(script.time_str,
3496
- &script.range_size);
3497
- if (!script.ptime_range) {
3498
- err = -ENOMEM;
3915
+ if (script.time_str) {
3916
+ err = perf_time__parse_for_ranges_reltime(script.time_str, session,
3917
+ &script.ptime_range,
3918
+ &script.range_size,
3919
+ &script.range_num,
3920
+ reltime);
3921
+ if (err < 0)
3922
+ goto out_delete;
3923
+
3924
+ itrace_synth_opts__set_time_range(&itrace_synth_opts,
3925
+ script.ptime_range,
3926
+ script.range_num);
3927
+ }
3928
+
3929
+ err = evswitch__init(&script.evswitch, session->evlist, stderr);
3930
+ if (err)
34993931 goto out_delete;
3500
- }
35013932
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
- }
3933
+ if (zstd_init(&(session->zstd_data), 0) < 0)
3934
+ pr_warning("Decompression initialization failed. Reported data may be incomplete.\n");
35273935
35283936 err = __cmd_script(&script);
35293937
35303938 flush_scripting();
35313939
35323940 out_delete:
3533
- zfree(&script.ptime_range);
3941
+ if (script.ptime_range) {
3942
+ itrace_synth_opts__clear_time_range(&itrace_synth_opts);
3943
+ zfree(&script.ptime_range);
3944
+ }
35343945
35353946 perf_evlist__free_stats(session->evlist);
35363947 perf_session__delete(session);
3948
+ perf_script__exit(&script);
35373949
35383950 if (script_started)
35393951 cleanup_scripting();