blob: 04913136bac95f5d4635947d9cf915e82449ef53 [file] [log] [blame]
Greg Kroah-Hartmanb2441312017-11-01 15:07:57 +01001// SPDX-License-Identifier: GPL-2.0
Frederic Weisbecker5f9c39d2009-08-17 16:18:08 +02002#include "builtin.h"
3
Andrea Gelminib7eead82010-08-05 15:51:38 +02004#include "perf.h"
Frederic Weisbecker5f9c39d2009-08-17 16:18:08 +02005#include "util/cache.h"
Andrea Gelminib7eead82010-08-05 15:51:38 +02006#include "util/debug.h"
Josh Poimboeuf4b6ab942015-12-15 09:39:39 -06007#include <subcmd/exec-cmd.h>
Andrea Gelminib7eead82010-08-05 15:51:38 +02008#include "util/header.h"
Josh Poimboeuf4b6ab942015-12-15 09:39:39 -06009#include <subcmd/parse-options.h>
Stephane Eranianfc36f942015-08-31 18:41:10 +020010#include "util/perf_regs.h"
Andrea Gelminib7eead82010-08-05 15:51:38 +020011#include "util/session.h"
Arnaldo Carvalho de Melo45694aa2011-11-28 08:30:20 -020012#include "util/tool.h"
Frederic Weisbecker5f9c39d2009-08-17 16:18:08 +020013#include "util/symbol.h"
14#include "util/thread.h"
Ingo Molnarcf723442009-11-28 10:11:00 +010015#include "util/trace-event.h"
Andrea Gelminib7eead82010-08-05 15:51:38 +020016#include "util/util.h"
David Ahern1424dc92011-03-09 22:23:28 -070017#include "util/evlist.h"
18#include "util/evsel.h"
Feng Tang36385be2012-09-07 16:42:24 +080019#include "util/sort.h"
Jiri Olsaf5fc14122013-10-15 16:27:32 +020020#include "util/data.h"
Adrian Hunter7a680eb2015-04-09 18:53:56 +030021#include "util/auxtrace.h"
Jiri Olsacfc88742016-01-05 22:09:06 +010022#include "util/cpumap.h"
23#include "util/thread_map.h"
24#include "util/stat.h"
Andi Kleen4bd1bef2017-11-17 13:43:00 -080025#include "util/color.h"
Arnaldo Carvalho de Meloa0675582017-04-17 16:51:59 -030026#include "util/string2.h"
Adrian Huntere2167082016-06-23 16:40:58 +030027#include "util/thread-stack.h"
David Aherna91f4c42016-11-29 10:15:43 -070028#include "util/time-utils.h"
Jiri Olsa06c3f2a2017-12-06 18:45:35 +010029#include "util/path.h"
Arnaldo Carvalho de Melofea01392017-04-17 16:23:22 -030030#include "print_binary.h"
Anton Blanchard5d67be92011-07-04 21:57:50 +100031#include <linux/bitmap.h>
Arnaldo Carvalho de Melo877a7a12017-04-17 11:39:06 -030032#include <linux/kernel.h>
Arnaldo Carvalho de Melo6125cc82016-04-14 18:15:18 -030033#include <linux/stringify.h>
Arnaldo Carvalho de Melobd48c632016-08-05 15:40:30 -030034#include <linux/time64.h>
Jiri Olsacfc88742016-01-05 22:09:06 +010035#include "asm/bug.h"
Jiri Olsac19ac912016-02-24 09:46:54 +010036#include "util/mem-events.h"
Andi Kleen48d02a12017-02-23 15:46:34 -080037#include "util/dump-insn.h"
Arnaldo Carvalho de Melo76b31a22017-04-18 12:26:44 -030038#include <dirent.h>
Arnaldo Carvalho de Meloa43783a2017-04-18 10:46:11 -030039#include <errno.h>
Arnaldo Carvalho de Melofd20e812017-04-17 15:23:08 -030040#include <inttypes.h>
Arnaldo Carvalho de Melo9607ad32017-04-19 15:49:18 -030041#include <signal.h>
Arnaldo Carvalho de Melo391e4202017-04-19 18:51:14 -030042#include <sys/param.h>
Arnaldo Carvalho de Melo7a8ef4c2017-04-19 20:57:47 -030043#include <sys/types.h>
44#include <sys/stat.h>
Arnaldo Carvalho de Melobafae982018-01-22 16:42:16 -030045#include <fcntl.h>
Arnaldo Carvalho de Melo7a8ef4c2017-04-19 20:57:47 -030046#include <unistd.h>
Andi Kleenb585ebd2018-09-20 11:05:36 -070047#include <subcmd/pager.h>
Frederic Weisbecker5f9c39d2009-08-17 16:18:08 +020048
Arnaldo Carvalho de Melo3d689ed2017-04-17 16:10:49 -030049#include "sane_ctype.h"
50
Tom Zanussi956ffd02009-11-25 01:15:46 -060051static char const *script_name;
52static char const *generate_script_lang;
Frederic Weisbeckerffabd992010-05-27 16:27:47 +020053static bool debug_mode;
Frederic Weisbeckere1889d72010-04-24 01:55:09 +020054static u64 last_timestamp;
Frederic Weisbecker6fcf7dd2010-05-27 15:46:25 +020055static u64 nr_unordered;
David Ahernc0230b22011-03-09 22:23:27 -070056static bool no_callchain;
Namhyung Kim47390ae2013-06-04 14:20:28 +090057static bool latency_format;
Robert Richter317df652011-11-25 15:05:25 +010058static bool system_wide;
Adrian Hunter400ea6d2015-04-09 18:54:05 +030059static bool print_flags;
Adrian Hunter83e19862015-09-25 16:15:36 +030060static bool nanosecs;
Anton Blanchard5d67be92011-07-04 21:57:50 +100061static const char *cpu_list;
62static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
Jiri Olsa91a2c3d2016-01-05 22:09:07 +010063static struct perf_stat_config stat_config;
Andi Kleen48d02a12017-02-23 15:46:34 -080064static int max_blocks;
Tom Zanussi956ffd02009-11-25 01:15:46 -060065
Adrian Hunter44cbe722015-09-25 16:15:50 +030066unsigned int scripting_max_stack = PERF_MAX_STACK_DEPTH;
Adrian Hunter03cd1fe2015-09-25 16:15:49 +030067
David Ahern745f43e2011-03-09 22:23:26 -070068enum perf_output_field {
69 PERF_OUTPUT_COMM = 1U << 0,
70 PERF_OUTPUT_TID = 1U << 1,
71 PERF_OUTPUT_PID = 1U << 2,
72 PERF_OUTPUT_TIME = 1U << 3,
73 PERF_OUTPUT_CPU = 1U << 4,
74 PERF_OUTPUT_EVNAME = 1U << 5,
75 PERF_OUTPUT_TRACE = 1U << 6,
David Ahern787bef12011-05-27 14:28:43 -060076 PERF_OUTPUT_IP = 1U << 7,
77 PERF_OUTPUT_SYM = 1U << 8,
David Ahern610723f2011-05-27 14:28:44 -060078 PERF_OUTPUT_DSO = 1U << 9,
David Ahern7cec0922011-05-30 13:08:23 -060079 PERF_OUTPUT_ADDR = 1U << 10,
Akihiro Nagaia978f2a2012-01-30 13:43:15 +090080 PERF_OUTPUT_SYMOFFSET = 1U << 11,
Adrian Huntercc8fae12013-12-06 09:42:57 +020081 PERF_OUTPUT_SRCLINE = 1U << 12,
Jiri Olsa535aeaae2014-08-25 16:45:42 +020082 PERF_OUTPUT_PERIOD = 1U << 13,
Stephane Eranianfc36f942015-08-31 18:41:10 +020083 PERF_OUTPUT_IREGS = 1U << 14,
Stephane Eraniandc323ce2015-08-31 18:41:13 +020084 PERF_OUTPUT_BRSTACK = 1U << 15,
85 PERF_OUTPUT_BRSTACKSYM = 1U << 16,
Jiri Olsa94ddddf2016-02-15 09:34:51 +010086 PERF_OUTPUT_DATA_SRC = 1U << 17,
87 PERF_OUTPUT_WEIGHT = 1U << 18,
Wang Nan30372f02016-02-24 11:20:45 +000088 PERF_OUTPUT_BPF_OUTPUT = 1U << 19,
Adrian Huntere2167082016-06-23 16:40:58 +030089 PERF_OUTPUT_CALLINDENT = 1U << 20,
Andi Kleen224e2c92016-10-07 16:42:27 +030090 PERF_OUTPUT_INSN = 1U << 21,
91 PERF_OUTPUT_INSNLEN = 1U << 22,
Andi Kleen48d02a12017-02-23 15:46:34 -080092 PERF_OUTPUT_BRSTACKINSN = 1U << 23,
Mark Santaniello106dacd2017-06-19 09:38:25 -070093 PERF_OUTPUT_BRSTACKOFF = 1U << 24,
Adrian Hunter47e78082017-05-26 11:17:22 +030094 PERF_OUTPUT_SYNTH = 1U << 25,
Kan Liang49d58f02017-08-29 13:11:11 -040095 PERF_OUTPUT_PHYS_ADDR = 1U << 26,
Andi Kleenb1491ac2017-09-05 11:40:57 -070096 PERF_OUTPUT_UREGS = 1U << 27,
Andi Kleen4bd1bef2017-11-17 13:43:00 -080097 PERF_OUTPUT_METRIC = 1U << 28,
Jiri Olsa28a0b392018-01-07 17:03:52 +010098 PERF_OUTPUT_MISC = 1U << 29,
David Ahern745f43e2011-03-09 22:23:26 -070099};
100
101struct output_option {
102 const char *str;
103 enum perf_output_field field;
104} all_output_options[] = {
105 {.str = "comm", .field = PERF_OUTPUT_COMM},
106 {.str = "tid", .field = PERF_OUTPUT_TID},
107 {.str = "pid", .field = PERF_OUTPUT_PID},
108 {.str = "time", .field = PERF_OUTPUT_TIME},
109 {.str = "cpu", .field = PERF_OUTPUT_CPU},
110 {.str = "event", .field = PERF_OUTPUT_EVNAME},
111 {.str = "trace", .field = PERF_OUTPUT_TRACE},
David Ahern787bef12011-05-27 14:28:43 -0600112 {.str = "ip", .field = PERF_OUTPUT_IP},
David Ahernc0230b22011-03-09 22:23:27 -0700113 {.str = "sym", .field = PERF_OUTPUT_SYM},
David Ahern610723f2011-05-27 14:28:44 -0600114 {.str = "dso", .field = PERF_OUTPUT_DSO},
David Ahern7cec0922011-05-30 13:08:23 -0600115 {.str = "addr", .field = PERF_OUTPUT_ADDR},
Akihiro Nagaia978f2a2012-01-30 13:43:15 +0900116 {.str = "symoff", .field = PERF_OUTPUT_SYMOFFSET},
Adrian Huntercc8fae12013-12-06 09:42:57 +0200117 {.str = "srcline", .field = PERF_OUTPUT_SRCLINE},
Jiri Olsa535aeaae2014-08-25 16:45:42 +0200118 {.str = "period", .field = PERF_OUTPUT_PERIOD},
Stephane Eranianfc36f942015-08-31 18:41:10 +0200119 {.str = "iregs", .field = PERF_OUTPUT_IREGS},
Andi Kleenb1491ac2017-09-05 11:40:57 -0700120 {.str = "uregs", .field = PERF_OUTPUT_UREGS},
Stephane Eraniandc323ce2015-08-31 18:41:13 +0200121 {.str = "brstack", .field = PERF_OUTPUT_BRSTACK},
122 {.str = "brstacksym", .field = PERF_OUTPUT_BRSTACKSYM},
Jiri Olsa94ddddf2016-02-15 09:34:51 +0100123 {.str = "data_src", .field = PERF_OUTPUT_DATA_SRC},
124 {.str = "weight", .field = PERF_OUTPUT_WEIGHT},
Wang Nan30372f02016-02-24 11:20:45 +0000125 {.str = "bpf-output", .field = PERF_OUTPUT_BPF_OUTPUT},
Adrian Huntere2167082016-06-23 16:40:58 +0300126 {.str = "callindent", .field = PERF_OUTPUT_CALLINDENT},
Andi Kleen224e2c92016-10-07 16:42:27 +0300127 {.str = "insn", .field = PERF_OUTPUT_INSN},
128 {.str = "insnlen", .field = PERF_OUTPUT_INSNLEN},
Andi Kleen48d02a12017-02-23 15:46:34 -0800129 {.str = "brstackinsn", .field = PERF_OUTPUT_BRSTACKINSN},
Mark Santaniello106dacd2017-06-19 09:38:25 -0700130 {.str = "brstackoff", .field = PERF_OUTPUT_BRSTACKOFF},
Adrian Hunter47e78082017-05-26 11:17:22 +0300131 {.str = "synth", .field = PERF_OUTPUT_SYNTH},
Kan Liang49d58f02017-08-29 13:11:11 -0400132 {.str = "phys_addr", .field = PERF_OUTPUT_PHYS_ADDR},
Andi Kleen4bd1bef2017-11-17 13:43:00 -0800133 {.str = "metric", .field = PERF_OUTPUT_METRIC},
Jiri Olsa28a0b392018-01-07 17:03:52 +0100134 {.str = "misc", .field = PERF_OUTPUT_MISC},
David Ahern745f43e2011-03-09 22:23:26 -0700135};
136
Adrian Hunter14057202017-06-21 13:17:19 +0300137enum {
138 OUTPUT_TYPE_SYNTH = PERF_TYPE_MAX,
139 OUTPUT_TYPE_MAX
140};
141
David Ahern745f43e2011-03-09 22:23:26 -0700142/* default set to maintain compatibility with current format */
David Ahern2c9e45f72011-03-17 10:03:21 -0600143static struct {
144 bool user_set;
David Ahern9cbdb702011-04-06 21:54:20 -0600145 bool wildcard_set;
David Aherna6ffaf92013-08-07 22:50:51 -0400146 unsigned int print_ip_opts;
David Ahern2c9e45f72011-03-17 10:03:21 -0600147 u64 fields;
148 u64 invalid_fields;
Adrian Hunter14057202017-06-21 13:17:19 +0300149} output[OUTPUT_TYPE_MAX] = {
David Ahern1424dc92011-03-09 22:23:28 -0700150
David Ahern2c9e45f72011-03-17 10:03:21 -0600151 [PERF_TYPE_HARDWARE] = {
152 .user_set = false,
David Ahern1424dc92011-03-09 22:23:28 -0700153
David Ahern2c9e45f72011-03-17 10:03:21 -0600154 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
155 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
David Ahern787bef12011-05-27 14:28:43 -0600156 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
Sandipan Das7903a702018-05-17 12:03:26 +0530157 PERF_OUTPUT_SYM | PERF_OUTPUT_SYMOFFSET |
158 PERF_OUTPUT_DSO | PERF_OUTPUT_PERIOD,
David Ahern2c9e45f72011-03-17 10:03:21 -0600159
Wang Nan30372f02016-02-24 11:20:45 +0000160 .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT,
David Ahern2c9e45f72011-03-17 10:03:21 -0600161 },
162
163 [PERF_TYPE_SOFTWARE] = {
164 .user_set = false,
165
166 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
167 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
David Ahern787bef12011-05-27 14:28:43 -0600168 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
Sandipan Das7903a702018-05-17 12:03:26 +0530169 PERF_OUTPUT_SYM | PERF_OUTPUT_SYMOFFSET |
170 PERF_OUTPUT_DSO | PERF_OUTPUT_PERIOD |
171 PERF_OUTPUT_BPF_OUTPUT,
David Ahern2c9e45f72011-03-17 10:03:21 -0600172
173 .invalid_fields = PERF_OUTPUT_TRACE,
174 },
175
176 [PERF_TYPE_TRACEPOINT] = {
177 .user_set = false,
178
179 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
180 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
Wang Nan30372f02016-02-24 11:20:45 +0000181 PERF_OUTPUT_EVNAME | PERF_OUTPUT_TRACE
David Ahern2c9e45f72011-03-17 10:03:21 -0600182 },
Arun Sharma0817a6a2011-04-14 10:38:18 -0700183
Seeteena Thoufeekfad76d42018-06-08 16:32:28 +0530184 [PERF_TYPE_HW_CACHE] = {
185 .user_set = false,
186
187 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
188 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
189 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
190 PERF_OUTPUT_SYM | PERF_OUTPUT_SYMOFFSET |
191 PERF_OUTPUT_DSO | PERF_OUTPUT_PERIOD,
192
193 .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT,
194 },
195
Arun Sharma0817a6a2011-04-14 10:38:18 -0700196 [PERF_TYPE_RAW] = {
197 .user_set = false,
198
199 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
200 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
David Ahern787bef12011-05-27 14:28:43 -0600201 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
Sandipan Das7903a702018-05-17 12:03:26 +0530202 PERF_OUTPUT_SYM | PERF_OUTPUT_SYMOFFSET |
203 PERF_OUTPUT_DSO | PERF_OUTPUT_PERIOD |
204 PERF_OUTPUT_ADDR | PERF_OUTPUT_DATA_SRC |
205 PERF_OUTPUT_WEIGHT | PERF_OUTPUT_PHYS_ADDR,
Arun Sharma0817a6a2011-04-14 10:38:18 -0700206
Wang Nan30372f02016-02-24 11:20:45 +0000207 .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT,
Arun Sharma0817a6a2011-04-14 10:38:18 -0700208 },
Wang Nan27cfef02015-12-08 02:25:43 +0000209
210 [PERF_TYPE_BREAKPOINT] = {
211 .user_set = false,
212
213 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
214 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
215 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
Sandipan Das7903a702018-05-17 12:03:26 +0530216 PERF_OUTPUT_SYM | PERF_OUTPUT_SYMOFFSET |
217 PERF_OUTPUT_DSO | PERF_OUTPUT_PERIOD,
Wang Nan27cfef02015-12-08 02:25:43 +0000218
Wang Nan30372f02016-02-24 11:20:45 +0000219 .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT,
Wang Nan27cfef02015-12-08 02:25:43 +0000220 },
Adrian Hunter14057202017-06-21 13:17:19 +0300221
222 [OUTPUT_TYPE_SYNTH] = {
223 .user_set = false,
224
225 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
226 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
227 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
Sandipan Das7903a702018-05-17 12:03:26 +0530228 PERF_OUTPUT_SYM | PERF_OUTPUT_SYMOFFSET |
229 PERF_OUTPUT_DSO | PERF_OUTPUT_SYNTH,
Adrian Hunter14057202017-06-21 13:17:19 +0300230
231 .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT,
232 },
David Ahern1424dc92011-03-09 22:23:28 -0700233};
David Ahern745f43e2011-03-09 22:23:26 -0700234
Arnaldo Carvalho de Melo642ee1c2017-10-30 13:11:15 -0300235struct perf_evsel_script {
236 char *filename;
237 FILE *fp;
238 u64 samples;
Andi Kleen4bd1bef2017-11-17 13:43:00 -0800239 /* For metric output */
240 u64 val;
241 int gnum;
Arnaldo Carvalho de Melo642ee1c2017-10-30 13:11:15 -0300242};
243
Andi Kleen4bd1bef2017-11-17 13:43:00 -0800244static inline struct perf_evsel_script *evsel_script(struct perf_evsel *evsel)
245{
246 return (struct perf_evsel_script *)evsel->priv;
247}
248
Arnaldo Carvalho de Melo642ee1c2017-10-30 13:11:15 -0300249static struct perf_evsel_script *perf_evsel_script__new(struct perf_evsel *evsel,
Jiri Olsa8ceb41d2017-01-23 22:07:59 +0100250 struct perf_data *data)
Arnaldo Carvalho de Melo642ee1c2017-10-30 13:11:15 -0300251{
Andi Kleen4bd1bef2017-11-17 13:43:00 -0800252 struct perf_evsel_script *es = zalloc(sizeof(*es));
Arnaldo Carvalho de Melo642ee1c2017-10-30 13:11:15 -0300253
254 if (es != NULL) {
Jiri Olsaeae8ad82017-01-23 22:25:41 +0100255 if (asprintf(&es->filename, "%s.%s.dump", data->file.path, perf_evsel__name(evsel)) < 0)
Arnaldo Carvalho de Melo642ee1c2017-10-30 13:11:15 -0300256 goto out_free;
257 es->fp = fopen(es->filename, "w");
258 if (es->fp == NULL)
259 goto out_free_filename;
Arnaldo Carvalho de Melo642ee1c2017-10-30 13:11:15 -0300260 }
261
262 return es;
263out_free_filename:
264 zfree(&es->filename);
265out_free:
266 free(es);
267 return NULL;
268}
269
270static void perf_evsel_script__delete(struct perf_evsel_script *es)
271{
272 zfree(&es->filename);
273 fclose(es->fp);
274 es->fp = NULL;
275 free(es);
276}
277
278static int perf_evsel_script__fprintf(struct perf_evsel_script *es, FILE *fp)
279{
280 struct stat st;
281
282 fstat(fileno(es->fp), &st);
283 return fprintf(fp, "[ perf script: Wrote %.3f MB %s (%" PRIu64 " samples) ]\n",
284 st.st_size / 1024.0 / 1024.0, es->filename, es->samples);
285}
286
Adrian Hunter14057202017-06-21 13:17:19 +0300287static inline int output_type(unsigned int type)
288{
289 switch (type) {
290 case PERF_TYPE_SYNTH:
291 return OUTPUT_TYPE_SYNTH;
292 default:
293 return type;
294 }
295}
296
297static inline unsigned int attr_type(unsigned int type)
298{
299 switch (type) {
300 case OUTPUT_TYPE_SYNTH:
301 return PERF_TYPE_SYNTH;
302 default:
303 return type;
304 }
305}
306
David Ahern2c9e45f72011-03-17 10:03:21 -0600307static bool output_set_by_user(void)
308{
309 int j;
Adrian Hunter14057202017-06-21 13:17:19 +0300310 for (j = 0; j < OUTPUT_TYPE_MAX; ++j) {
David Ahern2c9e45f72011-03-17 10:03:21 -0600311 if (output[j].user_set)
312 return true;
313 }
314 return false;
315}
David Ahern745f43e2011-03-09 22:23:26 -0700316
David Ahern9cbdb702011-04-06 21:54:20 -0600317static const char *output_field2str(enum perf_output_field field)
318{
319 int i, imax = ARRAY_SIZE(all_output_options);
320 const char *str = "";
321
322 for (i = 0; i < imax; ++i) {
323 if (all_output_options[i].field == field) {
324 str = all_output_options[i].str;
325 break;
326 }
327 }
328 return str;
329}
330
Adrian Hunter14057202017-06-21 13:17:19 +0300331#define PRINT_FIELD(x) (output[output_type(attr->type)].fields & PERF_OUTPUT_##x)
David Ahern1424dc92011-03-09 22:23:28 -0700332
Adrian Hunter6d5cdd62015-04-24 22:29:44 +0300333static int perf_evsel__do_check_stype(struct perf_evsel *evsel,
334 u64 sample_type, const char *sample_msg,
335 enum perf_output_field field,
336 bool allow_user_set)
David Ahern1424dc92011-03-09 22:23:28 -0700337{
Arnaldo Carvalho de Melo5bff01f2012-06-12 13:35:44 -0300338 struct perf_event_attr *attr = &evsel->attr;
Adrian Hunter14057202017-06-21 13:17:19 +0300339 int type = output_type(attr->type);
David Ahern9cbdb702011-04-06 21:54:20 -0600340 const char *evname;
341
342 if (attr->sample_type & sample_type)
343 return 0;
344
345 if (output[type].user_set) {
Adrian Hunter6d5cdd62015-04-24 22:29:44 +0300346 if (allow_user_set)
347 return 0;
Arnaldo Carvalho de Melo5bff01f2012-06-12 13:35:44 -0300348 evname = perf_evsel__name(evsel);
David Ahern9cbdb702011-04-06 21:54:20 -0600349 pr_err("Samples for '%s' event do not have %s attribute set. "
350 "Cannot print '%s' field.\n",
351 evname, sample_msg, output_field2str(field));
352 return -1;
353 }
354
355 /* user did not ask for it explicitly so remove from the default list */
356 output[type].fields &= ~field;
Arnaldo Carvalho de Melo5bff01f2012-06-12 13:35:44 -0300357 evname = perf_evsel__name(evsel);
David Ahern9cbdb702011-04-06 21:54:20 -0600358 pr_debug("Samples for '%s' event do not have %s attribute set. "
359 "Skipping '%s' field.\n",
360 evname, sample_msg, output_field2str(field));
361
362 return 0;
363}
364
Adrian Hunter6d5cdd62015-04-24 22:29:44 +0300365static int perf_evsel__check_stype(struct perf_evsel *evsel,
366 u64 sample_type, const char *sample_msg,
367 enum perf_output_field field)
368{
369 return perf_evsel__do_check_stype(evsel, sample_type, sample_msg, field,
370 false);
371}
372
David Ahern9cbdb702011-04-06 21:54:20 -0600373static int perf_evsel__check_attr(struct perf_evsel *evsel,
374 struct perf_session *session)
375{
376 struct perf_event_attr *attr = &evsel->attr;
Adrian Hunter6d5cdd62015-04-24 22:29:44 +0300377 bool allow_user_set;
378
Jiri Olsae099eba2016-01-05 22:09:09 +0100379 if (perf_header__has_feat(&session->header, HEADER_STAT))
380 return 0;
381
Adrian Hunter6d5cdd62015-04-24 22:29:44 +0300382 allow_user_set = perf_header__has_feat(&session->header,
383 HEADER_AUXTRACE);
David Ahern9cbdb702011-04-06 21:54:20 -0600384
David Ahern1424dc92011-03-09 22:23:28 -0700385 if (PRINT_FIELD(TRACE) &&
386 !perf_session__has_traces(session, "record -R"))
387 return -EINVAL;
388
David Ahern787bef12011-05-27 14:28:43 -0600389 if (PRINT_FIELD(IP)) {
Arnaldo Carvalho de Melo5bff01f2012-06-12 13:35:44 -0300390 if (perf_evsel__check_stype(evsel, PERF_SAMPLE_IP, "IP",
391 PERF_OUTPUT_IP))
David Ahern1424dc92011-03-09 22:23:28 -0700392 return -EINVAL;
David Ahern1424dc92011-03-09 22:23:28 -0700393 }
David Ahern7cec0922011-05-30 13:08:23 -0600394
395 if (PRINT_FIELD(ADDR) &&
Adrian Hunter6d5cdd62015-04-24 22:29:44 +0300396 perf_evsel__do_check_stype(evsel, PERF_SAMPLE_ADDR, "ADDR",
397 PERF_OUTPUT_ADDR, allow_user_set))
David Ahern7cec0922011-05-30 13:08:23 -0600398 return -EINVAL;
399
Jiri Olsa94ddddf2016-02-15 09:34:51 +0100400 if (PRINT_FIELD(DATA_SRC) &&
401 perf_evsel__check_stype(evsel, PERF_SAMPLE_DATA_SRC, "DATA_SRC",
402 PERF_OUTPUT_DATA_SRC))
403 return -EINVAL;
404
405 if (PRINT_FIELD(WEIGHT) &&
406 perf_evsel__check_stype(evsel, PERF_SAMPLE_WEIGHT, "WEIGHT",
407 PERF_OUTPUT_WEIGHT))
408 return -EINVAL;
409
Andi Kleen37fed3d2018-09-18 05:32:09 -0700410 if (PRINT_FIELD(SYM) &&
411 !(evsel->attr.sample_type & (PERF_SAMPLE_IP|PERF_SAMPLE_ADDR))) {
David Ahern7cec0922011-05-30 13:08:23 -0600412 pr_err("Display of symbols requested but neither sample IP nor "
Andi Kleen37fed3d2018-09-18 05:32:09 -0700413 "sample address\navailable. Hence, no addresses to convert "
David Ahern7cec0922011-05-30 13:08:23 -0600414 "to symbols.\n");
David Ahern787bef12011-05-27 14:28:43 -0600415 return -EINVAL;
416 }
Akihiro Nagaia978f2a2012-01-30 13:43:15 +0900417 if (PRINT_FIELD(SYMOFFSET) && !PRINT_FIELD(SYM)) {
418 pr_err("Display of offsets requested but symbol is not"
419 "selected.\n");
420 return -EINVAL;
421 }
Andi Kleen37fed3d2018-09-18 05:32:09 -0700422 if (PRINT_FIELD(DSO) &&
423 !(evsel->attr.sample_type & (PERF_SAMPLE_IP|PERF_SAMPLE_ADDR))) {
424 pr_err("Display of DSO requested but no address to convert.\n");
David Ahern610723f2011-05-27 14:28:44 -0600425 return -EINVAL;
426 }
Adrian Huntercc8fae12013-12-06 09:42:57 +0200427 if (PRINT_FIELD(SRCLINE) && !PRINT_FIELD(IP)) {
428 pr_err("Display of source line number requested but sample IP is not\n"
429 "selected. Hence, no address to lookup the source line number.\n");
430 return -EINVAL;
431 }
Andi Kleen48d02a12017-02-23 15:46:34 -0800432 if (PRINT_FIELD(BRSTACKINSN) &&
433 !(perf_evlist__combined_branch_type(session->evlist) &
434 PERF_SAMPLE_BRANCH_ANY)) {
435 pr_err("Display of branch stack assembler requested, but non all-branch filter set\n"
436 "Hint: run 'perf record -b ...'\n");
437 return -EINVAL;
438 }
David Ahern1424dc92011-03-09 22:23:28 -0700439 if ((PRINT_FIELD(PID) || PRINT_FIELD(TID)) &&
Arnaldo Carvalho de Melo5bff01f2012-06-12 13:35:44 -0300440 perf_evsel__check_stype(evsel, PERF_SAMPLE_TID, "TID",
441 PERF_OUTPUT_TID|PERF_OUTPUT_PID))
David Ahern1424dc92011-03-09 22:23:28 -0700442 return -EINVAL;
David Ahern1424dc92011-03-09 22:23:28 -0700443
444 if (PRINT_FIELD(TIME) &&
Arnaldo Carvalho de Melo5bff01f2012-06-12 13:35:44 -0300445 perf_evsel__check_stype(evsel, PERF_SAMPLE_TIME, "TIME",
446 PERF_OUTPUT_TIME))
David Ahern1424dc92011-03-09 22:23:28 -0700447 return -EINVAL;
David Ahern1424dc92011-03-09 22:23:28 -0700448
449 if (PRINT_FIELD(CPU) &&
Adrian Hunter6d5cdd62015-04-24 22:29:44 +0300450 perf_evsel__do_check_stype(evsel, PERF_SAMPLE_CPU, "CPU",
451 PERF_OUTPUT_CPU, allow_user_set))
David Ahern1424dc92011-03-09 22:23:28 -0700452 return -EINVAL;
David Ahern9cbdb702011-04-06 21:54:20 -0600453
Stephane Eranianfc36f942015-08-31 18:41:10 +0200454 if (PRINT_FIELD(IREGS) &&
455 perf_evsel__check_stype(evsel, PERF_SAMPLE_REGS_INTR, "IREGS",
456 PERF_OUTPUT_IREGS))
457 return -EINVAL;
458
Andi Kleenb1491ac2017-09-05 11:40:57 -0700459 if (PRINT_FIELD(UREGS) &&
460 perf_evsel__check_stype(evsel, PERF_SAMPLE_REGS_USER, "UREGS",
461 PERF_OUTPUT_UREGS))
462 return -EINVAL;
463
Kan Liang49d58f02017-08-29 13:11:11 -0400464 if (PRINT_FIELD(PHYS_ADDR) &&
465 perf_evsel__check_stype(evsel, PERF_SAMPLE_PHYS_ADDR, "PHYS_ADDR",
466 PERF_OUTPUT_PHYS_ADDR))
467 return -EINVAL;
468
David Ahern9cbdb702011-04-06 21:54:20 -0600469 return 0;
470}
471
Adrian Hunter7ea95722013-11-01 15:51:30 +0200472static void set_print_ip_opts(struct perf_event_attr *attr)
473{
Adrian Hunter14057202017-06-21 13:17:19 +0300474 unsigned int type = output_type(attr->type);
Adrian Hunter7ea95722013-11-01 15:51:30 +0200475
476 output[type].print_ip_opts = 0;
477 if (PRINT_FIELD(IP))
Arnaldo Carvalho de Meloe20ab862016-04-12 15:16:15 -0300478 output[type].print_ip_opts |= EVSEL__PRINT_IP;
Adrian Hunter7ea95722013-11-01 15:51:30 +0200479
480 if (PRINT_FIELD(SYM))
Arnaldo Carvalho de Meloe20ab862016-04-12 15:16:15 -0300481 output[type].print_ip_opts |= EVSEL__PRINT_SYM;
Adrian Hunter7ea95722013-11-01 15:51:30 +0200482
483 if (PRINT_FIELD(DSO))
Arnaldo Carvalho de Meloe20ab862016-04-12 15:16:15 -0300484 output[type].print_ip_opts |= EVSEL__PRINT_DSO;
Adrian Hunter7ea95722013-11-01 15:51:30 +0200485
486 if (PRINT_FIELD(SYMOFFSET))
Arnaldo Carvalho de Meloe20ab862016-04-12 15:16:15 -0300487 output[type].print_ip_opts |= EVSEL__PRINT_SYMOFFSET;
Adrian Huntercc8fae12013-12-06 09:42:57 +0200488
489 if (PRINT_FIELD(SRCLINE))
Arnaldo Carvalho de Meloe20ab862016-04-12 15:16:15 -0300490 output[type].print_ip_opts |= EVSEL__PRINT_SRCLINE;
Adrian Hunter7ea95722013-11-01 15:51:30 +0200491}
492
David Ahern9cbdb702011-04-06 21:54:20 -0600493/*
494 * verify all user requested events exist and the samples
495 * have the expected data
496 */
497static int perf_session__check_output_opt(struct perf_session *session)
498{
He Kuang40f20e52016-05-16 04:51:19 +0000499 unsigned int j;
David Ahern9cbdb702011-04-06 21:54:20 -0600500 struct perf_evsel *evsel;
501
Adrian Hunter14057202017-06-21 13:17:19 +0300502 for (j = 0; j < OUTPUT_TYPE_MAX; ++j) {
503 evsel = perf_session__find_first_evtype(session, attr_type(j));
David Ahern9cbdb702011-04-06 21:54:20 -0600504
505 /*
506 * even if fields is set to 0 (ie., show nothing) event must
507 * exist if user explicitly includes it on the command line
508 */
Adrian Hunter14057202017-06-21 13:17:19 +0300509 if (!evsel && output[j].user_set && !output[j].wildcard_set &&
510 j != OUTPUT_TYPE_SYNTH) {
David Ahern9cbdb702011-04-06 21:54:20 -0600511 pr_err("%s events do not exist. "
Adrian Hunter701516a2017-05-26 11:17:20 +0300512 "Remove corresponding -F option to proceed.\n",
David Ahern9cbdb702011-04-06 21:54:20 -0600513 event_type(j));
514 return -1;
515 }
516
517 if (evsel && output[j].fields &&
518 perf_evsel__check_attr(evsel, session))
519 return -1;
David Aherna6ffaf92013-08-07 22:50:51 -0400520
521 if (evsel == NULL)
522 continue;
523
Adrian Hunter7ea95722013-11-01 15:51:30 +0200524 set_print_ip_opts(&evsel->attr);
David Ahern1424dc92011-03-09 22:23:28 -0700525 }
526
Adrian Hunter98526ee2014-07-31 09:00:59 +0300527 if (!no_callchain) {
528 bool use_callchain = false;
He Kuang71ac8992016-08-04 11:25:43 +0000529 bool not_pipe = false;
Adrian Hunter98526ee2014-07-31 09:00:59 +0300530
Arnaldo Carvalho de Meloe5cadb92016-06-23 11:26:15 -0300531 evlist__for_each_entry(session->evlist, evsel) {
He Kuang71ac8992016-08-04 11:25:43 +0000532 not_pipe = true;
Arnaldo Carvalho de Melo27de9b22018-05-28 16:00:29 -0300533 if (evsel__has_callchain(evsel)) {
Adrian Hunter98526ee2014-07-31 09:00:59 +0300534 use_callchain = true;
535 break;
536 }
537 }
He Kuang71ac8992016-08-04 11:25:43 +0000538 if (not_pipe && !use_callchain)
Adrian Hunter98526ee2014-07-31 09:00:59 +0300539 symbol_conf.use_callchain = false;
540 }
541
David Ahern80b8b492013-11-19 21:07:37 -0700542 /*
543 * set default for tracepoints to print symbols only
544 * if callchains are present
545 */
546 if (symbol_conf.use_callchain &&
547 !output[PERF_TYPE_TRACEPOINT].user_set) {
David Ahern80b8b492013-11-19 21:07:37 -0700548 j = PERF_TYPE_TRACEPOINT;
David Ahern80b8b492013-11-19 21:07:37 -0700549
Arnaldo Carvalho de Meloe5cadb92016-06-23 11:26:15 -0300550 evlist__for_each_entry(session->evlist, evsel) {
He Kuang40f20e52016-05-16 04:51:19 +0000551 if (evsel->attr.type != j)
552 continue;
David Ahern80b8b492013-11-19 21:07:37 -0700553
Arnaldo Carvalho de Melo27de9b22018-05-28 16:00:29 -0300554 if (evsel__has_callchain(evsel)) {
He Kuang40f20e52016-05-16 04:51:19 +0000555 output[j].fields |= PERF_OUTPUT_IP;
556 output[j].fields |= PERF_OUTPUT_SYM;
Sandipan Das7903a702018-05-17 12:03:26 +0530557 output[j].fields |= PERF_OUTPUT_SYMOFFSET;
He Kuang40f20e52016-05-16 04:51:19 +0000558 output[j].fields |= PERF_OUTPUT_DSO;
Arnaldo Carvalho de Melo27de9b22018-05-28 16:00:29 -0300559 set_print_ip_opts(&evsel->attr);
He Kuang40f20e52016-05-16 04:51:19 +0000560 goto out;
561 }
David Ahern80b8b492013-11-19 21:07:37 -0700562 }
563 }
564
565out:
David Ahern1424dc92011-03-09 22:23:28 -0700566 return 0;
567}
David Ahern745f43e2011-03-09 22:23:26 -0700568
Milian Wolff9add8fe2018-11-07 23:34:37 +0100569static int perf_sample__fprintf_regs(struct regs_dump *regs, uint64_t mask,
570 FILE *fp
571)
Stephane Eranianfc36f942015-08-31 18:41:10 +0200572{
Andi Kleenb1491ac2017-09-05 11:40:57 -0700573 unsigned i = 0, r;
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300574 int printed = 0;
Andi Kleenb1491ac2017-09-05 11:40:57 -0700575
576 if (!regs || !regs->regs)
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300577 return 0;
Andi Kleenb1491ac2017-09-05 11:40:57 -0700578
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300579 printed += fprintf(fp, " ABI:%" PRIu64 " ", regs->abi);
Andi Kleenb1491ac2017-09-05 11:40:57 -0700580
581 for_each_set_bit(r, (unsigned long *) &mask, sizeof(mask) * 8) {
582 u64 val = regs->regs[i++];
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300583 printed += fprintf(fp, "%5s:0x%"PRIx64" ", perf_reg_name(r), val);
Andi Kleenb1491ac2017-09-05 11:40:57 -0700584 }
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300585
Milian Wolffb07d16f2018-11-07 10:37:05 +0100586 fprintf(fp, "\n");
587
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300588 return printed;
Andi Kleenb1491ac2017-09-05 11:40:57 -0700589}
590
Milian Wolff9add8fe2018-11-07 23:34:37 +0100591static int perf_sample__fprintf_iregs(struct perf_sample *sample,
592 struct perf_event_attr *attr, FILE *fp)
593{
594 return perf_sample__fprintf_regs(&sample->intr_regs,
595 attr->sample_regs_intr, fp);
596}
597
598static int perf_sample__fprintf_uregs(struct perf_sample *sample,
599 struct perf_event_attr *attr, FILE *fp)
600{
601 return perf_sample__fprintf_regs(&sample->user_regs,
602 attr->sample_regs_user, fp);
603}
604
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300605static int perf_sample__fprintf_start(struct perf_sample *sample,
606 struct thread *thread,
Jiri Olsa28a0b392018-01-07 17:03:52 +0100607 struct perf_evsel *evsel,
608 u32 type, FILE *fp)
David Ahernc70c94b2011-03-09 22:23:25 -0700609{
Arnaldo Carvalho de Melo5bff01f2012-06-12 13:35:44 -0300610 struct perf_event_attr *attr = &evsel->attr;
David Ahernc70c94b2011-03-09 22:23:25 -0700611 unsigned long secs;
David Ahern745f43e2011-03-09 22:23:26 -0700612 unsigned long long nsecs;
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300613 int printed = 0;
David Ahernc70c94b2011-03-09 22:23:25 -0700614
David Ahern745f43e2011-03-09 22:23:26 -0700615 if (PRINT_FIELD(COMM)) {
616 if (latency_format)
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300617 printed += fprintf(fp, "%8.8s ", thread__comm_str(thread));
Arnaldo Carvalho de Melob8798332018-06-04 10:34:20 -0300618 else if (PRINT_FIELD(IP) && evsel__has_callchain(evsel) && symbol_conf.use_callchain)
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300619 printed += fprintf(fp, "%s ", thread__comm_str(thread));
David Ahern745f43e2011-03-09 22:23:26 -0700620 else
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300621 printed += fprintf(fp, "%16s ", thread__comm_str(thread));
David Ahern745f43e2011-03-09 22:23:26 -0700622 }
David Ahernc70c94b2011-03-09 22:23:25 -0700623
David Ahern745f43e2011-03-09 22:23:26 -0700624 if (PRINT_FIELD(PID) && PRINT_FIELD(TID))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300625 printed += fprintf(fp, "%5d/%-5d ", sample->pid, sample->tid);
David Ahern745f43e2011-03-09 22:23:26 -0700626 else if (PRINT_FIELD(PID))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300627 printed += fprintf(fp, "%5d ", sample->pid);
David Ahern745f43e2011-03-09 22:23:26 -0700628 else if (PRINT_FIELD(TID))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300629 printed += fprintf(fp, "%5d ", sample->tid);
David Ahernc70c94b2011-03-09 22:23:25 -0700630
David Ahern745f43e2011-03-09 22:23:26 -0700631 if (PRINT_FIELD(CPU)) {
632 if (latency_format)
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300633 printed += fprintf(fp, "%3d ", sample->cpu);
David Ahern745f43e2011-03-09 22:23:26 -0700634 else
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300635 printed += fprintf(fp, "[%03d] ", sample->cpu);
David Ahern745f43e2011-03-09 22:23:26 -0700636 }
David Ahernc70c94b2011-03-09 22:23:25 -0700637
Jiri Olsa28a0b392018-01-07 17:03:52 +0100638 if (PRINT_FIELD(MISC)) {
639 int ret = 0;
640
641 #define has(m) \
642 (sample->misc & PERF_RECORD_MISC_##m) == PERF_RECORD_MISC_##m
643
644 if (has(KERNEL))
645 ret += fprintf(fp, "K");
646 if (has(USER))
647 ret += fprintf(fp, "U");
648 if (has(HYPERVISOR))
649 ret += fprintf(fp, "H");
650 if (has(GUEST_KERNEL))
651 ret += fprintf(fp, "G");
652 if (has(GUEST_USER))
653 ret += fprintf(fp, "g");
654
655 switch (type) {
656 case PERF_RECORD_MMAP:
657 case PERF_RECORD_MMAP2:
658 if (has(MMAP_DATA))
659 ret += fprintf(fp, "M");
660 break;
661 case PERF_RECORD_COMM:
662 if (has(COMM_EXEC))
663 ret += fprintf(fp, "E");
664 break;
665 case PERF_RECORD_SWITCH:
666 case PERF_RECORD_SWITCH_CPU_WIDE:
Alexey Budankovbf30cc12018-04-09 10:26:46 +0300667 if (has(SWITCH_OUT)) {
Jiri Olsa28a0b392018-01-07 17:03:52 +0100668 ret += fprintf(fp, "S");
Alexey Budankovbf30cc12018-04-09 10:26:46 +0300669 if (sample->misc & PERF_RECORD_MISC_SWITCH_OUT_PREEMPT)
670 ret += fprintf(fp, "p");
671 }
Jiri Olsa28a0b392018-01-07 17:03:52 +0100672 default:
673 break;
674 }
675
676 #undef has
677
678 ret += fprintf(fp, "%*s", 6 - ret, " ");
679 printed += ret;
680 }
681
David Ahern745f43e2011-03-09 22:23:26 -0700682 if (PRINT_FIELD(TIME)) {
683 nsecs = sample->time;
Arnaldo Carvalho de Melobd48c632016-08-05 15:40:30 -0300684 secs = nsecs / NSEC_PER_SEC;
685 nsecs -= secs * NSEC_PER_SEC;
Namhyung Kim99620a52016-10-24 11:02:45 +0900686
Adrian Hunter83e19862015-09-25 16:15:36 +0300687 if (nanosecs)
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300688 printed += fprintf(fp, "%5lu.%09llu: ", secs, nsecs);
Namhyung Kim99620a52016-10-24 11:02:45 +0900689 else {
690 char sample_time[32];
691 timestamp__scnprintf_usec(sample->time, sample_time, sizeof(sample_time));
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300692 printed += fprintf(fp, "%12s: ", sample_time);
Namhyung Kim99620a52016-10-24 11:02:45 +0900693 }
David Ahern745f43e2011-03-09 22:23:26 -0700694 }
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300695
696 return printed;
David Ahernc70c94b2011-03-09 22:23:25 -0700697}
698
Stephane Eraniandc323ce2015-08-31 18:41:13 +0200699static inline char
700mispred_str(struct branch_entry *br)
701{
702 if (!(br->flags.mispred || br->flags.predicted))
703 return '-';
704
705 return br->flags.predicted ? 'P' : 'M';
706}
707
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300708static int perf_sample__fprintf_brstack(struct perf_sample *sample,
709 struct thread *thread,
710 struct perf_event_attr *attr, FILE *fp)
Stephane Eraniandc323ce2015-08-31 18:41:13 +0200711{
712 struct branch_stack *br = sample->branch_stack;
Mark Santaniello55b9b502017-06-19 09:38:24 -0700713 struct addr_location alf, alt;
714 u64 i, from, to;
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300715 int printed = 0;
Stephane Eraniandc323ce2015-08-31 18:41:13 +0200716
717 if (!(br && br->nr))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300718 return 0;
Stephane Eraniandc323ce2015-08-31 18:41:13 +0200719
720 for (i = 0; i < br->nr; i++) {
Mark Santaniello55b9b502017-06-19 09:38:24 -0700721 from = br->entries[i].from;
722 to = br->entries[i].to;
723
724 if (PRINT_FIELD(DSO)) {
725 memset(&alf, 0, sizeof(alf));
726 memset(&alt, 0, sizeof(alt));
Arnaldo Carvalho de Melof07a2d32018-04-24 10:49:50 -0300727 thread__find_map(thread, sample->cpumode, from, &alf);
728 thread__find_map(thread, sample->cpumode, to, &alt);
Mark Santaniello55b9b502017-06-19 09:38:24 -0700729 }
730
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300731 printed += fprintf(fp, " 0x%"PRIx64, from);
Mark Santaniello55b9b502017-06-19 09:38:24 -0700732 if (PRINT_FIELD(DSO)) {
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300733 printed += fprintf(fp, "(");
734 printed += map__fprintf_dsoname(alf.map, fp);
735 printed += fprintf(fp, ")");
Mark Santaniello55b9b502017-06-19 09:38:24 -0700736 }
737
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300738 printed += fprintf(fp, "/0x%"PRIx64, to);
Mark Santaniello55b9b502017-06-19 09:38:24 -0700739 if (PRINT_FIELD(DSO)) {
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300740 printed += fprintf(fp, "(");
741 printed += map__fprintf_dsoname(alt.map, fp);
742 printed += fprintf(fp, ")");
Mark Santaniello55b9b502017-06-19 09:38:24 -0700743 }
744
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300745 printed += fprintf(fp, "/%c/%c/%c/%d ",
Stephane Eraniandc323ce2015-08-31 18:41:13 +0200746 mispred_str( br->entries + i),
747 br->entries[i].flags.in_tx? 'X' : '-',
748 br->entries[i].flags.abort? 'A' : '-',
749 br->entries[i].flags.cycles);
750 }
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300751
752 return printed;
Stephane Eraniandc323ce2015-08-31 18:41:13 +0200753}
754
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300755static int perf_sample__fprintf_brstacksym(struct perf_sample *sample,
756 struct thread *thread,
757 struct perf_event_attr *attr, FILE *fp)
Stephane Eraniandc323ce2015-08-31 18:41:13 +0200758{
759 struct branch_stack *br = sample->branch_stack;
760 struct addr_location alf, alt;
Stephane Eraniandc323ce2015-08-31 18:41:13 +0200761 u64 i, from, to;
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300762 int printed = 0;
Stephane Eraniandc323ce2015-08-31 18:41:13 +0200763
764 if (!(br && br->nr))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300765 return 0;
Stephane Eraniandc323ce2015-08-31 18:41:13 +0200766
767 for (i = 0; i < br->nr; i++) {
768
769 memset(&alf, 0, sizeof(alf));
770 memset(&alt, 0, sizeof(alt));
771 from = br->entries[i].from;
772 to = br->entries[i].to;
773
Arnaldo Carvalho de Melocc5f02f2018-04-24 11:32:30 -0300774 thread__find_symbol(thread, sample->cpumode, from, &alf);
775 thread__find_symbol(thread, sample->cpumode, to, &alt);
Stephane Eraniandc323ce2015-08-31 18:41:13 +0200776
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300777 printed += symbol__fprintf_symname_offs(alf.sym, &alf, fp);
Mark Santaniello55b9b502017-06-19 09:38:24 -0700778 if (PRINT_FIELD(DSO)) {
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300779 printed += fprintf(fp, "(");
780 printed += map__fprintf_dsoname(alf.map, fp);
781 printed += fprintf(fp, ")");
Mark Santaniello55b9b502017-06-19 09:38:24 -0700782 }
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300783 printed += fprintf(fp, "%c", '/');
784 printed += symbol__fprintf_symname_offs(alt.sym, &alt, fp);
Mark Santaniello55b9b502017-06-19 09:38:24 -0700785 if (PRINT_FIELD(DSO)) {
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300786 printed += fprintf(fp, "(");
787 printed += map__fprintf_dsoname(alt.map, fp);
788 printed += fprintf(fp, ")");
Mark Santaniello55b9b502017-06-19 09:38:24 -0700789 }
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300790 printed += fprintf(fp, "/%c/%c/%c/%d ",
Stephane Eraniandc323ce2015-08-31 18:41:13 +0200791 mispred_str( br->entries + i),
792 br->entries[i].flags.in_tx? 'X' : '-',
793 br->entries[i].flags.abort? 'A' : '-',
794 br->entries[i].flags.cycles);
795 }
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300796
797 return printed;
Stephane Eraniandc323ce2015-08-31 18:41:13 +0200798}
799
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300800static int perf_sample__fprintf_brstackoff(struct perf_sample *sample,
801 struct thread *thread,
802 struct perf_event_attr *attr, FILE *fp)
Mark Santaniello106dacd2017-06-19 09:38:25 -0700803{
804 struct branch_stack *br = sample->branch_stack;
805 struct addr_location alf, alt;
806 u64 i, from, to;
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300807 int printed = 0;
Mark Santaniello106dacd2017-06-19 09:38:25 -0700808
809 if (!(br && br->nr))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300810 return 0;
Mark Santaniello106dacd2017-06-19 09:38:25 -0700811
812 for (i = 0; i < br->nr; i++) {
813
814 memset(&alf, 0, sizeof(alf));
815 memset(&alt, 0, sizeof(alt));
816 from = br->entries[i].from;
817 to = br->entries[i].to;
818
Arnaldo Carvalho de Melo71a84b52018-04-24 11:58:56 -0300819 if (thread__find_map(thread, sample->cpumode, from, &alf) &&
820 !alf.map->dso->adjust_symbols)
Mark Santaniello106dacd2017-06-19 09:38:25 -0700821 from = map__map_ip(alf.map, from);
822
Arnaldo Carvalho de Melo71a84b52018-04-24 11:58:56 -0300823 if (thread__find_map(thread, sample->cpumode, to, &alt) &&
824 !alt.map->dso->adjust_symbols)
Mark Santaniello106dacd2017-06-19 09:38:25 -0700825 to = map__map_ip(alt.map, to);
826
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300827 printed += fprintf(fp, " 0x%"PRIx64, from);
Mark Santaniello106dacd2017-06-19 09:38:25 -0700828 if (PRINT_FIELD(DSO)) {
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300829 printed += fprintf(fp, "(");
830 printed += map__fprintf_dsoname(alf.map, fp);
831 printed += fprintf(fp, ")");
Mark Santaniello106dacd2017-06-19 09:38:25 -0700832 }
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300833 printed += fprintf(fp, "/0x%"PRIx64, to);
Mark Santaniello106dacd2017-06-19 09:38:25 -0700834 if (PRINT_FIELD(DSO)) {
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300835 printed += fprintf(fp, "(");
836 printed += map__fprintf_dsoname(alt.map, fp);
837 printed += fprintf(fp, ")");
Mark Santaniello106dacd2017-06-19 09:38:25 -0700838 }
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300839 printed += fprintf(fp, "/%c/%c/%c/%d ",
Mark Santaniello106dacd2017-06-19 09:38:25 -0700840 mispred_str(br->entries + i),
841 br->entries[i].flags.in_tx ? 'X' : '-',
842 br->entries[i].flags.abort ? 'A' : '-',
843 br->entries[i].flags.cycles);
844 }
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300845
846 return printed;
Mark Santaniello106dacd2017-06-19 09:38:25 -0700847}
Andi Kleen48d02a12017-02-23 15:46:34 -0800848#define MAXBB 16384UL
849
850static int grab_bb(u8 *buffer, u64 start, u64 end,
851 struct machine *machine, struct thread *thread,
852 bool *is64bit, u8 *cpumode, bool last)
853{
854 long offset, len;
855 struct addr_location al;
856 bool kernel;
857
858 if (!start || !end)
859 return 0;
860
861 kernel = machine__kernel_ip(machine, start);
862 if (kernel)
863 *cpumode = PERF_RECORD_MISC_KERNEL;
864 else
865 *cpumode = PERF_RECORD_MISC_USER;
866
867 /*
868 * Block overlaps between kernel and user.
869 * This can happen due to ring filtering
870 * On Intel CPUs the entry into the kernel is filtered,
871 * but the exit is not. Let the caller patch it up.
872 */
873 if (kernel != machine__kernel_ip(machine, end)) {
Arnaldo Carvalho de Melo5ce2c5b2017-10-26 09:55:22 -0300874 pr_debug("\tblock %" PRIx64 "-%" PRIx64 " transfers between kernel and user\n", start, end);
Andi Kleen48d02a12017-02-23 15:46:34 -0800875 return -ENXIO;
876 }
877
878 memset(&al, 0, sizeof(al));
879 if (end - start > MAXBB - MAXINSN) {
880 if (last)
Arnaldo Carvalho de Melo5ce2c5b2017-10-26 09:55:22 -0300881 pr_debug("\tbrstack does not reach to final jump (%" PRIx64 "-%" PRIx64 ")\n", start, end);
Andi Kleen48d02a12017-02-23 15:46:34 -0800882 else
Arnaldo Carvalho de Melo5ce2c5b2017-10-26 09:55:22 -0300883 pr_debug("\tblock %" PRIx64 "-%" PRIx64 " (%" PRIu64 ") too long to dump\n", start, end, end - start);
Andi Kleen48d02a12017-02-23 15:46:34 -0800884 return 0;
885 }
886
Arnaldo Carvalho de Melo71a84b52018-04-24 11:58:56 -0300887 if (!thread__find_map(thread, *cpumode, start, &al) || !al.map->dso) {
Arnaldo Carvalho de Melo5ce2c5b2017-10-26 09:55:22 -0300888 pr_debug("\tcannot resolve %" PRIx64 "-%" PRIx64 "\n", start, end);
Andi Kleen48d02a12017-02-23 15:46:34 -0800889 return 0;
890 }
891 if (al.map->dso->data.status == DSO_DATA_STATUS_ERROR) {
Arnaldo Carvalho de Melo5ce2c5b2017-10-26 09:55:22 -0300892 pr_debug("\tcannot resolve %" PRIx64 "-%" PRIx64 "\n", start, end);
Andi Kleen48d02a12017-02-23 15:46:34 -0800893 return 0;
894 }
895
896 /* Load maps to ensure dso->is_64_bit has been updated */
897 map__load(al.map);
898
899 offset = al.map->map_ip(al.map, start);
900 len = dso__data_read_offset(al.map->dso, machine, offset, (u8 *)buffer,
901 end - start + MAXINSN);
902
903 *is64bit = al.map->dso->is_64_bit;
904 if (len <= 0)
Arnaldo Carvalho de Melo5ce2c5b2017-10-26 09:55:22 -0300905 pr_debug("\tcannot fetch code for block at %" PRIx64 "-%" PRIx64 "\n",
Andi Kleen48d02a12017-02-23 15:46:34 -0800906 start, end);
907 return len;
908}
909
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300910static int ip__fprintf_jump(uint64_t ip, struct branch_entry *en,
911 struct perf_insn *x, u8 *inbuf, int len,
Andi Kleenfe571202018-09-24 10:07:32 -0700912 int insn, FILE *fp, int *total_cycles)
Andi Kleen48d02a12017-02-23 15:46:34 -0800913{
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300914 int printed = fprintf(fp, "\t%016" PRIx64 "\t%-30s\t#%s%s%s%s", ip,
915 dump_insn(x, ip, inbuf, len, NULL),
916 en->flags.predicted ? " PRED" : "",
917 en->flags.mispred ? " MISPRED" : "",
918 en->flags.in_tx ? " INTX" : "",
919 en->flags.abort ? " ABORT" : "");
Andi Kleen48d02a12017-02-23 15:46:34 -0800920 if (en->flags.cycles) {
Andi Kleenfe571202018-09-24 10:07:32 -0700921 *total_cycles += en->flags.cycles;
922 printed += fprintf(fp, " %d cycles [%d]", en->flags.cycles, *total_cycles);
Andi Kleen48d02a12017-02-23 15:46:34 -0800923 if (insn)
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300924 printed += fprintf(fp, " %.2f IPC", (float)insn / en->flags.cycles);
Andi Kleen48d02a12017-02-23 15:46:34 -0800925 }
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300926 return printed + fprintf(fp, "\n");
Andi Kleen48d02a12017-02-23 15:46:34 -0800927}
928
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300929static int ip__fprintf_sym(uint64_t addr, struct thread *thread,
930 u8 cpumode, int cpu, struct symbol **lastsym,
931 struct perf_event_attr *attr, FILE *fp)
Andi Kleen48d02a12017-02-23 15:46:34 -0800932{
933 struct addr_location al;
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300934 int off, printed = 0;
Andi Kleen48d02a12017-02-23 15:46:34 -0800935
936 memset(&al, 0, sizeof(al));
937
Arnaldo Carvalho de Melo404eb5a2018-04-26 09:34:37 -0300938 thread__find_map(thread, cpumode, addr, &al);
939
Andi Kleen48d02a12017-02-23 15:46:34 -0800940 if ((*lastsym) && al.addr >= (*lastsym)->start && al.addr < (*lastsym)->end)
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300941 return 0;
Andi Kleen48d02a12017-02-23 15:46:34 -0800942
943 al.cpu = cpu;
944 al.sym = NULL;
945 if (al.map)
946 al.sym = map__find_symbol(al.map, al.addr);
947
948 if (!al.sym)
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300949 return 0;
Andi Kleen48d02a12017-02-23 15:46:34 -0800950
951 if (al.addr < al.sym->end)
952 off = al.addr - al.sym->start;
953 else
954 off = al.addr - al.map->start - al.sym->start;
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300955 printed += fprintf(fp, "\t%s", al.sym->name);
Andi Kleen48d02a12017-02-23 15:46:34 -0800956 if (off)
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300957 printed += fprintf(fp, "%+d", off);
958 printed += fprintf(fp, ":");
Andi Kleen48d02a12017-02-23 15:46:34 -0800959 if (PRINT_FIELD(SRCLINE))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300960 printed += map__fprintf_srcline(al.map, al.addr, "\t", fp);
961 printed += fprintf(fp, "\n");
Andi Kleen48d02a12017-02-23 15:46:34 -0800962 *lastsym = al.sym;
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300963
964 return printed;
Andi Kleen48d02a12017-02-23 15:46:34 -0800965}
966
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300967static int perf_sample__fprintf_brstackinsn(struct perf_sample *sample,
968 struct thread *thread,
969 struct perf_event_attr *attr,
970 struct machine *machine, FILE *fp)
Andi Kleen48d02a12017-02-23 15:46:34 -0800971{
972 struct branch_stack *br = sample->branch_stack;
973 u64 start, end;
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300974 int i, insn, len, nr, ilen, printed = 0;
Andi Kleen48d02a12017-02-23 15:46:34 -0800975 struct perf_insn x;
976 u8 buffer[MAXBB];
977 unsigned off;
978 struct symbol *lastsym = NULL;
Andi Kleenfe571202018-09-24 10:07:32 -0700979 int total_cycles = 0;
Andi Kleen48d02a12017-02-23 15:46:34 -0800980
981 if (!(br && br->nr))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300982 return 0;
Andi Kleen48d02a12017-02-23 15:46:34 -0800983 nr = br->nr;
984 if (max_blocks && nr > max_blocks + 1)
985 nr = max_blocks + 1;
986
987 x.thread = thread;
988 x.cpu = sample->cpu;
989
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300990 printed += fprintf(fp, "%c", '\n');
Andi Kleen48d02a12017-02-23 15:46:34 -0800991
992 /* Handle first from jump, of which we don't know the entry. */
993 len = grab_bb(buffer, br->entries[nr-1].from,
994 br->entries[nr-1].from,
995 machine, thread, &x.is64bit, &x.cpumode, false);
996 if (len > 0) {
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300997 printed += ip__fprintf_sym(br->entries[nr - 1].from, thread,
998 x.cpumode, x.cpu, &lastsym, attr, fp);
999 printed += ip__fprintf_jump(br->entries[nr - 1].from, &br->entries[nr - 1],
Andi Kleenfe571202018-09-24 10:07:32 -07001000 &x, buffer, len, 0, fp, &total_cycles);
Andi Kleen48d02a12017-02-23 15:46:34 -08001001 }
1002
1003 /* Print all blocks */
1004 for (i = nr - 2; i >= 0; i--) {
1005 if (br->entries[i].from || br->entries[i].to)
1006 pr_debug("%d: %" PRIx64 "-%" PRIx64 "\n", i,
1007 br->entries[i].from,
1008 br->entries[i].to);
1009 start = br->entries[i + 1].to;
1010 end = br->entries[i].from;
1011
1012 len = grab_bb(buffer, start, end, machine, thread, &x.is64bit, &x.cpumode, false);
1013 /* Patch up missing kernel transfers due to ring filters */
1014 if (len == -ENXIO && i > 0) {
1015 end = br->entries[--i].from;
1016 pr_debug("\tpatching up to %" PRIx64 "-%" PRIx64 "\n", start, end);
1017 len = grab_bb(buffer, start, end, machine, thread, &x.is64bit, &x.cpumode, false);
1018 }
1019 if (len <= 0)
1020 continue;
1021
1022 insn = 0;
1023 for (off = 0;; off += ilen) {
1024 uint64_t ip = start + off;
1025
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001026 printed += ip__fprintf_sym(ip, thread, x.cpumode, x.cpu, &lastsym, attr, fp);
Andi Kleen48d02a12017-02-23 15:46:34 -08001027 if (ip == end) {
Andi Kleenfe571202018-09-24 10:07:32 -07001028 printed += ip__fprintf_jump(ip, &br->entries[i], &x, buffer + off, len - off, insn, fp,
1029 &total_cycles);
Andi Kleen48d02a12017-02-23 15:46:34 -08001030 break;
1031 } else {
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001032 printed += fprintf(fp, "\t%016" PRIx64 "\t%s\n", ip,
1033 dump_insn(&x, ip, buffer + off, len - off, &ilen));
Andi Kleen48d02a12017-02-23 15:46:34 -08001034 if (ilen == 0)
1035 break;
1036 insn++;
1037 }
1038 }
1039 }
1040
1041 /*
1042 * Hit the branch? In this case we are already done, and the target
1043 * has not been executed yet.
1044 */
1045 if (br->entries[0].from == sample->ip)
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001046 goto out;
Andi Kleen48d02a12017-02-23 15:46:34 -08001047 if (br->entries[0].flags.abort)
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001048 goto out;
Andi Kleen48d02a12017-02-23 15:46:34 -08001049
1050 /*
1051 * Print final block upto sample
1052 */
1053 start = br->entries[0].to;
1054 end = sample->ip;
1055 len = grab_bb(buffer, start, end, machine, thread, &x.is64bit, &x.cpumode, true);
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001056 printed += ip__fprintf_sym(start, thread, x.cpumode, x.cpu, &lastsym, attr, fp);
Andi Kleen48d02a12017-02-23 15:46:34 -08001057 if (len <= 0) {
1058 /* Print at least last IP if basic block did not work */
1059 len = grab_bb(buffer, sample->ip, sample->ip,
1060 machine, thread, &x.is64bit, &x.cpumode, false);
1061 if (len <= 0)
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001062 goto out;
Andi Kleen48d02a12017-02-23 15:46:34 -08001063
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001064 printed += fprintf(fp, "\t%016" PRIx64 "\t%s\n", sample->ip,
Andi Kleen48d02a12017-02-23 15:46:34 -08001065 dump_insn(&x, sample->ip, buffer, len, NULL));
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001066 goto out;
Andi Kleen48d02a12017-02-23 15:46:34 -08001067 }
1068 for (off = 0; off <= end - start; off += ilen) {
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001069 printed += fprintf(fp, "\t%016" PRIx64 "\t%s\n", start + off,
1070 dump_insn(&x, start + off, buffer + off, len - off, &ilen));
Andi Kleen48d02a12017-02-23 15:46:34 -08001071 if (ilen == 0)
1072 break;
1073 }
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001074out:
1075 return printed;
Andi Kleen48d02a12017-02-23 15:46:34 -08001076}
Stephane Eraniandc323ce2015-08-31 18:41:13 +02001077
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001078static int perf_sample__fprintf_addr(struct perf_sample *sample,
1079 struct thread *thread,
1080 struct perf_event_attr *attr, FILE *fp)
David Ahern7cec0922011-05-30 13:08:23 -06001081{
1082 struct addr_location al;
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001083 int printed = fprintf(fp, "%16" PRIx64, sample->addr);
David Ahern7cec0922011-05-30 13:08:23 -06001084
1085 if (!sample_addr_correlates_sym(attr))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001086 goto out;
David Ahern7cec0922011-05-30 13:08:23 -06001087
Arnaldo Carvalho de Meloc2740a82016-03-22 18:44:46 -03001088 thread__resolve(thread, &al, sample);
David Ahern7cec0922011-05-30 13:08:23 -06001089
1090 if (PRINT_FIELD(SYM)) {
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001091 printed += fprintf(fp, " ");
Akihiro Nagaia978f2a2012-01-30 13:43:15 +09001092 if (PRINT_FIELD(SYMOFFSET))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001093 printed += symbol__fprintf_symname_offs(al.sym, &al, fp);
Akihiro Nagaia978f2a2012-01-30 13:43:15 +09001094 else
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001095 printed += symbol__fprintf_symname(al.sym, fp);
David Ahern7cec0922011-05-30 13:08:23 -06001096 }
1097
1098 if (PRINT_FIELD(DSO)) {
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001099 printed += fprintf(fp, " (");
1100 printed += map__fprintf_dsoname(al.map, fp);
1101 printed += fprintf(fp, ")");
David Ahern7cec0922011-05-30 13:08:23 -06001102 }
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001103out:
1104 return printed;
David Ahern7cec0922011-05-30 13:08:23 -06001105}
1106
Andi Kleen99f753f2018-09-20 11:05:39 -07001107static const char *resolve_branch_sym(struct perf_sample *sample,
1108 struct perf_evsel *evsel,
1109 struct thread *thread,
1110 struct addr_location *al,
1111 u64 *ip)
1112{
1113 struct addr_location addr_al;
1114 struct perf_event_attr *attr = &evsel->attr;
1115 const char *name = NULL;
1116
1117 if (sample->flags & (PERF_IP_FLAG_CALL | PERF_IP_FLAG_TRACE_BEGIN)) {
1118 if (sample_addr_correlates_sym(attr)) {
1119 thread__resolve(thread, &addr_al, sample);
1120 if (addr_al.sym)
1121 name = addr_al.sym->name;
1122 else
1123 *ip = sample->addr;
1124 } else {
1125 *ip = sample->addr;
1126 }
1127 } else if (sample->flags & (PERF_IP_FLAG_RETURN | PERF_IP_FLAG_TRACE_END)) {
1128 if (al->sym)
1129 name = al->sym->name;
1130 else
1131 *ip = sample->ip;
1132 }
1133 return name;
1134}
1135
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001136static int perf_sample__fprintf_callindent(struct perf_sample *sample,
1137 struct perf_evsel *evsel,
1138 struct thread *thread,
1139 struct addr_location *al, FILE *fp)
Adrian Huntere2167082016-06-23 16:40:58 +03001140{
1141 struct perf_event_attr *attr = &evsel->attr;
1142 size_t depth = thread_stack__depth(thread);
Adrian Huntere2167082016-06-23 16:40:58 +03001143 const char *name = NULL;
1144 static int spacing;
1145 int len = 0;
Andi Kleena78cdee2018-09-18 05:32:10 -07001146 int dlen = 0;
Adrian Huntere2167082016-06-23 16:40:58 +03001147 u64 ip = 0;
1148
1149 /*
1150 * The 'return' has already been popped off the stack so the depth has
1151 * to be adjusted to match the 'call'.
1152 */
1153 if (thread->ts && sample->flags & PERF_IP_FLAG_RETURN)
1154 depth += 1;
1155
Andi Kleen99f753f2018-09-20 11:05:39 -07001156 name = resolve_branch_sym(sample, evsel, thread, al, &ip);
Adrian Huntere2167082016-06-23 16:40:58 +03001157
Andi Kleena78cdee2018-09-18 05:32:10 -07001158 if (PRINT_FIELD(DSO) && !(PRINT_FIELD(IP) || PRINT_FIELD(ADDR))) {
1159 dlen += fprintf(fp, "(");
1160 dlen += map__fprintf_dsoname(al->map, fp);
1161 dlen += fprintf(fp, ")\t");
1162 }
1163
Adrian Huntere2167082016-06-23 16:40:58 +03001164 if (name)
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001165 len = fprintf(fp, "%*s%s", (int)depth * 4, "", name);
Adrian Huntere2167082016-06-23 16:40:58 +03001166 else if (ip)
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001167 len = fprintf(fp, "%*s%16" PRIx64, (int)depth * 4, "", ip);
Adrian Huntere2167082016-06-23 16:40:58 +03001168
1169 if (len < 0)
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001170 return len;
Adrian Huntere2167082016-06-23 16:40:58 +03001171
1172 /*
1173 * Try to keep the output length from changing frequently so that the
1174 * output lines up more nicely.
1175 */
1176 if (len > spacing || (len && len < spacing - 52))
1177 spacing = round_up(len + 4, 32);
1178
1179 if (len < spacing)
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001180 len += fprintf(fp, "%*s", spacing - len, "");
1181
Andi Kleena78cdee2018-09-18 05:32:10 -07001182 return len + dlen;
Adrian Huntere2167082016-06-23 16:40:58 +03001183}
1184
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001185static int perf_sample__fprintf_insn(struct perf_sample *sample,
1186 struct perf_event_attr *attr,
1187 struct thread *thread,
1188 struct machine *machine, FILE *fp)
Andi Kleen224e2c92016-10-07 16:42:27 +03001189{
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001190 int printed = 0;
1191
Andi Kleen224e2c92016-10-07 16:42:27 +03001192 if (PRINT_FIELD(INSNLEN))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001193 printed += fprintf(fp, " ilen: %d", sample->insn_len);
Andi Kleen224e2c92016-10-07 16:42:27 +03001194 if (PRINT_FIELD(INSN)) {
1195 int i;
1196
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001197 printed += fprintf(fp, " insn:");
Andi Kleen224e2c92016-10-07 16:42:27 +03001198 for (i = 0; i < sample->insn_len; i++)
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001199 printed += fprintf(fp, " %02x", (unsigned char)sample->insn[i]);
Andi Kleen224e2c92016-10-07 16:42:27 +03001200 }
Andi Kleen48d02a12017-02-23 15:46:34 -08001201 if (PRINT_FIELD(BRSTACKINSN))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001202 printed += perf_sample__fprintf_brstackinsn(sample, thread, attr, machine, fp);
1203
1204 return printed;
Andi Kleen224e2c92016-10-07 16:42:27 +03001205}
1206
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001207static int perf_sample__fprintf_bts(struct perf_sample *sample,
1208 struct perf_evsel *evsel,
1209 struct thread *thread,
1210 struct addr_location *al,
1211 struct machine *machine, FILE *fp)
Akihiro Nagai95582592012-01-30 13:43:09 +09001212{
1213 struct perf_event_attr *attr = &evsel->attr;
Adrian Hunter14057202017-06-21 13:17:19 +03001214 unsigned int type = output_type(attr->type);
Adrian Hunter8066be5f2014-07-22 16:17:15 +03001215 bool print_srcline_last = false;
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001216 int printed = 0;
Akihiro Nagai95582592012-01-30 13:43:09 +09001217
Adrian Huntere2167082016-06-23 16:40:58 +03001218 if (PRINT_FIELD(CALLINDENT))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001219 printed += perf_sample__fprintf_callindent(sample, evsel, thread, al, fp);
Adrian Huntere2167082016-06-23 16:40:58 +03001220
Akihiro Nagai95582592012-01-30 13:43:09 +09001221 /* print branch_from information */
1222 if (PRINT_FIELD(IP)) {
Adrian Hunter14057202017-06-21 13:17:19 +03001223 unsigned int print_opts = output[type].print_ip_opts;
Chris Phlipote557b672016-04-19 19:32:11 -07001224 struct callchain_cursor *cursor = NULL;
Adrian Hunter8066be5f2014-07-22 16:17:15 +03001225
Arnaldo Carvalho de Melo6f736732016-04-14 17:45:51 -03001226 if (symbol_conf.use_callchain && sample->callchain &&
Chris Phlipote557b672016-04-19 19:32:11 -07001227 thread__resolve_callchain(al->thread, &callchain_cursor, evsel,
Arnaldo Carvalho de Melo6f736732016-04-14 17:45:51 -03001228 sample, NULL, NULL, scripting_max_stack) == 0)
Chris Phlipote557b672016-04-19 19:32:11 -07001229 cursor = &callchain_cursor;
Arnaldo Carvalho de Melo6f736732016-04-14 17:45:51 -03001230
1231 if (cursor == NULL) {
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001232 printed += fprintf(fp, " ");
Arnaldo Carvalho de Meloe20ab862016-04-12 15:16:15 -03001233 if (print_opts & EVSEL__PRINT_SRCLINE) {
Adrian Hunter8066be5f2014-07-22 16:17:15 +03001234 print_srcline_last = true;
Arnaldo Carvalho de Meloe20ab862016-04-12 15:16:15 -03001235 print_opts &= ~EVSEL__PRINT_SRCLINE;
Adrian Hunter8066be5f2014-07-22 16:17:15 +03001236 }
Arnaldo Carvalho de Melo6f736732016-04-14 17:45:51 -03001237 } else
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001238 printed += fprintf(fp, "\n");
Arnaldo Carvalho de Melo6f736732016-04-14 17:45:51 -03001239
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001240 printed += sample__fprintf_sym(sample, al, 0, print_opts, cursor, fp);
Akihiro Nagai95582592012-01-30 13:43:09 +09001241 }
1242
Akihiro Nagai95582592012-01-30 13:43:09 +09001243 /* print branch_to information */
Adrian Hunter243be3d2013-10-18 15:29:14 +03001244 if (PRINT_FIELD(ADDR) ||
1245 ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) &&
Adrian Hunter14057202017-06-21 13:17:19 +03001246 !output[type].user_set)) {
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001247 printed += fprintf(fp, " => ");
1248 printed += perf_sample__fprintf_addr(sample, thread, attr, fp);
Adrian Hunter578bea42014-07-22 16:17:16 +03001249 }
Akihiro Nagai95582592012-01-30 13:43:09 +09001250
Adrian Hunter8066be5f2014-07-22 16:17:15 +03001251 if (print_srcline_last)
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001252 printed += map__fprintf_srcline(al->map, al->addr, "\n ", fp);
Adrian Hunter8066be5f2014-07-22 16:17:15 +03001253
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001254 printed += perf_sample__fprintf_insn(sample, attr, thread, machine, fp);
1255 return printed + fprintf(fp, "\n");
Akihiro Nagai95582592012-01-30 13:43:09 +09001256}
1257
Adrian Hunter055cd332016-06-23 16:40:56 +03001258static struct {
1259 u32 flags;
1260 const char *name;
1261} sample_flags[] = {
1262 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL, "call"},
1263 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN, "return"},
1264 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CONDITIONAL, "jcc"},
1265 {PERF_IP_FLAG_BRANCH, "jmp"},
1266 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_INTERRUPT, "int"},
1267 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN | PERF_IP_FLAG_INTERRUPT, "iret"},
1268 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_SYSCALLRET, "syscall"},
1269 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN | PERF_IP_FLAG_SYSCALLRET, "sysret"},
1270 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_ASYNC, "async"},
1271 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_ASYNC | PERF_IP_FLAG_INTERRUPT, "hw int"},
1272 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TX_ABORT, "tx abrt"},
1273 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TRACE_BEGIN, "tr strt"},
1274 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TRACE_END, "tr end"},
1275 {0, NULL}
1276};
1277
Adrian Hunter62cb1b82018-09-20 16:00:43 +03001278static const char *sample_flags_to_name(u32 flags)
1279{
1280 int i;
1281
1282 for (i = 0; sample_flags[i].name ; i++) {
1283 if (sample_flags[i].flags == flags)
1284 return sample_flags[i].name;
1285 }
1286
1287 return NULL;
1288}
1289
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001290static int perf_sample__fprintf_flags(u32 flags, FILE *fp)
Adrian Hunter400ea6d2015-04-09 18:54:05 +03001291{
1292 const char *chars = PERF_IP_FLAG_CHARS;
1293 const int n = strlen(PERF_IP_FLAG_CHARS);
Adrian Hunter055cd332016-06-23 16:40:56 +03001294 bool in_tx = flags & PERF_IP_FLAG_IN_TX;
1295 const char *name = NULL;
Adrian Hunter400ea6d2015-04-09 18:54:05 +03001296 char str[33];
1297 int i, pos = 0;
1298
Adrian Hunter62cb1b82018-09-20 16:00:43 +03001299 name = sample_flags_to_name(flags & ~PERF_IP_FLAG_IN_TX);
1300 if (name)
1301 return fprintf(fp, " %-15s%4s ", name, in_tx ? "(x)" : "");
1302
1303 if (flags & PERF_IP_FLAG_TRACE_BEGIN) {
1304 name = sample_flags_to_name(flags & ~(PERF_IP_FLAG_IN_TX | PERF_IP_FLAG_TRACE_BEGIN));
1305 if (name)
1306 return fprintf(fp, " tr strt %-7s%4s ", name, in_tx ? "(x)" : "");
1307 }
1308
1309 if (flags & PERF_IP_FLAG_TRACE_END) {
1310 name = sample_flags_to_name(flags & ~(PERF_IP_FLAG_IN_TX | PERF_IP_FLAG_TRACE_END));
1311 if (name)
1312 return fprintf(fp, " tr end %-7s%4s ", name, in_tx ? "(x)" : "");
Adrian Hunter055cd332016-06-23 16:40:56 +03001313 }
1314
Adrian Hunter400ea6d2015-04-09 18:54:05 +03001315 for (i = 0; i < n; i++, flags >>= 1) {
1316 if (flags & 1)
1317 str[pos++] = chars[i];
1318 }
1319 for (; i < 32; i++, flags >>= 1) {
1320 if (flags & 1)
1321 str[pos++] = '?';
1322 }
1323 str[pos] = 0;
Adrian Hunter055cd332016-06-23 16:40:56 +03001324
Adrian Hunter62cb1b82018-09-20 16:00:43 +03001325 return fprintf(fp, " %-19s ", str);
Adrian Hunter400ea6d2015-04-09 18:54:05 +03001326}
1327
Wang Nan30372f02016-02-24 11:20:45 +00001328struct printer_data {
1329 int line_no;
1330 bool hit_nul;
1331 bool is_printable;
1332};
1333
Arnaldo Carvalho de Melo923d0c92017-10-17 10:35:00 -03001334static int sample__fprintf_bpf_output(enum binary_printer_ops op,
1335 unsigned int val,
1336 void *extra, FILE *fp)
Wang Nan30372f02016-02-24 11:20:45 +00001337{
1338 unsigned char ch = (unsigned char)val;
1339 struct printer_data *printer_data = extra;
Arnaldo Carvalho de Melo923d0c92017-10-17 10:35:00 -03001340 int printed = 0;
Wang Nan30372f02016-02-24 11:20:45 +00001341
1342 switch (op) {
1343 case BINARY_PRINT_DATA_BEGIN:
Arnaldo Carvalho de Melo923d0c92017-10-17 10:35:00 -03001344 printed += fprintf(fp, "\n");
Wang Nan30372f02016-02-24 11:20:45 +00001345 break;
1346 case BINARY_PRINT_LINE_BEGIN:
Arnaldo Carvalho de Melo923d0c92017-10-17 10:35:00 -03001347 printed += fprintf(fp, "%17s", !printer_data->line_no ? "BPF output:" :
Wang Nan30372f02016-02-24 11:20:45 +00001348 " ");
1349 break;
1350 case BINARY_PRINT_ADDR:
Arnaldo Carvalho de Melo923d0c92017-10-17 10:35:00 -03001351 printed += fprintf(fp, " %04x:", val);
Wang Nan30372f02016-02-24 11:20:45 +00001352 break;
1353 case BINARY_PRINT_NUM_DATA:
Arnaldo Carvalho de Melo923d0c92017-10-17 10:35:00 -03001354 printed += fprintf(fp, " %02x", val);
Wang Nan30372f02016-02-24 11:20:45 +00001355 break;
1356 case BINARY_PRINT_NUM_PAD:
Arnaldo Carvalho de Melo923d0c92017-10-17 10:35:00 -03001357 printed += fprintf(fp, " ");
Wang Nan30372f02016-02-24 11:20:45 +00001358 break;
1359 case BINARY_PRINT_SEP:
Arnaldo Carvalho de Melo923d0c92017-10-17 10:35:00 -03001360 printed += fprintf(fp, " ");
Wang Nan30372f02016-02-24 11:20:45 +00001361 break;
1362 case BINARY_PRINT_CHAR_DATA:
1363 if (printer_data->hit_nul && ch)
1364 printer_data->is_printable = false;
1365
1366 if (!isprint(ch)) {
Arnaldo Carvalho de Melo923d0c92017-10-17 10:35:00 -03001367 printed += fprintf(fp, "%c", '.');
Wang Nan30372f02016-02-24 11:20:45 +00001368
1369 if (!printer_data->is_printable)
1370 break;
1371
1372 if (ch == '\0')
1373 printer_data->hit_nul = true;
1374 else
1375 printer_data->is_printable = false;
1376 } else {
Arnaldo Carvalho de Melo923d0c92017-10-17 10:35:00 -03001377 printed += fprintf(fp, "%c", ch);
Wang Nan30372f02016-02-24 11:20:45 +00001378 }
1379 break;
1380 case BINARY_PRINT_CHAR_PAD:
Arnaldo Carvalho de Melo923d0c92017-10-17 10:35:00 -03001381 printed += fprintf(fp, " ");
Wang Nan30372f02016-02-24 11:20:45 +00001382 break;
1383 case BINARY_PRINT_LINE_END:
Arnaldo Carvalho de Melo923d0c92017-10-17 10:35:00 -03001384 printed += fprintf(fp, "\n");
Wang Nan30372f02016-02-24 11:20:45 +00001385 printer_data->line_no++;
1386 break;
1387 case BINARY_PRINT_DATA_END:
1388 default:
1389 break;
1390 }
Arnaldo Carvalho de Melo923d0c92017-10-17 10:35:00 -03001391
1392 return printed;
Wang Nan30372f02016-02-24 11:20:45 +00001393}
1394
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001395static int perf_sample__fprintf_bpf_output(struct perf_sample *sample, FILE *fp)
Wang Nan30372f02016-02-24 11:20:45 +00001396{
1397 unsigned int nr_bytes = sample->raw_size;
1398 struct printer_data printer_data = {0, false, true};
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001399 int printed = binary__fprintf(sample->raw_data, nr_bytes, 8,
1400 sample__fprintf_bpf_output, &printer_data, fp);
Wang Nan30372f02016-02-24 11:20:45 +00001401
1402 if (printer_data.is_printable && printer_data.hit_nul)
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001403 printed += fprintf(fp, "%17s \"%s\"\n", "BPF string:", (char *)(sample->raw_data));
1404
1405 return printed;
Wang Nan30372f02016-02-24 11:20:45 +00001406}
1407
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001408static int perf_sample__fprintf_spacing(int len, int spacing, FILE *fp)
Adrian Hunter65c5e182017-06-30 11:36:42 +03001409{
1410 if (len > 0 && len < spacing)
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001411 return fprintf(fp, "%*s", spacing - len, "");
1412
1413 return 0;
Adrian Hunter65c5e182017-06-30 11:36:42 +03001414}
1415
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001416static int perf_sample__fprintf_pt_spacing(int len, FILE *fp)
Adrian Hunter65c5e182017-06-30 11:36:42 +03001417{
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001418 return perf_sample__fprintf_spacing(len, 34, fp);
Adrian Hunter65c5e182017-06-30 11:36:42 +03001419}
1420
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001421static int perf_sample__fprintf_synth_ptwrite(struct perf_sample *sample, FILE *fp)
Adrian Hunter65c5e182017-06-30 11:36:42 +03001422{
1423 struct perf_synth_intel_ptwrite *data = perf_sample__synth_ptr(sample);
1424 int len;
1425
1426 if (perf_sample__bad_synth_size(sample, *data))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001427 return 0;
Adrian Hunter65c5e182017-06-30 11:36:42 +03001428
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001429 len = fprintf(fp, " IP: %u payload: %#" PRIx64 " ",
Adrian Hunter65c5e182017-06-30 11:36:42 +03001430 data->ip, le64_to_cpu(data->payload));
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001431 return len + perf_sample__fprintf_pt_spacing(len, fp);
Adrian Hunter65c5e182017-06-30 11:36:42 +03001432}
1433
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001434static int perf_sample__fprintf_synth_mwait(struct perf_sample *sample, FILE *fp)
Adrian Hunter65c5e182017-06-30 11:36:42 +03001435{
1436 struct perf_synth_intel_mwait *data = perf_sample__synth_ptr(sample);
1437 int len;
1438
1439 if (perf_sample__bad_synth_size(sample, *data))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001440 return 0;
Adrian Hunter65c5e182017-06-30 11:36:42 +03001441
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001442 len = fprintf(fp, " hints: %#x extensions: %#x ",
1443 data->hints, data->extensions);
1444 return len + perf_sample__fprintf_pt_spacing(len, fp);
Adrian Hunter65c5e182017-06-30 11:36:42 +03001445}
1446
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001447static int perf_sample__fprintf_synth_pwre(struct perf_sample *sample, FILE *fp)
Adrian Hunter65c5e182017-06-30 11:36:42 +03001448{
1449 struct perf_synth_intel_pwre *data = perf_sample__synth_ptr(sample);
1450 int len;
1451
1452 if (perf_sample__bad_synth_size(sample, *data))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001453 return 0;
Adrian Hunter65c5e182017-06-30 11:36:42 +03001454
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001455 len = fprintf(fp, " hw: %u cstate: %u sub-cstate: %u ",
1456 data->hw, data->cstate, data->subcstate);
1457 return len + perf_sample__fprintf_pt_spacing(len, fp);
Adrian Hunter65c5e182017-06-30 11:36:42 +03001458}
1459
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001460static int perf_sample__fprintf_synth_exstop(struct perf_sample *sample, FILE *fp)
Adrian Hunter65c5e182017-06-30 11:36:42 +03001461{
1462 struct perf_synth_intel_exstop *data = perf_sample__synth_ptr(sample);
1463 int len;
1464
1465 if (perf_sample__bad_synth_size(sample, *data))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001466 return 0;
Adrian Hunter65c5e182017-06-30 11:36:42 +03001467
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001468 len = fprintf(fp, " IP: %u ", data->ip);
1469 return len + perf_sample__fprintf_pt_spacing(len, fp);
Adrian Hunter65c5e182017-06-30 11:36:42 +03001470}
1471
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001472static int perf_sample__fprintf_synth_pwrx(struct perf_sample *sample, FILE *fp)
Adrian Hunter65c5e182017-06-30 11:36:42 +03001473{
1474 struct perf_synth_intel_pwrx *data = perf_sample__synth_ptr(sample);
1475 int len;
1476
1477 if (perf_sample__bad_synth_size(sample, *data))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001478 return 0;
Adrian Hunter65c5e182017-06-30 11:36:42 +03001479
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001480 len = fprintf(fp, " deepest cstate: %u last cstate: %u wake reason: %#x ",
Adrian Hunter65c5e182017-06-30 11:36:42 +03001481 data->deepest_cstate, data->last_cstate,
1482 data->wake_reason);
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001483 return len + perf_sample__fprintf_pt_spacing(len, fp);
Adrian Hunter65c5e182017-06-30 11:36:42 +03001484}
1485
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001486static int perf_sample__fprintf_synth_cbr(struct perf_sample *sample, FILE *fp)
Adrian Hunter65c5e182017-06-30 11:36:42 +03001487{
1488 struct perf_synth_intel_cbr *data = perf_sample__synth_ptr(sample);
1489 unsigned int percent, freq;
1490 int len;
1491
1492 if (perf_sample__bad_synth_size(sample, *data))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001493 return 0;
Adrian Hunter65c5e182017-06-30 11:36:42 +03001494
1495 freq = (le32_to_cpu(data->freq) + 500) / 1000;
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001496 len = fprintf(fp, " cbr: %2u freq: %4u MHz ", data->cbr, freq);
Adrian Hunter65c5e182017-06-30 11:36:42 +03001497 if (data->max_nonturbo) {
1498 percent = (5 + (1000 * data->cbr) / data->max_nonturbo) / 10;
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001499 len += fprintf(fp, "(%3u%%) ", percent);
Adrian Hunter65c5e182017-06-30 11:36:42 +03001500 }
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001501 return len + perf_sample__fprintf_pt_spacing(len, fp);
Adrian Hunter65c5e182017-06-30 11:36:42 +03001502}
1503
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001504static int perf_sample__fprintf_synth(struct perf_sample *sample,
1505 struct perf_evsel *evsel, FILE *fp)
Adrian Hunter47e78082017-05-26 11:17:22 +03001506{
1507 switch (evsel->attr.config) {
Adrian Hunter65c5e182017-06-30 11:36:42 +03001508 case PERF_SYNTH_INTEL_PTWRITE:
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001509 return perf_sample__fprintf_synth_ptwrite(sample, fp);
Adrian Hunter65c5e182017-06-30 11:36:42 +03001510 case PERF_SYNTH_INTEL_MWAIT:
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001511 return perf_sample__fprintf_synth_mwait(sample, fp);
Adrian Hunter65c5e182017-06-30 11:36:42 +03001512 case PERF_SYNTH_INTEL_PWRE:
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001513 return perf_sample__fprintf_synth_pwre(sample, fp);
Adrian Hunter65c5e182017-06-30 11:36:42 +03001514 case PERF_SYNTH_INTEL_EXSTOP:
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001515 return perf_sample__fprintf_synth_exstop(sample, fp);
Adrian Hunter65c5e182017-06-30 11:36:42 +03001516 case PERF_SYNTH_INTEL_PWRX:
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001517 return perf_sample__fprintf_synth_pwrx(sample, fp);
Adrian Hunter65c5e182017-06-30 11:36:42 +03001518 case PERF_SYNTH_INTEL_CBR:
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001519 return perf_sample__fprintf_synth_cbr(sample, fp);
Adrian Hunter47e78082017-05-26 11:17:22 +03001520 default:
1521 break;
1522 }
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001523
1524 return 0;
Adrian Hunter47e78082017-05-26 11:17:22 +03001525}
1526
Jiri Olsa809e9422015-11-26 18:55:21 +01001527struct perf_script {
1528 struct perf_tool tool;
1529 struct perf_session *session;
1530 bool show_task_events;
1531 bool show_mmap_events;
1532 bool show_switch_events;
Hari Bathini96a44bb2017-03-08 02:12:06 +05301533 bool show_namespace_events;
Jiri Olsa3d7c27b2018-01-07 17:03:53 +01001534 bool show_lost_events;
Jiri Olsa3233b372018-02-06 19:17:59 +01001535 bool show_round_events;
Jiri Olsacfc88742016-01-05 22:09:06 +01001536 bool allocated;
Arnaldo Carvalho de Meloa14390f2017-10-26 10:30:20 -03001537 bool per_event_dump;
Jiri Olsacfc88742016-01-05 22:09:06 +01001538 struct cpu_map *cpus;
1539 struct thread_map *threads;
Jiri Olsa9cdbc402016-01-07 10:14:05 +01001540 int name_width;
David Aherna91f4c42016-11-29 10:15:43 -07001541 const char *time_str;
Jin Yaocc2ef582018-01-10 23:00:33 +08001542 struct perf_time_interval *ptime_range;
1543 int range_size;
Jin Yao2ab046c2017-12-08 21:13:46 +08001544 int range_num;
Jiri Olsa809e9422015-11-26 18:55:21 +01001545};
1546
Jiri Olsa9cdbc402016-01-07 10:14:05 +01001547static int perf_evlist__max_name_len(struct perf_evlist *evlist)
1548{
1549 struct perf_evsel *evsel;
1550 int max = 0;
1551
Arnaldo Carvalho de Meloe5cadb92016-06-23 11:26:15 -03001552 evlist__for_each_entry(evlist, evsel) {
Jiri Olsa9cdbc402016-01-07 10:14:05 +01001553 int len = strlen(perf_evsel__name(evsel));
1554
1555 max = MAX(len, max);
1556 }
1557
1558 return max;
1559}
1560
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001561static int data_src__fprintf(u64 data_src, FILE *fp)
Jiri Olsac19ac912016-02-24 09:46:54 +01001562{
1563 struct mem_info mi = { .data_src.val = data_src };
1564 char decode[100];
1565 char out[100];
1566 static int maxlen;
1567 int len;
1568
1569 perf_script__meminfo_scnprintf(decode, 100, &mi);
1570
1571 len = scnprintf(out, 100, "%16" PRIx64 " %s", data_src, decode);
1572 if (maxlen < len)
1573 maxlen = len;
1574
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001575 return fprintf(fp, "%-*s", maxlen, out);
Jiri Olsac19ac912016-02-24 09:46:54 +01001576}
1577
Andi Kleen4bd1bef2017-11-17 13:43:00 -08001578struct metric_ctx {
1579 struct perf_sample *sample;
1580 struct thread *thread;
1581 struct perf_evsel *evsel;
1582 FILE *fp;
1583};
1584
Jiri Olsa6ca9a082018-08-30 08:32:28 +02001585static void script_print_metric(struct perf_stat_config *config __maybe_unused,
1586 void *ctx, const char *color,
Andi Kleen4bd1bef2017-11-17 13:43:00 -08001587 const char *fmt,
1588 const char *unit, double val)
1589{
1590 struct metric_ctx *mctx = ctx;
1591
1592 if (!fmt)
1593 return;
1594 perf_sample__fprintf_start(mctx->sample, mctx->thread, mctx->evsel,
Jiri Olsa28a0b392018-01-07 17:03:52 +01001595 PERF_RECORD_SAMPLE, mctx->fp);
Andi Kleen4bd1bef2017-11-17 13:43:00 -08001596 fputs("\tmetric: ", mctx->fp);
1597 if (color)
1598 color_fprintf(mctx->fp, color, fmt, val);
1599 else
1600 printf(fmt, val);
1601 fprintf(mctx->fp, " %s\n", unit);
1602}
1603
Jiri Olsa6ca9a082018-08-30 08:32:28 +02001604static void script_new_line(struct perf_stat_config *config __maybe_unused,
1605 void *ctx)
Andi Kleen4bd1bef2017-11-17 13:43:00 -08001606{
1607 struct metric_ctx *mctx = ctx;
1608
1609 perf_sample__fprintf_start(mctx->sample, mctx->thread, mctx->evsel,
Jiri Olsa28a0b392018-01-07 17:03:52 +01001610 PERF_RECORD_SAMPLE, mctx->fp);
Andi Kleen4bd1bef2017-11-17 13:43:00 -08001611 fputs("\tmetric: ", mctx->fp);
1612}
1613
1614static void perf_sample__fprint_metric(struct perf_script *script,
1615 struct thread *thread,
1616 struct perf_evsel *evsel,
1617 struct perf_sample *sample,
1618 FILE *fp)
1619{
1620 struct perf_stat_output_ctx ctx = {
1621 .print_metric = script_print_metric,
1622 .new_line = script_new_line,
1623 .ctx = &(struct metric_ctx) {
1624 .sample = sample,
1625 .thread = thread,
1626 .evsel = evsel,
1627 .fp = fp,
1628 },
1629 .force_header = false,
1630 };
1631 struct perf_evsel *ev2;
1632 static bool init;
1633 u64 val;
1634
1635 if (!init) {
1636 perf_stat__init_shadow_stats();
1637 init = true;
1638 }
1639 if (!evsel->stats)
1640 perf_evlist__alloc_stats(script->session->evlist, false);
1641 if (evsel_script(evsel->leader)->gnum++ == 0)
1642 perf_stat__reset_shadow_stats();
1643 val = sample->period * evsel->scale;
1644 perf_stat__update_shadow_stats(evsel,
1645 val,
Jin Yao1fcd0392017-12-05 22:03:04 +08001646 sample->cpu,
1647 &rt_stat);
Andi Kleen4bd1bef2017-11-17 13:43:00 -08001648 evsel_script(evsel)->val = val;
1649 if (evsel_script(evsel->leader)->gnum == evsel->leader->nr_members) {
1650 for_each_group_member (ev2, evsel->leader) {
Jiri Olsa6ca9a082018-08-30 08:32:28 +02001651 perf_stat__print_shadow_stats(&stat_config, ev2,
Andi Kleen4bd1bef2017-11-17 13:43:00 -08001652 evsel_script(ev2)->val,
1653 sample->cpu,
1654 &ctx,
Jin Yaoe0128b32017-12-05 22:03:05 +08001655 NULL,
1656 &rt_stat);
Andi Kleen4bd1bef2017-11-17 13:43:00 -08001657 }
1658 evsel_script(evsel->leader)->gnum = 0;
1659 }
1660}
1661
Andi Kleen99f753f2018-09-20 11:05:39 -07001662static bool show_event(struct perf_sample *sample,
1663 struct perf_evsel *evsel,
1664 struct thread *thread,
1665 struct addr_location *al)
1666{
1667 int depth = thread_stack__depth(thread);
1668
1669 if (!symbol_conf.graph_function)
1670 return true;
1671
1672 if (thread->filter) {
1673 if (depth <= thread->filter_entry_depth) {
1674 thread->filter = false;
1675 return false;
1676 }
1677 return true;
1678 } else {
1679 const char *s = symbol_conf.graph_function;
1680 u64 ip;
1681 const char *name = resolve_branch_sym(sample, evsel, thread, al,
1682 &ip);
1683 unsigned nlen;
1684
1685 if (!name)
1686 return false;
1687 nlen = strlen(name);
1688 while (*s) {
1689 unsigned len = strcspn(s, ",");
1690 if (nlen == len && !strncmp(name, s, len)) {
1691 thread->filter = true;
1692 thread->filter_entry_depth = depth;
1693 return true;
1694 }
1695 s += len;
1696 if (*s == ',')
1697 s++;
1698 }
1699 return false;
1700 }
1701}
1702
Arnaldo Carvalho de Meloa3dff302016-03-23 11:55:24 -03001703static void process_event(struct perf_script *script,
Jiri Olsa809e9422015-11-26 18:55:21 +01001704 struct perf_sample *sample, struct perf_evsel *evsel,
Andi Kleen48d02a12017-02-23 15:46:34 -08001705 struct addr_location *al,
1706 struct machine *machine)
David Ahernbe6d8422011-03-09 22:23:23 -07001707{
Arnaldo Carvalho de Melof9d5d542015-04-01 13:29:25 -03001708 struct thread *thread = al->thread;
Arnaldo Carvalho de Melo9e69c212011-03-15 15:44:01 -03001709 struct perf_event_attr *attr = &evsel->attr;
Adrian Hunter14057202017-06-21 13:17:19 +03001710 unsigned int type = output_type(attr->type);
Arnaldo Carvalho de Melo642ee1c2017-10-30 13:11:15 -03001711 struct perf_evsel_script *es = evsel->priv;
1712 FILE *fp = es->fp;
David Ahern1424dc92011-03-09 22:23:28 -07001713
Adrian Hunter14057202017-06-21 13:17:19 +03001714 if (output[type].fields == 0)
David Ahern1424dc92011-03-09 22:23:28 -07001715 return;
1716
Andi Kleen99f753f2018-09-20 11:05:39 -07001717 if (!show_event(sample, evsel, thread, al))
1718 return;
1719
Arnaldo Carvalho de Melo642ee1c2017-10-30 13:11:15 -03001720 ++es->samples;
1721
Jiri Olsa28a0b392018-01-07 17:03:52 +01001722 perf_sample__fprintf_start(sample, thread, evsel,
1723 PERF_RECORD_SAMPLE, fp);
David Ahern745f43e2011-03-09 22:23:26 -07001724
Jiri Olsa535aeaae2014-08-25 16:45:42 +02001725 if (PRINT_FIELD(PERIOD))
Arnaldo Carvalho de Melo69c71252017-10-26 09:51:13 -03001726 fprintf(fp, "%10" PRIu64 " ", sample->period);
Jiri Olsa535aeaae2014-08-25 16:45:42 +02001727
Namhyung Kime944d3d2013-11-18 14:34:52 +09001728 if (PRINT_FIELD(EVNAME)) {
1729 const char *evname = perf_evsel__name(evsel);
Jiri Olsa9cdbc402016-01-07 10:14:05 +01001730
1731 if (!script->name_width)
1732 script->name_width = perf_evlist__max_name_len(script->session->evlist);
1733
Arnaldo Carvalho de Melo69c71252017-10-26 09:51:13 -03001734 fprintf(fp, "%*s: ", script->name_width, evname ?: "[unknown]");
Namhyung Kime944d3d2013-11-18 14:34:52 +09001735 }
1736
Adrian Hunter400ea6d2015-04-09 18:54:05 +03001737 if (print_flags)
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001738 perf_sample__fprintf_flags(sample->flags, fp);
Adrian Hunter400ea6d2015-04-09 18:54:05 +03001739
Akihiro Nagai95582592012-01-30 13:43:09 +09001740 if (is_bts_event(attr)) {
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001741 perf_sample__fprintf_bts(sample, evsel, thread, al, machine, fp);
Akihiro Nagai95582592012-01-30 13:43:09 +09001742 return;
1743 }
1744
Arnaldo Carvalho de Melo894f3f12017-10-26 10:26:52 -03001745 if (PRINT_FIELD(TRACE)) {
1746 event_format__fprintf(evsel->tp_format, sample->cpu,
1747 sample->raw_data, sample->raw_size, fp);
1748 }
Adrian Hunter47e78082017-05-26 11:17:22 +03001749
1750 if (attr->type == PERF_TYPE_SYNTH && PRINT_FIELD(SYNTH))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001751 perf_sample__fprintf_synth(sample, evsel, fp);
Adrian Hunter47e78082017-05-26 11:17:22 +03001752
David Ahern7cec0922011-05-30 13:08:23 -06001753 if (PRINT_FIELD(ADDR))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001754 perf_sample__fprintf_addr(sample, thread, attr, fp);
David Ahern7cec0922011-05-30 13:08:23 -06001755
Jiri Olsa94ddddf2016-02-15 09:34:51 +01001756 if (PRINT_FIELD(DATA_SRC))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001757 data_src__fprintf(sample->data_src, fp);
Jiri Olsa94ddddf2016-02-15 09:34:51 +01001758
1759 if (PRINT_FIELD(WEIGHT))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001760 fprintf(fp, "%16" PRIu64, sample->weight);
Jiri Olsa94ddddf2016-02-15 09:34:51 +01001761
David Ahern787bef12011-05-27 14:28:43 -06001762 if (PRINT_FIELD(IP)) {
Chris Phlipote557b672016-04-19 19:32:11 -07001763 struct callchain_cursor *cursor = NULL;
David Aherna6ffaf92013-08-07 22:50:51 -04001764
Arnaldo Carvalho de Melo92231522016-04-18 11:31:46 -03001765 if (symbol_conf.use_callchain && sample->callchain &&
Chris Phlipote557b672016-04-19 19:32:11 -07001766 thread__resolve_callchain(al->thread, &callchain_cursor, evsel,
Arnaldo Carvalho de Melo6f736732016-04-14 17:45:51 -03001767 sample, NULL, NULL, scripting_max_stack) == 0)
Chris Phlipote557b672016-04-19 19:32:11 -07001768 cursor = &callchain_cursor;
Arnaldo Carvalho de Melo6f736732016-04-14 17:45:51 -03001769
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001770 fputc(cursor ? '\n' : ' ', fp);
1771 sample__fprintf_sym(sample, al, 0, output[type].print_ip_opts, cursor, fp);
David Ahernc0230b22011-03-09 22:23:27 -07001772 }
1773
Stephane Eranianfc36f942015-08-31 18:41:10 +02001774 if (PRINT_FIELD(IREGS))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001775 perf_sample__fprintf_iregs(sample, attr, fp);
Stephane Eranianfc36f942015-08-31 18:41:10 +02001776
Andi Kleenb1491ac2017-09-05 11:40:57 -07001777 if (PRINT_FIELD(UREGS))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001778 perf_sample__fprintf_uregs(sample, attr, fp);
Andi Kleenb1491ac2017-09-05 11:40:57 -07001779
Stephane Eraniandc323ce2015-08-31 18:41:13 +02001780 if (PRINT_FIELD(BRSTACK))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001781 perf_sample__fprintf_brstack(sample, thread, attr, fp);
Stephane Eraniandc323ce2015-08-31 18:41:13 +02001782 else if (PRINT_FIELD(BRSTACKSYM))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001783 perf_sample__fprintf_brstacksym(sample, thread, attr, fp);
Mark Santaniello106dacd2017-06-19 09:38:25 -07001784 else if (PRINT_FIELD(BRSTACKOFF))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001785 perf_sample__fprintf_brstackoff(sample, thread, attr, fp);
Stephane Eraniandc323ce2015-08-31 18:41:13 +02001786
Wang Nan30372f02016-02-24 11:20:45 +00001787 if (perf_evsel__is_bpf_output(evsel) && PRINT_FIELD(BPF_OUTPUT))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001788 perf_sample__fprintf_bpf_output(sample, fp);
1789 perf_sample__fprintf_insn(sample, attr, thread, machine, fp);
Kan Liang49d58f02017-08-29 13:11:11 -04001790
1791 if (PRINT_FIELD(PHYS_ADDR))
Arnaldo Carvalho de Melo69c71252017-10-26 09:51:13 -03001792 fprintf(fp, "%16" PRIx64, sample->phys_addr);
1793 fprintf(fp, "\n");
Andi Kleen4bd1bef2017-11-17 13:43:00 -08001794
1795 if (PRINT_FIELD(METRIC))
1796 perf_sample__fprint_metric(script, thread, evsel, sample, fp);
Milian Wolff7ee40672018-10-21 21:14:24 +02001797
1798 if (verbose)
1799 fflush(fp);
David Ahernbe6d8422011-03-09 22:23:23 -07001800}
1801
Tom Zanussi956ffd02009-11-25 01:15:46 -06001802static struct scripting_ops *scripting_ops;
1803
Jiri Olsa36e33c52016-01-06 11:49:56 +01001804static void __process_stat(struct perf_evsel *counter, u64 tstamp)
1805{
1806 int nthreads = thread_map__nr(counter->threads);
1807 int ncpus = perf_evsel__nr_cpus(counter);
1808 int cpu, thread;
1809 static int header_printed;
1810
1811 if (counter->system_wide)
1812 nthreads = 1;
1813
1814 if (!header_printed) {
1815 printf("%3s %8s %15s %15s %15s %15s %s\n",
1816 "CPU", "THREAD", "VAL", "ENA", "RUN", "TIME", "EVENT");
1817 header_printed = 1;
1818 }
1819
1820 for (thread = 0; thread < nthreads; thread++) {
1821 for (cpu = 0; cpu < ncpus; cpu++) {
1822 struct perf_counts_values *counts;
1823
1824 counts = perf_counts(counter->counts, cpu, thread);
1825
1826 printf("%3d %8d %15" PRIu64 " %15" PRIu64 " %15" PRIu64 " %15" PRIu64 " %s\n",
1827 counter->cpus->map[cpu],
1828 thread_map__pid(counter->threads, thread),
1829 counts->val,
1830 counts->ena,
1831 counts->run,
1832 tstamp,
1833 perf_evsel__name(counter));
1834 }
1835 }
1836}
1837
Jiri Olsae099eba2016-01-05 22:09:09 +01001838static void process_stat(struct perf_evsel *counter, u64 tstamp)
1839{
1840 if (scripting_ops && scripting_ops->process_stat)
1841 scripting_ops->process_stat(&stat_config, counter, tstamp);
Jiri Olsa36e33c52016-01-06 11:49:56 +01001842 else
1843 __process_stat(counter, tstamp);
Jiri Olsae099eba2016-01-05 22:09:09 +01001844}
1845
1846static void process_stat_interval(u64 tstamp)
1847{
1848 if (scripting_ops && scripting_ops->process_stat_interval)
1849 scripting_ops->process_stat_interval(tstamp);
1850}
1851
Tom Zanussi956ffd02009-11-25 01:15:46 -06001852static void setup_scripting(void)
1853{
Tom Zanussi16c632d2009-11-25 01:15:48 -06001854 setup_perl_scripting();
Tom Zanussi7e4b21b2010-01-27 02:27:57 -06001855 setup_python_scripting();
Tom Zanussi956ffd02009-11-25 01:15:46 -06001856}
1857
Adrian Hunterd445dd22014-08-15 22:08:37 +03001858static int flush_scripting(void)
1859{
Jiri Olsa2aaecfc2015-11-26 14:55:23 +01001860 return scripting_ops ? scripting_ops->flush_script() : 0;
Adrian Hunterd445dd22014-08-15 22:08:37 +03001861}
1862
Tom Zanussi956ffd02009-11-25 01:15:46 -06001863static int cleanup_scripting(void)
1864{
Ingo Molnar133dc4c2010-11-16 18:45:39 +01001865 pr_debug("\nperf script stopped\n");
Tom Zanussi3824a4e2010-05-09 23:46:57 -05001866
Jiri Olsa2aaecfc2015-11-26 14:55:23 +01001867 return scripting_ops ? scripting_ops->stop_script() : 0;
Tom Zanussi956ffd02009-11-25 01:15:46 -06001868}
1869
Jiri Olsa809e9422015-11-26 18:55:21 +01001870static int process_sample_event(struct perf_tool *tool,
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -02001871 union perf_event *event,
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -02001872 struct perf_sample *sample,
Arnaldo Carvalho de Melo9e69c212011-03-15 15:44:01 -03001873 struct perf_evsel *evsel,
Arnaldo Carvalho de Melo743eb862011-11-28 07:56:39 -02001874 struct machine *machine)
Frederic Weisbecker5f9c39d2009-08-17 16:18:08 +02001875{
Jiri Olsa809e9422015-11-26 18:55:21 +01001876 struct perf_script *scr = container_of(tool, struct perf_script, tool);
David Aherne7984b72011-11-21 10:02:52 -07001877 struct addr_location al;
Frederic Weisbecker5f9c39d2009-08-17 16:18:08 +02001878
Jin Yao2ab046c2017-12-08 21:13:46 +08001879 if (perf_time__ranges_skip_sample(scr->ptime_range, scr->range_num,
1880 sample->time)) {
David Aherna91f4c42016-11-29 10:15:43 -07001881 return 0;
Jin Yao2ab046c2017-12-08 21:13:46 +08001882 }
David Aherna91f4c42016-11-29 10:15:43 -07001883
David Ahern1424dc92011-03-09 22:23:28 -07001884 if (debug_mode) {
1885 if (sample->time < last_timestamp) {
1886 pr_err("Samples misordered, previous: %" PRIu64
1887 " this: %" PRIu64 "\n", last_timestamp,
1888 sample->time);
1889 nr_unordered++;
Frederic Weisbeckere1889d72010-04-24 01:55:09 +02001890 }
David Ahern1424dc92011-03-09 22:23:28 -07001891 last_timestamp = sample->time;
1892 return 0;
Frederic Weisbecker5f9c39d2009-08-17 16:18:08 +02001893 }
Anton Blanchard5d67be92011-07-04 21:57:50 +10001894
Arnaldo Carvalho de Melobb3eb562016-03-22 18:39:09 -03001895 if (machine__resolve(machine, &al, sample) < 0) {
David Aherne7984b72011-11-21 10:02:52 -07001896 pr_err("problem processing %d event, skipping it.\n",
1897 event->header.type);
1898 return -1;
1899 }
1900
1901 if (al.filtered)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001902 goto out_put;
David Aherne7984b72011-11-21 10:02:52 -07001903
Anton Blanchard5d67be92011-07-04 21:57:50 +10001904 if (cpu_list && !test_bit(sample->cpu, cpu_bitmap))
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001905 goto out_put;
Anton Blanchard5d67be92011-07-04 21:57:50 +10001906
Jiri Olsa2aaecfc2015-11-26 14:55:23 +01001907 if (scripting_ops)
1908 scripting_ops->process_event(event, sample, evsel, &al);
1909 else
Andi Kleen48d02a12017-02-23 15:46:34 -08001910 process_event(scr, sample, evsel, &al, machine);
Jiri Olsa2aaecfc2015-11-26 14:55:23 +01001911
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001912out_put:
1913 addr_location__put(&al);
Frederic Weisbecker5f9c39d2009-08-17 16:18:08 +02001914 return 0;
1915}
1916
Adrian Hunter7ea95722013-11-01 15:51:30 +02001917static int process_attr(struct perf_tool *tool, union perf_event *event,
1918 struct perf_evlist **pevlist)
1919{
1920 struct perf_script *scr = container_of(tool, struct perf_script, tool);
1921 struct perf_evlist *evlist;
1922 struct perf_evsel *evsel, *pos;
1923 int err;
Ravi Bangoriaa3af66f2018-06-25 18:12:19 +05301924 static struct perf_evsel_script *es;
Adrian Hunter7ea95722013-11-01 15:51:30 +02001925
1926 err = perf_event__process_attr(tool, event, pevlist);
1927 if (err)
1928 return err;
1929
1930 evlist = *pevlist;
1931 evsel = perf_evlist__last(*pevlist);
1932
Ravi Bangoriaa3af66f2018-06-25 18:12:19 +05301933 if (!evsel->priv) {
1934 if (scr->per_event_dump) {
1935 evsel->priv = perf_evsel_script__new(evsel,
1936 scr->session->data);
1937 } else {
1938 es = zalloc(sizeof(*es));
1939 if (!es)
1940 return -ENOMEM;
1941 es->fp = stdout;
1942 evsel->priv = es;
1943 }
1944 }
1945
Adrian Hunter14057202017-06-21 13:17:19 +03001946 if (evsel->attr.type >= PERF_TYPE_MAX &&
1947 evsel->attr.type != PERF_TYPE_SYNTH)
Adrian Hunter7ea95722013-11-01 15:51:30 +02001948 return 0;
1949
Arnaldo Carvalho de Meloe5cadb92016-06-23 11:26:15 -03001950 evlist__for_each_entry(evlist, pos) {
Adrian Hunter7ea95722013-11-01 15:51:30 +02001951 if (pos->attr.type == evsel->attr.type && pos != evsel)
1952 return 0;
1953 }
1954
1955 set_print_ip_opts(&evsel->attr);
1956
Jiri Olsad2b5a312015-10-16 12:41:25 +02001957 if (evsel->attr.sample_type)
1958 err = perf_evsel__check_attr(evsel, scr->session);
1959
1960 return err;
Adrian Hunter7ea95722013-11-01 15:51:30 +02001961}
1962
Namhyung Kimad7ebb92013-11-26 17:51:12 +09001963static int process_comm_event(struct perf_tool *tool,
1964 union perf_event *event,
1965 struct perf_sample *sample,
1966 struct machine *machine)
1967{
1968 struct thread *thread;
1969 struct perf_script *script = container_of(tool, struct perf_script, tool);
1970 struct perf_session *session = script->session;
Adrian Hunter06b234e2015-07-21 12:44:05 +03001971 struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
Namhyung Kimad7ebb92013-11-26 17:51:12 +09001972 int ret = -1;
1973
1974 thread = machine__findnew_thread(machine, event->comm.pid, event->comm.tid);
1975 if (thread == NULL) {
1976 pr_debug("problem processing COMM event, skipping it.\n");
1977 return -1;
1978 }
1979
1980 if (perf_event__process_comm(tool, event, sample, machine) < 0)
1981 goto out;
1982
1983 if (!evsel->attr.sample_id_all) {
1984 sample->cpu = 0;
1985 sample->time = 0;
1986 sample->tid = event->comm.tid;
1987 sample->pid = event->comm.pid;
1988 }
Jiri Olsa28a0b392018-01-07 17:03:52 +01001989 perf_sample__fprintf_start(sample, thread, evsel,
1990 PERF_RECORD_COMM, stdout);
Namhyung Kimad7ebb92013-11-26 17:51:12 +09001991 perf_event__fprintf(event, stdout);
1992 ret = 0;
Namhyung Kimad7ebb92013-11-26 17:51:12 +09001993out:
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001994 thread__put(thread);
Namhyung Kimad7ebb92013-11-26 17:51:12 +09001995 return ret;
1996}
1997
Hari Bathini96a44bb2017-03-08 02:12:06 +05301998static int process_namespaces_event(struct perf_tool *tool,
1999 union perf_event *event,
2000 struct perf_sample *sample,
2001 struct machine *machine)
2002{
2003 struct thread *thread;
2004 struct perf_script *script = container_of(tool, struct perf_script, tool);
2005 struct perf_session *session = script->session;
2006 struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
2007 int ret = -1;
2008
2009 thread = machine__findnew_thread(machine, event->namespaces.pid,
2010 event->namespaces.tid);
2011 if (thread == NULL) {
2012 pr_debug("problem processing NAMESPACES event, skipping it.\n");
2013 return -1;
2014 }
2015
2016 if (perf_event__process_namespaces(tool, event, sample, machine) < 0)
2017 goto out;
2018
2019 if (!evsel->attr.sample_id_all) {
2020 sample->cpu = 0;
2021 sample->time = 0;
2022 sample->tid = event->namespaces.tid;
2023 sample->pid = event->namespaces.pid;
2024 }
Jiri Olsa28a0b392018-01-07 17:03:52 +01002025 perf_sample__fprintf_start(sample, thread, evsel,
2026 PERF_RECORD_NAMESPACES, stdout);
Hari Bathini96a44bb2017-03-08 02:12:06 +05302027 perf_event__fprintf(event, stdout);
2028 ret = 0;
2029out:
2030 thread__put(thread);
2031 return ret;
2032}
2033
Namhyung Kimad7ebb92013-11-26 17:51:12 +09002034static int process_fork_event(struct perf_tool *tool,
2035 union perf_event *event,
2036 struct perf_sample *sample,
2037 struct machine *machine)
2038{
2039 struct thread *thread;
2040 struct perf_script *script = container_of(tool, struct perf_script, tool);
2041 struct perf_session *session = script->session;
Adrian Hunter06b234e2015-07-21 12:44:05 +03002042 struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
Namhyung Kimad7ebb92013-11-26 17:51:12 +09002043
2044 if (perf_event__process_fork(tool, event, sample, machine) < 0)
2045 return -1;
2046
2047 thread = machine__findnew_thread(machine, event->fork.pid, event->fork.tid);
2048 if (thread == NULL) {
2049 pr_debug("problem processing FORK event, skipping it.\n");
2050 return -1;
2051 }
2052
2053 if (!evsel->attr.sample_id_all) {
2054 sample->cpu = 0;
2055 sample->time = event->fork.time;
2056 sample->tid = event->fork.tid;
2057 sample->pid = event->fork.pid;
2058 }
Jiri Olsa28a0b392018-01-07 17:03:52 +01002059 perf_sample__fprintf_start(sample, thread, evsel,
2060 PERF_RECORD_FORK, stdout);
Namhyung Kimad7ebb92013-11-26 17:51:12 +09002061 perf_event__fprintf(event, stdout);
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002062 thread__put(thread);
Namhyung Kimad7ebb92013-11-26 17:51:12 +09002063
2064 return 0;
2065}
2066static int process_exit_event(struct perf_tool *tool,
2067 union perf_event *event,
2068 struct perf_sample *sample,
2069 struct machine *machine)
2070{
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002071 int err = 0;
Namhyung Kimad7ebb92013-11-26 17:51:12 +09002072 struct thread *thread;
2073 struct perf_script *script = container_of(tool, struct perf_script, tool);
2074 struct perf_session *session = script->session;
Adrian Hunter06b234e2015-07-21 12:44:05 +03002075 struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
Namhyung Kimad7ebb92013-11-26 17:51:12 +09002076
2077 thread = machine__findnew_thread(machine, event->fork.pid, event->fork.tid);
2078 if (thread == NULL) {
2079 pr_debug("problem processing EXIT event, skipping it.\n");
2080 return -1;
2081 }
2082
2083 if (!evsel->attr.sample_id_all) {
2084 sample->cpu = 0;
2085 sample->time = 0;
Adrian Hunter53ff6bc2015-08-18 12:07:05 +03002086 sample->tid = event->fork.tid;
2087 sample->pid = event->fork.pid;
Namhyung Kimad7ebb92013-11-26 17:51:12 +09002088 }
Jiri Olsa28a0b392018-01-07 17:03:52 +01002089 perf_sample__fprintf_start(sample, thread, evsel,
2090 PERF_RECORD_EXIT, stdout);
Namhyung Kimad7ebb92013-11-26 17:51:12 +09002091 perf_event__fprintf(event, stdout);
2092
2093 if (perf_event__process_exit(tool, event, sample, machine) < 0)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002094 err = -1;
Namhyung Kimad7ebb92013-11-26 17:51:12 +09002095
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002096 thread__put(thread);
2097 return err;
Namhyung Kimad7ebb92013-11-26 17:51:12 +09002098}
2099
Namhyung Kimba1ddf42013-11-26 17:54:26 +09002100static int process_mmap_event(struct perf_tool *tool,
2101 union perf_event *event,
2102 struct perf_sample *sample,
2103 struct machine *machine)
2104{
2105 struct thread *thread;
2106 struct perf_script *script = container_of(tool, struct perf_script, tool);
2107 struct perf_session *session = script->session;
Adrian Hunter06b234e2015-07-21 12:44:05 +03002108 struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
Namhyung Kimba1ddf42013-11-26 17:54:26 +09002109
2110 if (perf_event__process_mmap(tool, event, sample, machine) < 0)
2111 return -1;
2112
2113 thread = machine__findnew_thread(machine, event->mmap.pid, event->mmap.tid);
2114 if (thread == NULL) {
2115 pr_debug("problem processing MMAP event, skipping it.\n");
2116 return -1;
2117 }
2118
2119 if (!evsel->attr.sample_id_all) {
2120 sample->cpu = 0;
2121 sample->time = 0;
2122 sample->tid = event->mmap.tid;
2123 sample->pid = event->mmap.pid;
2124 }
Jiri Olsa28a0b392018-01-07 17:03:52 +01002125 perf_sample__fprintf_start(sample, thread, evsel,
2126 PERF_RECORD_MMAP, stdout);
Namhyung Kimba1ddf42013-11-26 17:54:26 +09002127 perf_event__fprintf(event, stdout);
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002128 thread__put(thread);
Namhyung Kimba1ddf42013-11-26 17:54:26 +09002129 return 0;
2130}
2131
2132static int process_mmap2_event(struct perf_tool *tool,
2133 union perf_event *event,
2134 struct perf_sample *sample,
2135 struct machine *machine)
2136{
2137 struct thread *thread;
2138 struct perf_script *script = container_of(tool, struct perf_script, tool);
2139 struct perf_session *session = script->session;
Adrian Hunter06b234e2015-07-21 12:44:05 +03002140 struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
Namhyung Kimba1ddf42013-11-26 17:54:26 +09002141
2142 if (perf_event__process_mmap2(tool, event, sample, machine) < 0)
2143 return -1;
2144
2145 thread = machine__findnew_thread(machine, event->mmap2.pid, event->mmap2.tid);
2146 if (thread == NULL) {
2147 pr_debug("problem processing MMAP2 event, skipping it.\n");
2148 return -1;
2149 }
2150
2151 if (!evsel->attr.sample_id_all) {
2152 sample->cpu = 0;
2153 sample->time = 0;
2154 sample->tid = event->mmap2.tid;
2155 sample->pid = event->mmap2.pid;
2156 }
Jiri Olsa28a0b392018-01-07 17:03:52 +01002157 perf_sample__fprintf_start(sample, thread, evsel,
2158 PERF_RECORD_MMAP2, stdout);
Namhyung Kimba1ddf42013-11-26 17:54:26 +09002159 perf_event__fprintf(event, stdout);
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002160 thread__put(thread);
Namhyung Kimba1ddf42013-11-26 17:54:26 +09002161 return 0;
2162}
2163
Adrian Hunter7c148982015-07-21 12:44:06 +03002164static int process_switch_event(struct perf_tool *tool,
2165 union perf_event *event,
2166 struct perf_sample *sample,
2167 struct machine *machine)
2168{
2169 struct thread *thread;
2170 struct perf_script *script = container_of(tool, struct perf_script, tool);
2171 struct perf_session *session = script->session;
2172 struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
2173
2174 if (perf_event__process_switch(tool, event, sample, machine) < 0)
2175 return -1;
2176
2177 thread = machine__findnew_thread(machine, sample->pid,
2178 sample->tid);
2179 if (thread == NULL) {
2180 pr_debug("problem processing SWITCH event, skipping it.\n");
2181 return -1;
2182 }
2183
Jiri Olsa28a0b392018-01-07 17:03:52 +01002184 perf_sample__fprintf_start(sample, thread, evsel,
2185 PERF_RECORD_SWITCH, stdout);
Adrian Hunter7c148982015-07-21 12:44:06 +03002186 perf_event__fprintf(event, stdout);
2187 thread__put(thread);
2188 return 0;
2189}
2190
Jiri Olsa3d7c27b2018-01-07 17:03:53 +01002191static int
2192process_lost_event(struct perf_tool *tool,
2193 union perf_event *event,
2194 struct perf_sample *sample,
2195 struct machine *machine)
2196{
2197 struct perf_script *script = container_of(tool, struct perf_script, tool);
2198 struct perf_session *session = script->session;
2199 struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
2200 struct thread *thread;
2201
2202 thread = machine__findnew_thread(machine, sample->pid,
2203 sample->tid);
2204 if (thread == NULL)
2205 return -1;
2206
2207 perf_sample__fprintf_start(sample, thread, evsel,
2208 PERF_RECORD_LOST, stdout);
2209 perf_event__fprintf(event, stdout);
2210 thread__put(thread);
2211 return 0;
2212}
2213
Jiri Olsa3233b372018-02-06 19:17:59 +01002214static int
2215process_finished_round_event(struct perf_tool *tool __maybe_unused,
2216 union perf_event *event,
2217 struct ordered_events *oe __maybe_unused)
2218
2219{
2220 perf_event__fprintf(event, stdout);
2221 return 0;
2222}
2223
Irina Tirdea1d037ca2012-09-11 01:15:03 +03002224static void sig_handler(int sig __maybe_unused)
Tom Zanussic239da32010-04-01 23:59:18 -05002225{
2226 session_done = 1;
2227}
2228
Arnaldo Carvalho de Meloa14390f2017-10-26 10:30:20 -03002229static void perf_script__fclose_per_event_dump(struct perf_script *script)
2230{
2231 struct perf_evlist *evlist = script->session->evlist;
2232 struct perf_evsel *evsel;
2233
2234 evlist__for_each_entry(evlist, evsel) {
2235 if (!evsel->priv)
2236 break;
Arnaldo Carvalho de Melo642ee1c2017-10-30 13:11:15 -03002237 perf_evsel_script__delete(evsel->priv);
Arnaldo Carvalho de Meloa14390f2017-10-26 10:30:20 -03002238 evsel->priv = NULL;
2239 }
2240}
2241
2242static int perf_script__fopen_per_event_dump(struct perf_script *script)
2243{
2244 struct perf_evsel *evsel;
2245
2246 evlist__for_each_entry(script->session->evlist, evsel) {
Arnaldo Carvalho de Melofa48c892017-11-09 16:04:26 -03002247 /*
2248 * Already setup? I.e. we may be called twice in cases like
2249 * Intel PT, one for the intel_pt// and dummy events, then
2250 * for the evsels syntheized from the auxtrace info.
2251 *
2252 * Ses perf_script__process_auxtrace_info.
2253 */
2254 if (evsel->priv != NULL)
2255 continue;
2256
Jiri Olsa8ceb41d2017-01-23 22:07:59 +01002257 evsel->priv = perf_evsel_script__new(evsel, script->session->data);
Arnaldo Carvalho de Meloa14390f2017-10-26 10:30:20 -03002258 if (evsel->priv == NULL)
2259 goto out_err_fclose;
2260 }
2261
2262 return 0;
2263
2264out_err_fclose:
2265 perf_script__fclose_per_event_dump(script);
2266 return -1;
2267}
2268
2269static int perf_script__setup_per_event_dump(struct perf_script *script)
2270{
2271 struct perf_evsel *evsel;
Arnaldo Carvalho de Melo642ee1c2017-10-30 13:11:15 -03002272 static struct perf_evsel_script es_stdout;
Arnaldo Carvalho de Meloa14390f2017-10-26 10:30:20 -03002273
2274 if (script->per_event_dump)
2275 return perf_script__fopen_per_event_dump(script);
2276
Arnaldo Carvalho de Melo642ee1c2017-10-30 13:11:15 -03002277 es_stdout.fp = stdout;
2278
Arnaldo Carvalho de Meloa14390f2017-10-26 10:30:20 -03002279 evlist__for_each_entry(script->session->evlist, evsel)
Arnaldo Carvalho de Melo642ee1c2017-10-30 13:11:15 -03002280 evsel->priv = &es_stdout;
Arnaldo Carvalho de Meloa14390f2017-10-26 10:30:20 -03002281
2282 return 0;
2283}
2284
Arnaldo Carvalho de Melo642ee1c2017-10-30 13:11:15 -03002285static void perf_script__exit_per_event_dump_stats(struct perf_script *script)
2286{
2287 struct perf_evsel *evsel;
2288
2289 evlist__for_each_entry(script->session->evlist, evsel) {
2290 struct perf_evsel_script *es = evsel->priv;
2291
2292 perf_evsel_script__fprintf(es, stdout);
2293 perf_evsel_script__delete(es);
2294 evsel->priv = NULL;
2295 }
2296}
2297
Adrian Hunter6f3e5ed2013-10-22 10:34:07 +03002298static int __cmd_script(struct perf_script *script)
Frederic Weisbecker5f9c39d2009-08-17 16:18:08 +02002299{
Frederic Weisbecker6fcf7dd2010-05-27 15:46:25 +02002300 int ret;
2301
Tom Zanussic239da32010-04-01 23:59:18 -05002302 signal(SIGINT, sig_handler);
2303
Namhyung Kimad7ebb92013-11-26 17:51:12 +09002304 /* override event processing functions */
2305 if (script->show_task_events) {
2306 script->tool.comm = process_comm_event;
2307 script->tool.fork = process_fork_event;
2308 script->tool.exit = process_exit_event;
2309 }
Namhyung Kimba1ddf42013-11-26 17:54:26 +09002310 if (script->show_mmap_events) {
2311 script->tool.mmap = process_mmap_event;
2312 script->tool.mmap2 = process_mmap2_event;
2313 }
Adrian Hunter7c148982015-07-21 12:44:06 +03002314 if (script->show_switch_events)
2315 script->tool.context_switch = process_switch_event;
Hari Bathini96a44bb2017-03-08 02:12:06 +05302316 if (script->show_namespace_events)
2317 script->tool.namespaces = process_namespaces_event;
Jiri Olsa3d7c27b2018-01-07 17:03:53 +01002318 if (script->show_lost_events)
2319 script->tool.lost = process_lost_event;
Jiri Olsa3233b372018-02-06 19:17:59 +01002320 if (script->show_round_events) {
2321 script->tool.ordered_events = false;
2322 script->tool.finished_round = process_finished_round_event;
2323 }
Namhyung Kimad7ebb92013-11-26 17:51:12 +09002324
Arnaldo Carvalho de Meloa14390f2017-10-26 10:30:20 -03002325 if (perf_script__setup_per_event_dump(script)) {
2326 pr_err("Couldn't create the per event dump files\n");
2327 return -1;
2328 }
2329
Arnaldo Carvalho de Melob7b61cb2015-03-03 11:58:45 -03002330 ret = perf_session__process_events(script->session);
Frederic Weisbecker6fcf7dd2010-05-27 15:46:25 +02002331
Arnaldo Carvalho de Meloa14390f2017-10-26 10:30:20 -03002332 if (script->per_event_dump)
Arnaldo Carvalho de Melo642ee1c2017-10-30 13:11:15 -03002333 perf_script__exit_per_event_dump_stats(script);
Arnaldo Carvalho de Meloa14390f2017-10-26 10:30:20 -03002334
Arnaldo Carvalho de Melo6d8afb52011-01-04 16:27:30 -02002335 if (debug_mode)
Arnaldo Carvalho de Melo9486aa32011-01-22 20:37:02 -02002336 pr_err("Misordered timestamps: %" PRIu64 "\n", nr_unordered);
Frederic Weisbecker6fcf7dd2010-05-27 15:46:25 +02002337
2338 return ret;
Frederic Weisbecker5f9c39d2009-08-17 16:18:08 +02002339}
2340
Tom Zanussi956ffd02009-11-25 01:15:46 -06002341struct script_spec {
2342 struct list_head node;
2343 struct scripting_ops *ops;
2344 char spec[0];
2345};
2346
Arnaldo Carvalho de Meloeccdfe22011-01-04 16:32:52 -02002347static LIST_HEAD(script_specs);
Tom Zanussi956ffd02009-11-25 01:15:46 -06002348
2349static struct script_spec *script_spec__new(const char *spec,
2350 struct scripting_ops *ops)
2351{
2352 struct script_spec *s = malloc(sizeof(*s) + strlen(spec) + 1);
2353
2354 if (s != NULL) {
2355 strcpy(s->spec, spec);
2356 s->ops = ops;
2357 }
2358
2359 return s;
2360}
2361
Tom Zanussi956ffd02009-11-25 01:15:46 -06002362static void script_spec__add(struct script_spec *s)
2363{
2364 list_add_tail(&s->node, &script_specs);
2365}
2366
2367static struct script_spec *script_spec__find(const char *spec)
2368{
2369 struct script_spec *s;
2370
2371 list_for_each_entry(s, &script_specs, node)
2372 if (strcasecmp(s->spec, spec) == 0)
2373 return s;
2374 return NULL;
2375}
2376
Tom Zanussi956ffd02009-11-25 01:15:46 -06002377int script_spec_register(const char *spec, struct scripting_ops *ops)
2378{
2379 struct script_spec *s;
2380
2381 s = script_spec__find(spec);
2382 if (s)
2383 return -1;
2384
Taeung Song8560bae2016-02-26 00:13:10 +09002385 s = script_spec__new(spec, ops);
Tom Zanussi956ffd02009-11-25 01:15:46 -06002386 if (!s)
2387 return -1;
Taeung Song8560bae2016-02-26 00:13:10 +09002388 else
2389 script_spec__add(s);
Tom Zanussi956ffd02009-11-25 01:15:46 -06002390
2391 return 0;
2392}
2393
2394static struct scripting_ops *script_spec__lookup(const char *spec)
2395{
2396 struct script_spec *s = script_spec__find(spec);
2397 if (!s)
2398 return NULL;
2399
2400 return s->ops;
2401}
2402
2403static void list_available_languages(void)
2404{
2405 struct script_spec *s;
2406
2407 fprintf(stderr, "\n");
2408 fprintf(stderr, "Scripting language extensions (used in "
Ingo Molnar133dc4c2010-11-16 18:45:39 +01002409 "perf script -s [spec:]script.[spec]):\n\n");
Tom Zanussi956ffd02009-11-25 01:15:46 -06002410
2411 list_for_each_entry(s, &script_specs, node)
2412 fprintf(stderr, " %-42s [%s]\n", s->spec, s->ops->name);
2413
2414 fprintf(stderr, "\n");
2415}
2416
Irina Tirdea1d037ca2012-09-11 01:15:03 +03002417static int parse_scriptname(const struct option *opt __maybe_unused,
2418 const char *str, int unset __maybe_unused)
Tom Zanussi956ffd02009-11-25 01:15:46 -06002419{
2420 char spec[PATH_MAX];
2421 const char *script, *ext;
2422 int len;
2423
Tom Zanussif526d682010-01-27 02:27:52 -06002424 if (strcmp(str, "lang") == 0) {
Tom Zanussi956ffd02009-11-25 01:15:46 -06002425 list_available_languages();
Tom Zanussif526d682010-01-27 02:27:52 -06002426 exit(0);
Tom Zanussi956ffd02009-11-25 01:15:46 -06002427 }
2428
2429 script = strchr(str, ':');
2430 if (script) {
2431 len = script - str;
2432 if (len >= PATH_MAX) {
2433 fprintf(stderr, "invalid language specifier");
2434 return -1;
2435 }
2436 strncpy(spec, str, len);
2437 spec[len] = '\0';
2438 scripting_ops = script_spec__lookup(spec);
2439 if (!scripting_ops) {
2440 fprintf(stderr, "invalid language specifier");
2441 return -1;
2442 }
2443 script++;
2444 } else {
2445 script = str;
Ben Hutchingsd1e95bb2010-10-10 16:11:02 +01002446 ext = strrchr(script, '.');
Tom Zanussi956ffd02009-11-25 01:15:46 -06002447 if (!ext) {
2448 fprintf(stderr, "invalid script extension");
2449 return -1;
2450 }
2451 scripting_ops = script_spec__lookup(++ext);
2452 if (!scripting_ops) {
2453 fprintf(stderr, "invalid script extension");
2454 return -1;
2455 }
2456 }
2457
2458 script_name = strdup(script);
2459
2460 return 0;
2461}
2462
Irina Tirdea1d037ca2012-09-11 01:15:03 +03002463static int parse_output_fields(const struct option *opt __maybe_unused,
2464 const char *arg, int unset __maybe_unused)
David Ahern745f43e2011-03-09 22:23:26 -07002465{
Arnaldo Carvalho de Melo49346e82017-04-05 11:43:41 -03002466 char *tok, *strtok_saveptr = NULL;
Sasha Levin50ca19a2012-12-20 14:11:19 -05002467 int i, imax = ARRAY_SIZE(all_output_options);
David Ahern2c9e45f72011-03-17 10:03:21 -06002468 int j;
David Ahern745f43e2011-03-09 22:23:26 -07002469 int rc = 0;
2470 char *str = strdup(arg);
David Ahern1424dc92011-03-09 22:23:28 -07002471 int type = -1;
Andi Kleen36ce5652017-06-02 08:48:10 -07002472 enum { DEFAULT, SET, ADD, REMOVE } change = DEFAULT;
David Ahern745f43e2011-03-09 22:23:26 -07002473
2474 if (!str)
2475 return -ENOMEM;
2476
David Ahern2c9e45f72011-03-17 10:03:21 -06002477 /* first word can state for which event type the user is specifying
2478 * the fields. If no type exists, the specified fields apply to all
2479 * event types found in the file minus the invalid fields for a type.
David Ahern1424dc92011-03-09 22:23:28 -07002480 */
David Ahern2c9e45f72011-03-17 10:03:21 -06002481 tok = strchr(str, ':');
2482 if (tok) {
2483 *tok = '\0';
2484 tok++;
2485 if (!strcmp(str, "hw"))
2486 type = PERF_TYPE_HARDWARE;
2487 else if (!strcmp(str, "sw"))
2488 type = PERF_TYPE_SOFTWARE;
2489 else if (!strcmp(str, "trace"))
2490 type = PERF_TYPE_TRACEPOINT;
Arun Sharma0817a6a2011-04-14 10:38:18 -07002491 else if (!strcmp(str, "raw"))
2492 type = PERF_TYPE_RAW;
Wang Nan27cfef02015-12-08 02:25:43 +00002493 else if (!strcmp(str, "break"))
2494 type = PERF_TYPE_BREAKPOINT;
Adrian Hunter14057202017-06-21 13:17:19 +03002495 else if (!strcmp(str, "synth"))
2496 type = OUTPUT_TYPE_SYNTH;
David Ahern2c9e45f72011-03-17 10:03:21 -06002497 else {
2498 fprintf(stderr, "Invalid event type in field string.\n");
Robert Richter38efb532011-11-25 11:38:40 +01002499 rc = -EINVAL;
2500 goto out;
David Ahern2c9e45f72011-03-17 10:03:21 -06002501 }
2502
2503 if (output[type].user_set)
2504 pr_warning("Overriding previous field request for %s events.\n",
2505 event_type(type));
2506
2507 output[type].fields = 0;
2508 output[type].user_set = true;
David Ahern9cbdb702011-04-06 21:54:20 -06002509 output[type].wildcard_set = false;
David Ahern2c9e45f72011-03-17 10:03:21 -06002510
2511 } else {
2512 tok = str;
2513 if (strlen(str) == 0) {
2514 fprintf(stderr,
2515 "Cannot set fields to 'none' for all event types.\n");
2516 rc = -EINVAL;
2517 goto out;
2518 }
2519
Andi Kleen36ce5652017-06-02 08:48:10 -07002520 /* Don't override defaults for +- */
2521 if (strchr(str, '+') || strchr(str, '-'))
2522 goto parse;
2523
David Ahern2c9e45f72011-03-17 10:03:21 -06002524 if (output_set_by_user())
2525 pr_warning("Overriding previous field request for all events.\n");
2526
Adrian Hunter14057202017-06-21 13:17:19 +03002527 for (j = 0; j < OUTPUT_TYPE_MAX; ++j) {
David Ahern2c9e45f72011-03-17 10:03:21 -06002528 output[j].fields = 0;
2529 output[j].user_set = true;
David Ahern9cbdb702011-04-06 21:54:20 -06002530 output[j].wildcard_set = true;
David Ahern2c9e45f72011-03-17 10:03:21 -06002531 }
David Ahern1424dc92011-03-09 22:23:28 -07002532 }
2533
Andi Kleen36ce5652017-06-02 08:48:10 -07002534parse:
Arnaldo Carvalho de Melo49346e82017-04-05 11:43:41 -03002535 for (tok = strtok_r(tok, ",", &strtok_saveptr); tok; tok = strtok_r(NULL, ",", &strtok_saveptr)) {
Andi Kleen36ce5652017-06-02 08:48:10 -07002536 if (*tok == '+') {
2537 if (change == SET)
2538 goto out_badmix;
2539 change = ADD;
2540 tok++;
2541 } else if (*tok == '-') {
2542 if (change == SET)
2543 goto out_badmix;
2544 change = REMOVE;
2545 tok++;
2546 } else {
2547 if (change != SET && change != DEFAULT)
2548 goto out_badmix;
2549 change = SET;
2550 }
2551
David Ahern745f43e2011-03-09 22:23:26 -07002552 for (i = 0; i < imax; ++i) {
David Ahern2c9e45f72011-03-17 10:03:21 -06002553 if (strcmp(tok, all_output_options[i].str) == 0)
David Ahern745f43e2011-03-09 22:23:26 -07002554 break;
David Ahern745f43e2011-03-09 22:23:26 -07002555 }
Adrian Hunter400ea6d2015-04-09 18:54:05 +03002556 if (i == imax && strcmp(tok, "flags") == 0) {
Andi Kleen36ce5652017-06-02 08:48:10 -07002557 print_flags = change == REMOVE ? false : true;
Adrian Hunter400ea6d2015-04-09 18:54:05 +03002558 continue;
2559 }
David Ahern745f43e2011-03-09 22:23:26 -07002560 if (i == imax) {
David Ahern2c9e45f72011-03-17 10:03:21 -06002561 fprintf(stderr, "Invalid field requested.\n");
David Ahern745f43e2011-03-09 22:23:26 -07002562 rc = -EINVAL;
David Ahern2c9e45f72011-03-17 10:03:21 -06002563 goto out;
2564 }
2565
2566 if (type == -1) {
2567 /* add user option to all events types for
2568 * which it is valid
2569 */
Adrian Hunter14057202017-06-21 13:17:19 +03002570 for (j = 0; j < OUTPUT_TYPE_MAX; ++j) {
David Ahern2c9e45f72011-03-17 10:03:21 -06002571 if (output[j].invalid_fields & all_output_options[i].field) {
2572 pr_warning("\'%s\' not valid for %s events. Ignoring.\n",
2573 all_output_options[i].str, event_type(j));
Andi Kleen36ce5652017-06-02 08:48:10 -07002574 } else {
2575 if (change == REMOVE)
2576 output[j].fields &= ~all_output_options[i].field;
2577 else
2578 output[j].fields |= all_output_options[i].field;
Andi Kleen37fed3d2018-09-18 05:32:09 -07002579 output[j].user_set = true;
2580 output[j].wildcard_set = true;
Andi Kleen36ce5652017-06-02 08:48:10 -07002581 }
David Ahern2c9e45f72011-03-17 10:03:21 -06002582 }
2583 } else {
2584 if (output[type].invalid_fields & all_output_options[i].field) {
2585 fprintf(stderr, "\'%s\' not valid for %s events.\n",
2586 all_output_options[i].str, event_type(type));
2587
2588 rc = -EINVAL;
2589 goto out;
2590 }
Andi Kleen37fed3d2018-09-18 05:32:09 -07002591 output[type].user_set = true;
2592 output[type].wildcard_set = true;
David Ahern2c9e45f72011-03-17 10:03:21 -06002593 }
David Ahern2c9e45f72011-03-17 10:03:21 -06002594 }
2595
2596 if (type >= 0) {
2597 if (output[type].fields == 0) {
2598 pr_debug("No fields requested for %s type. "
2599 "Events will not be displayed.\n", event_type(type));
David Ahern745f43e2011-03-09 22:23:26 -07002600 }
David Ahern1424dc92011-03-09 22:23:28 -07002601 }
Andi Kleen36ce5652017-06-02 08:48:10 -07002602 goto out;
David Ahern745f43e2011-03-09 22:23:26 -07002603
Andi Kleen36ce5652017-06-02 08:48:10 -07002604out_badmix:
2605 fprintf(stderr, "Cannot mix +-field with overridden fields\n");
2606 rc = -EINVAL;
David Ahern2c9e45f72011-03-17 10:03:21 -06002607out:
David Ahern745f43e2011-03-09 22:23:26 -07002608 free(str);
2609 return rc;
2610}
2611
Arnaldo Carvalho de Meloa5e8e822016-04-08 11:25:59 -03002612#define for_each_lang(scripts_path, scripts_dir, lang_dirent) \
2613 while ((lang_dirent = readdir(scripts_dir)) != NULL) \
2614 if ((lang_dirent->d_type == DT_DIR || \
2615 (lang_dirent->d_type == DT_UNKNOWN && \
2616 is_directory(scripts_path, lang_dirent))) && \
2617 (strcmp(lang_dirent->d_name, ".")) && \
2618 (strcmp(lang_dirent->d_name, "..")))
Tom Zanussi4b9c0c52009-12-15 02:53:38 -06002619
Arnaldo Carvalho de Meloa5e8e822016-04-08 11:25:59 -03002620#define for_each_script(lang_path, lang_dir, script_dirent) \
2621 while ((script_dirent = readdir(lang_dir)) != NULL) \
2622 if (script_dirent->d_type != DT_DIR && \
2623 (script_dirent->d_type != DT_UNKNOWN || \
2624 !is_directory(lang_path, script_dirent)))
Tom Zanussi4b9c0c52009-12-15 02:53:38 -06002625
2626
2627#define RECORD_SUFFIX "-record"
2628#define REPORT_SUFFIX "-report"
2629
2630struct script_desc {
2631 struct list_head node;
2632 char *name;
2633 char *half_liner;
2634 char *args;
2635};
2636
Arnaldo Carvalho de Meloeccdfe22011-01-04 16:32:52 -02002637static LIST_HEAD(script_descs);
Tom Zanussi4b9c0c52009-12-15 02:53:38 -06002638
2639static struct script_desc *script_desc__new(const char *name)
2640{
2641 struct script_desc *s = zalloc(sizeof(*s));
2642
Tom Zanussib5b87312010-11-10 08:16:51 -06002643 if (s != NULL && name)
Tom Zanussi4b9c0c52009-12-15 02:53:38 -06002644 s->name = strdup(name);
2645
2646 return s;
2647}
2648
2649static void script_desc__delete(struct script_desc *s)
2650{
Arnaldo Carvalho de Melo74cf2492013-12-27 16:55:14 -03002651 zfree(&s->name);
2652 zfree(&s->half_liner);
2653 zfree(&s->args);
Tom Zanussi4b9c0c52009-12-15 02:53:38 -06002654 free(s);
2655}
2656
2657static void script_desc__add(struct script_desc *s)
2658{
2659 list_add_tail(&s->node, &script_descs);
2660}
2661
2662static struct script_desc *script_desc__find(const char *name)
2663{
2664 struct script_desc *s;
2665
2666 list_for_each_entry(s, &script_descs, node)
2667 if (strcasecmp(s->name, name) == 0)
2668 return s;
2669 return NULL;
2670}
2671
2672static struct script_desc *script_desc__findnew(const char *name)
2673{
2674 struct script_desc *s = script_desc__find(name);
2675
2676 if (s)
2677 return s;
2678
2679 s = script_desc__new(name);
2680 if (!s)
Dan Carpenter2ec5cab62017-07-22 10:36:10 +03002681 return NULL;
Tom Zanussi4b9c0c52009-12-15 02:53:38 -06002682
2683 script_desc__add(s);
2684
2685 return s;
Tom Zanussi4b9c0c52009-12-15 02:53:38 -06002686}
2687
Stephane Eranian965bb6b2010-12-03 17:52:01 +02002688static const char *ends_with(const char *str, const char *suffix)
Tom Zanussi4b9c0c52009-12-15 02:53:38 -06002689{
2690 size_t suffix_len = strlen(suffix);
Stephane Eranian965bb6b2010-12-03 17:52:01 +02002691 const char *p = str;
Tom Zanussi4b9c0c52009-12-15 02:53:38 -06002692
2693 if (strlen(str) > suffix_len) {
2694 p = str + strlen(str) - suffix_len;
2695 if (!strncmp(p, suffix, suffix_len))
2696 return p;
2697 }
2698
2699 return NULL;
2700}
2701
Tom Zanussi4b9c0c52009-12-15 02:53:38 -06002702static int read_script_info(struct script_desc *desc, const char *filename)
2703{
2704 char line[BUFSIZ], *p;
2705 FILE *fp;
2706
2707 fp = fopen(filename, "r");
2708 if (!fp)
2709 return -1;
2710
2711 while (fgets(line, sizeof(line), fp)) {
2712 p = ltrim(line);
2713 if (strlen(p) == 0)
2714 continue;
2715 if (*p != '#')
2716 continue;
2717 p++;
2718 if (strlen(p) && *p == '!')
2719 continue;
2720
2721 p = ltrim(p);
2722 if (strlen(p) && p[strlen(p) - 1] == '\n')
2723 p[strlen(p) - 1] = '\0';
2724
2725 if (!strncmp(p, "description:", strlen("description:"))) {
2726 p += strlen("description:");
2727 desc->half_liner = strdup(ltrim(p));
2728 continue;
2729 }
2730
2731 if (!strncmp(p, "args:", strlen("args:"))) {
2732 p += strlen("args:");
2733 desc->args = strdup(ltrim(p));
2734 continue;
2735 }
2736 }
2737
2738 fclose(fp);
2739
2740 return 0;
2741}
2742
Robert Richter38efb532011-11-25 11:38:40 +01002743static char *get_script_root(struct dirent *script_dirent, const char *suffix)
2744{
2745 char *script_root, *str;
2746
2747 script_root = strdup(script_dirent->d_name);
2748 if (!script_root)
2749 return NULL;
2750
2751 str = (char *)ends_with(script_root, suffix);
2752 if (!str) {
2753 free(script_root);
2754 return NULL;
2755 }
2756
2757 *str = '\0';
2758 return script_root;
2759}
2760
Irina Tirdea1d037ca2012-09-11 01:15:03 +03002761static int list_available_scripts(const struct option *opt __maybe_unused,
2762 const char *s __maybe_unused,
2763 int unset __maybe_unused)
Tom Zanussi4b9c0c52009-12-15 02:53:38 -06002764{
Arnaldo Carvalho de Meloa5e8e822016-04-08 11:25:59 -03002765 struct dirent *script_dirent, *lang_dirent;
Tom Zanussi4b9c0c52009-12-15 02:53:38 -06002766 char scripts_path[MAXPATHLEN];
2767 DIR *scripts_dir, *lang_dir;
2768 char script_path[MAXPATHLEN];
2769 char lang_path[MAXPATHLEN];
2770 struct script_desc *desc;
2771 char first_half[BUFSIZ];
2772 char *script_root;
Tom Zanussi4b9c0c52009-12-15 02:53:38 -06002773
Josh Poimboeuf46113a52015-12-15 09:39:37 -06002774 snprintf(scripts_path, MAXPATHLEN, "%s/scripts", get_argv_exec_path());
Tom Zanussi4b9c0c52009-12-15 02:53:38 -06002775
2776 scripts_dir = opendir(scripts_path);
He Kuang88ded4d2016-08-04 11:25:42 +00002777 if (!scripts_dir) {
2778 fprintf(stdout,
2779 "open(%s) failed.\n"
2780 "Check \"PERF_EXEC_PATH\" env to set scripts dir.\n",
2781 scripts_path);
2782 exit(-1);
2783 }
Tom Zanussi4b9c0c52009-12-15 02:53:38 -06002784
Arnaldo Carvalho de Meloa5e8e822016-04-08 11:25:59 -03002785 for_each_lang(scripts_path, scripts_dir, lang_dirent) {
Jiri Olsa77f18152018-03-19 09:29:01 +01002786 scnprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path,
2787 lang_dirent->d_name);
Tom Zanussi4b9c0c52009-12-15 02:53:38 -06002788 lang_dir = opendir(lang_path);
2789 if (!lang_dir)
2790 continue;
2791
Arnaldo Carvalho de Meloa5e8e822016-04-08 11:25:59 -03002792 for_each_script(lang_path, lang_dir, script_dirent) {
2793 script_root = get_script_root(script_dirent, REPORT_SUFFIX);
Robert Richter38efb532011-11-25 11:38:40 +01002794 if (script_root) {
Tom Zanussi4b9c0c52009-12-15 02:53:38 -06002795 desc = script_desc__findnew(script_root);
Jiri Olsa77f18152018-03-19 09:29:01 +01002796 scnprintf(script_path, MAXPATHLEN, "%s/%s",
2797 lang_path, script_dirent->d_name);
Tom Zanussi4b9c0c52009-12-15 02:53:38 -06002798 read_script_info(desc, script_path);
Robert Richter38efb532011-11-25 11:38:40 +01002799 free(script_root);
Tom Zanussi4b9c0c52009-12-15 02:53:38 -06002800 }
Tom Zanussi4b9c0c52009-12-15 02:53:38 -06002801 }
2802 }
2803
2804 fprintf(stdout, "List of available trace scripts:\n");
2805 list_for_each_entry(desc, &script_descs, node) {
2806 sprintf(first_half, "%s %s", desc->name,
2807 desc->args ? desc->args : "");
2808 fprintf(stdout, " %-36s %s\n", first_half,
2809 desc->half_liner ? desc->half_liner : "");
2810 }
2811
2812 exit(0);
2813}
2814
Feng Tange5f37052012-09-07 16:42:26 +08002815/*
Feng Tang49e639e2012-10-30 11:56:03 +08002816 * Some scripts specify the required events in their "xxx-record" file,
2817 * this function will check if the events in perf.data match those
2818 * mentioned in the "xxx-record".
2819 *
2820 * Fixme: All existing "xxx-record" are all in good formats "-e event ",
2821 * which is covered well now. And new parsing code should be added to
2822 * cover the future complexing formats like event groups etc.
2823 */
2824static int check_ev_match(char *dir_name, char *scriptname,
2825 struct perf_session *session)
2826{
2827 char filename[MAXPATHLEN], evname[128];
2828 char line[BUFSIZ], *p;
2829 struct perf_evsel *pos;
2830 int match, len;
2831 FILE *fp;
2832
Jiri Olsa77f18152018-03-19 09:29:01 +01002833 scnprintf(filename, MAXPATHLEN, "%s/bin/%s-record", dir_name, scriptname);
Feng Tang49e639e2012-10-30 11:56:03 +08002834
2835 fp = fopen(filename, "r");
2836 if (!fp)
2837 return -1;
2838
2839 while (fgets(line, sizeof(line), fp)) {
2840 p = ltrim(line);
2841 if (*p == '#')
2842 continue;
2843
2844 while (strlen(p)) {
2845 p = strstr(p, "-e");
2846 if (!p)
2847 break;
2848
2849 p += 2;
2850 p = ltrim(p);
2851 len = strcspn(p, " \t");
2852 if (!len)
2853 break;
2854
2855 snprintf(evname, len + 1, "%s", p);
2856
2857 match = 0;
Arnaldo Carvalho de Meloe5cadb92016-06-23 11:26:15 -03002858 evlist__for_each_entry(session->evlist, pos) {
Feng Tang49e639e2012-10-30 11:56:03 +08002859 if (!strcmp(perf_evsel__name(pos), evname)) {
2860 match = 1;
2861 break;
2862 }
2863 }
2864
2865 if (!match) {
2866 fclose(fp);
2867 return -1;
2868 }
2869 }
2870 }
2871
2872 fclose(fp);
2873 return 0;
2874}
2875
2876/*
Feng Tange5f37052012-09-07 16:42:26 +08002877 * Return -1 if none is found, otherwise the actual scripts number.
2878 *
2879 * Currently the only user of this function is the script browser, which
2880 * will list all statically runnable scripts, select one, execute it and
2881 * show the output in a perf browser.
2882 */
2883int find_scripts(char **scripts_array, char **scripts_path_array)
2884{
Arnaldo Carvalho de Meloa5e8e822016-04-08 11:25:59 -03002885 struct dirent *script_dirent, *lang_dirent;
Feng Tang49e639e2012-10-30 11:56:03 +08002886 char scripts_path[MAXPATHLEN], lang_path[MAXPATHLEN];
Feng Tange5f37052012-09-07 16:42:26 +08002887 DIR *scripts_dir, *lang_dir;
Feng Tang49e639e2012-10-30 11:56:03 +08002888 struct perf_session *session;
Jiri Olsa8ceb41d2017-01-23 22:07:59 +01002889 struct perf_data data = {
Jiri Olsaeae8ad82017-01-23 22:25:41 +01002890 .file = {
2891 .path = input_name,
2892 },
2893 .mode = PERF_DATA_MODE_READ,
Jiri Olsaf5fc14122013-10-15 16:27:32 +02002894 };
Feng Tange5f37052012-09-07 16:42:26 +08002895 char *temp;
2896 int i = 0;
2897
Jiri Olsa8ceb41d2017-01-23 22:07:59 +01002898 session = perf_session__new(&data, false, NULL);
Feng Tang49e639e2012-10-30 11:56:03 +08002899 if (!session)
2900 return -1;
2901
Josh Poimboeuf46113a52015-12-15 09:39:37 -06002902 snprintf(scripts_path, MAXPATHLEN, "%s/scripts", get_argv_exec_path());
Feng Tange5f37052012-09-07 16:42:26 +08002903
2904 scripts_dir = opendir(scripts_path);
Feng Tang49e639e2012-10-30 11:56:03 +08002905 if (!scripts_dir) {
2906 perf_session__delete(session);
Feng Tange5f37052012-09-07 16:42:26 +08002907 return -1;
Feng Tang49e639e2012-10-30 11:56:03 +08002908 }
Feng Tange5f37052012-09-07 16:42:26 +08002909
Arnaldo Carvalho de Meloa5e8e822016-04-08 11:25:59 -03002910 for_each_lang(scripts_path, scripts_dir, lang_dirent) {
Jiri Olsa77f18152018-03-19 09:29:01 +01002911 scnprintf(lang_path, MAXPATHLEN, "%s/%s", scripts_path,
2912 lang_dirent->d_name);
Jin Yao90ce61b2018-04-09 18:26:47 +08002913#ifndef HAVE_LIBPERL_SUPPORT
Feng Tange5f37052012-09-07 16:42:26 +08002914 if (strstr(lang_path, "perl"))
2915 continue;
2916#endif
Jin Yao90ce61b2018-04-09 18:26:47 +08002917#ifndef HAVE_LIBPYTHON_SUPPORT
Feng Tange5f37052012-09-07 16:42:26 +08002918 if (strstr(lang_path, "python"))
2919 continue;
2920#endif
2921
2922 lang_dir = opendir(lang_path);
2923 if (!lang_dir)
2924 continue;
2925
Arnaldo Carvalho de Meloa5e8e822016-04-08 11:25:59 -03002926 for_each_script(lang_path, lang_dir, script_dirent) {
Feng Tange5f37052012-09-07 16:42:26 +08002927 /* Skip those real time scripts: xxxtop.p[yl] */
Arnaldo Carvalho de Meloa5e8e822016-04-08 11:25:59 -03002928 if (strstr(script_dirent->d_name, "top."))
Feng Tange5f37052012-09-07 16:42:26 +08002929 continue;
2930 sprintf(scripts_path_array[i], "%s/%s", lang_path,
Arnaldo Carvalho de Meloa5e8e822016-04-08 11:25:59 -03002931 script_dirent->d_name);
2932 temp = strchr(script_dirent->d_name, '.');
Feng Tange5f37052012-09-07 16:42:26 +08002933 snprintf(scripts_array[i],
Arnaldo Carvalho de Meloa5e8e822016-04-08 11:25:59 -03002934 (temp - script_dirent->d_name) + 1,
2935 "%s", script_dirent->d_name);
Feng Tang49e639e2012-10-30 11:56:03 +08002936
2937 if (check_ev_match(lang_path,
2938 scripts_array[i], session))
2939 continue;
2940
Feng Tange5f37052012-09-07 16:42:26 +08002941 i++;
2942 }
Feng Tang49e639e2012-10-30 11:56:03 +08002943 closedir(lang_dir);
Feng Tange5f37052012-09-07 16:42:26 +08002944 }
2945
Feng Tang49e639e2012-10-30 11:56:03 +08002946 closedir(scripts_dir);
2947 perf_session__delete(session);
Feng Tange5f37052012-09-07 16:42:26 +08002948 return i;
2949}
2950
Tom Zanussi38752942009-12-15 02:53:39 -06002951static char *get_script_path(const char *script_root, const char *suffix)
2952{
Arnaldo Carvalho de Meloa5e8e822016-04-08 11:25:59 -03002953 struct dirent *script_dirent, *lang_dirent;
Tom Zanussi38752942009-12-15 02:53:39 -06002954 char scripts_path[MAXPATHLEN];
2955 char script_path[MAXPATHLEN];
2956 DIR *scripts_dir, *lang_dir;
2957 char lang_path[MAXPATHLEN];
Robert Richter38efb532011-11-25 11:38:40 +01002958 char *__script_root;
Tom Zanussi38752942009-12-15 02:53:39 -06002959
Josh Poimboeuf46113a52015-12-15 09:39:37 -06002960 snprintf(scripts_path, MAXPATHLEN, "%s/scripts", get_argv_exec_path());
Tom Zanussi38752942009-12-15 02:53:39 -06002961
2962 scripts_dir = opendir(scripts_path);
2963 if (!scripts_dir)
2964 return NULL;
2965
Arnaldo Carvalho de Meloa5e8e822016-04-08 11:25:59 -03002966 for_each_lang(scripts_path, scripts_dir, lang_dirent) {
Jiri Olsa77f18152018-03-19 09:29:01 +01002967 scnprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path,
2968 lang_dirent->d_name);
Tom Zanussi38752942009-12-15 02:53:39 -06002969 lang_dir = opendir(lang_path);
2970 if (!lang_dir)
2971 continue;
2972
Arnaldo Carvalho de Meloa5e8e822016-04-08 11:25:59 -03002973 for_each_script(lang_path, lang_dir, script_dirent) {
2974 __script_root = get_script_root(script_dirent, suffix);
Robert Richter38efb532011-11-25 11:38:40 +01002975 if (__script_root && !strcmp(script_root, __script_root)) {
2976 free(__script_root);
Namhyung Kim946ef2a2012-01-08 02:25:25 +09002977 closedir(lang_dir);
2978 closedir(scripts_dir);
Jiri Olsa77f18152018-03-19 09:29:01 +01002979 scnprintf(script_path, MAXPATHLEN, "%s/%s",
2980 lang_path, script_dirent->d_name);
Robert Richter38efb532011-11-25 11:38:40 +01002981 return strdup(script_path);
Tom Zanussi38752942009-12-15 02:53:39 -06002982 }
2983 free(__script_root);
2984 }
Namhyung Kim946ef2a2012-01-08 02:25:25 +09002985 closedir(lang_dir);
Tom Zanussi38752942009-12-15 02:53:39 -06002986 }
Namhyung Kim946ef2a2012-01-08 02:25:25 +09002987 closedir(scripts_dir);
Tom Zanussi38752942009-12-15 02:53:39 -06002988
Robert Richter38efb532011-11-25 11:38:40 +01002989 return NULL;
Tom Zanussi38752942009-12-15 02:53:39 -06002990}
2991
Tom Zanussib5b87312010-11-10 08:16:51 -06002992static bool is_top_script(const char *script_path)
2993{
Stephane Eranian965bb6b2010-12-03 17:52:01 +02002994 return ends_with(script_path, "top") == NULL ? false : true;
Tom Zanussib5b87312010-11-10 08:16:51 -06002995}
2996
2997static int has_required_arg(char *script_path)
2998{
2999 struct script_desc *desc;
3000 int n_args = 0;
3001 char *p;
3002
3003 desc = script_desc__new(NULL);
3004
3005 if (read_script_info(desc, script_path))
3006 goto out;
3007
3008 if (!desc->args)
3009 goto out;
3010
3011 for (p = desc->args; *p; p++)
3012 if (*p == '<')
3013 n_args++;
3014out:
3015 script_desc__delete(desc);
3016
3017 return n_args;
3018}
3019
David Ahernd54b1a92012-08-26 12:24:46 -06003020static int have_cmd(int argc, const char **argv)
Tom Zanussi34c86ea2010-11-10 08:15:43 -06003021{
3022 char **__argv = malloc(sizeof(const char *) * argc);
3023
David Ahernd54b1a92012-08-26 12:24:46 -06003024 if (!__argv) {
3025 pr_err("malloc failed\n");
3026 return -1;
3027 }
3028
Tom Zanussi34c86ea2010-11-10 08:15:43 -06003029 memcpy(__argv, argv, sizeof(const char *) * argc);
3030 argc = parse_options(argc, (const char **)__argv, record_options,
3031 NULL, PARSE_OPT_STOP_AT_NON_OPTION);
3032 free(__argv);
3033
David Ahernd54b1a92012-08-26 12:24:46 -06003034 system_wide = (argc == 0);
3035
3036 return 0;
Tom Zanussi34c86ea2010-11-10 08:15:43 -06003037}
3038
Jiri Olsa7322d6c2015-08-13 09:17:24 +02003039static void script__setup_sample_type(struct perf_script *script)
3040{
3041 struct perf_session *session = script->session;
3042 u64 sample_type = perf_evlist__combined_sample_type(session->evlist);
3043
3044 if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain) {
3045 if ((sample_type & PERF_SAMPLE_REGS_USER) &&
Arnaldo Carvalho de Meloeabad8c2018-01-15 16:48:46 -03003046 (sample_type & PERF_SAMPLE_STACK_USER)) {
Jiri Olsa7322d6c2015-08-13 09:17:24 +02003047 callchain_param.record_mode = CALLCHAIN_DWARF;
Arnaldo Carvalho de Meloeabad8c2018-01-15 16:48:46 -03003048 dwarf_callchain_users = true;
3049 } else if (sample_type & PERF_SAMPLE_BRANCH_STACK)
Jiri Olsa7322d6c2015-08-13 09:17:24 +02003050 callchain_param.record_mode = CALLCHAIN_LBR;
3051 else
3052 callchain_param.record_mode = CALLCHAIN_FP;
3053 }
3054}
3055
Jiri Olsa89f16882018-09-13 14:54:03 +02003056static int process_stat_round_event(struct perf_session *session,
3057 union perf_event *event)
Jiri Olsae099eba2016-01-05 22:09:09 +01003058{
3059 struct stat_round_event *round = &event->stat_round;
3060 struct perf_evsel *counter;
3061
Arnaldo Carvalho de Meloe5cadb92016-06-23 11:26:15 -03003062 evlist__for_each_entry(session->evlist, counter) {
Jiri Olsae099eba2016-01-05 22:09:09 +01003063 perf_stat_process_counter(&stat_config, counter);
3064 process_stat(counter, round->time);
3065 }
3066
3067 process_stat_interval(round->time);
3068 return 0;
3069}
3070
Jiri Olsa89f16882018-09-13 14:54:03 +02003071static int process_stat_config_event(struct perf_session *session __maybe_unused,
3072 union perf_event *event)
Jiri Olsa91a2c3d2016-01-05 22:09:07 +01003073{
3074 perf_event__read_stat_config(&stat_config, &event->stat_config);
3075 return 0;
3076}
3077
Jiri Olsacfc88742016-01-05 22:09:06 +01003078static int set_maps(struct perf_script *script)
3079{
3080 struct perf_evlist *evlist = script->session->evlist;
3081
3082 if (!script->cpus || !script->threads)
3083 return 0;
3084
3085 if (WARN_ONCE(script->allocated, "stats double allocation\n"))
3086 return -EINVAL;
3087
3088 perf_evlist__set_maps(evlist, script->cpus, script->threads);
3089
3090 if (perf_evlist__alloc_stats(evlist, true))
3091 return -ENOMEM;
3092
3093 script->allocated = true;
3094 return 0;
3095}
3096
3097static
Jiri Olsa89f16882018-09-13 14:54:03 +02003098int process_thread_map_event(struct perf_session *session,
3099 union perf_event *event)
Jiri Olsacfc88742016-01-05 22:09:06 +01003100{
Jiri Olsa89f16882018-09-13 14:54:03 +02003101 struct perf_tool *tool = session->tool;
Jiri Olsacfc88742016-01-05 22:09:06 +01003102 struct perf_script *script = container_of(tool, struct perf_script, tool);
3103
3104 if (script->threads) {
3105 pr_warning("Extra thread map event, ignoring.\n");
3106 return 0;
3107 }
3108
3109 script->threads = thread_map__new_event(&event->thread_map);
3110 if (!script->threads)
3111 return -ENOMEM;
3112
3113 return set_maps(script);
3114}
3115
3116static
Jiri Olsa89f16882018-09-13 14:54:03 +02003117int process_cpu_map_event(struct perf_session *session,
3118 union perf_event *event)
Jiri Olsacfc88742016-01-05 22:09:06 +01003119{
Jiri Olsa89f16882018-09-13 14:54:03 +02003120 struct perf_tool *tool = session->tool;
Jiri Olsacfc88742016-01-05 22:09:06 +01003121 struct perf_script *script = container_of(tool, struct perf_script, tool);
3122
3123 if (script->cpus) {
3124 pr_warning("Extra cpu map event, ignoring.\n");
3125 return 0;
3126 }
3127
3128 script->cpus = cpu_map__new_data(&event->cpu_map.data);
3129 if (!script->cpus)
3130 return -ENOMEM;
3131
3132 return set_maps(script);
3133}
3134
Jiri Olsa89f16882018-09-13 14:54:03 +02003135static int process_feature_event(struct perf_session *session,
3136 union perf_event *event)
Ravi Bangoria92ead7e2018-06-25 18:12:20 +05303137{
3138 if (event->feat.feat_id < HEADER_LAST_FEATURE)
Jiri Olsa89f16882018-09-13 14:54:03 +02003139 return perf_event__process_feature(session, event);
Ravi Bangoria92ead7e2018-06-25 18:12:20 +05303140 return 0;
3141}
3142
Arnaldo Carvalho de Melofa48c892017-11-09 16:04:26 -03003143#ifdef HAVE_AUXTRACE_SUPPORT
Jiri Olsa89f16882018-09-13 14:54:03 +02003144static int perf_script__process_auxtrace_info(struct perf_session *session,
3145 union perf_event *event)
Arnaldo Carvalho de Melofa48c892017-11-09 16:04:26 -03003146{
Jiri Olsa89f16882018-09-13 14:54:03 +02003147 struct perf_tool *tool = session->tool;
3148
3149 int ret = perf_event__process_auxtrace_info(session, event);
Arnaldo Carvalho de Melofa48c892017-11-09 16:04:26 -03003150
3151 if (ret == 0) {
3152 struct perf_script *script = container_of(tool, struct perf_script, tool);
3153
3154 ret = perf_script__setup_per_event_dump(script);
3155 }
3156
3157 return ret;
3158}
3159#else
3160#define perf_script__process_auxtrace_info 0
3161#endif
3162
Andi Kleenb585ebd2018-09-20 11:05:36 -07003163static int parse_insn_trace(const struct option *opt __maybe_unused,
3164 const char *str __maybe_unused,
3165 int unset __maybe_unused)
3166{
3167 parse_output_fields(NULL, "+insn,-event,-period", 0);
3168 itrace_parse_synth_opts(opt, "i0ns", 0);
3169 nanosecs = true;
3170 return 0;
3171}
3172
3173static int parse_xed(const struct option *opt __maybe_unused,
3174 const char *str __maybe_unused,
3175 int unset __maybe_unused)
3176{
3177 force_pager("xed -F insn: -A -64 | less");
3178 return 0;
3179}
3180
Andi Kleend1b15522018-09-20 11:05:38 -07003181static int parse_call_trace(const struct option *opt __maybe_unused,
3182 const char *str __maybe_unused,
3183 int unset __maybe_unused)
3184{
3185 parse_output_fields(NULL, "-ip,-addr,-event,-period,+callindent", 0);
3186 itrace_parse_synth_opts(opt, "cewp", 0);
3187 nanosecs = true;
3188 return 0;
3189}
3190
3191static int parse_callret_trace(const struct option *opt __maybe_unused,
3192 const char *str __maybe_unused,
3193 int unset __maybe_unused)
3194{
3195 parse_output_fields(NULL, "-ip,-addr,-event,-period,+callindent,+flags", 0);
3196 itrace_parse_synth_opts(opt, "crewp", 0);
3197 nanosecs = true;
3198 return 0;
3199}
3200
Arnaldo Carvalho de Melob0ad8ea2017-03-27 11:47:20 -03003201int cmd_script(int argc, const char **argv)
Frederic Weisbecker5f9c39d2009-08-17 16:18:08 +02003202{
Arnaldo Carvalho de Melo69b64702012-10-01 15:20:58 -03003203 bool show_full_info = false;
Jiri Olsae90debd2013-12-09 11:02:50 +01003204 bool header = false;
3205 bool header_only = false;
Namhyung Kim6cc870f2014-08-12 15:40:33 +09003206 bool script_started = false;
Tom Zanussib5b87312010-11-10 08:16:51 -06003207 char *rec_script_path = NULL;
3208 char *rep_script_path = NULL;
Arnaldo Carvalho de Melod8f66242009-12-13 19:50:24 -02003209 struct perf_session *session;
Andi Kleen4eb06812018-09-20 11:05:37 -07003210 struct itrace_synth_opts itrace_synth_opts = {
3211 .set = false,
3212 .default_no_sample = true,
3213 };
Tom Zanussib5b87312010-11-10 08:16:51 -06003214 char *script_path = NULL;
Tom Zanussi38752942009-12-15 02:53:39 -06003215 const char **__argv;
Namhyung Kim6cc870f2014-08-12 15:40:33 +09003216 int i, j, err = 0;
Adrian Hunter6f3e5ed2013-10-22 10:34:07 +03003217 struct perf_script script = {
3218 .tool = {
3219 .sample = process_sample_event,
3220 .mmap = perf_event__process_mmap,
3221 .mmap2 = perf_event__process_mmap2,
3222 .comm = perf_event__process_comm,
Hari Bathinif3b36142017-03-08 02:11:43 +05303223 .namespaces = perf_event__process_namespaces,
Adrian Hunter6f3e5ed2013-10-22 10:34:07 +03003224 .exit = perf_event__process_exit,
3225 .fork = perf_event__process_fork,
Adrian Hunter7ea95722013-11-01 15:51:30 +02003226 .attr = process_attr,
Jiri Olsa91daee32016-04-07 09:11:13 +02003227 .event_update = perf_event__process_event_update,
Adrian Hunter6f3e5ed2013-10-22 10:34:07 +03003228 .tracing_data = perf_event__process_tracing_data,
Ravi Bangoria92ead7e2018-06-25 18:12:20 +05303229 .feature = process_feature_event,
Adrian Hunter6f3e5ed2013-10-22 10:34:07 +03003230 .build_id = perf_event__process_build_id,
Adrian Hunter7a680eb2015-04-09 18:53:56 +03003231 .id_index = perf_event__process_id_index,
Arnaldo Carvalho de Melofa48c892017-11-09 16:04:26 -03003232 .auxtrace_info = perf_script__process_auxtrace_info,
Adrian Hunter7a680eb2015-04-09 18:53:56 +03003233 .auxtrace = perf_event__process_auxtrace,
3234 .auxtrace_error = perf_event__process_auxtrace_error,
Jiri Olsae099eba2016-01-05 22:09:09 +01003235 .stat = perf_event__process_stat_event,
3236 .stat_round = process_stat_round_event,
Jiri Olsa91a2c3d2016-01-05 22:09:07 +01003237 .stat_config = process_stat_config_event,
Jiri Olsacfc88742016-01-05 22:09:06 +01003238 .thread_map = process_thread_map_event,
3239 .cpu_map = process_cpu_map_event,
Jiri Olsa0a8cb852014-07-06 14:18:21 +02003240 .ordered_events = true,
Adrian Hunter6f3e5ed2013-10-22 10:34:07 +03003241 .ordering_requires_timestamps = true,
3242 },
3243 };
Jiri Olsa8ceb41d2017-01-23 22:07:59 +01003244 struct perf_data data = {
Yunlong Song06af0f22015-04-02 21:47:16 +08003245 .mode = PERF_DATA_MODE_READ,
3246 };
Arnaldo Carvalho de Melo69b64702012-10-01 15:20:58 -03003247 const struct option options[] = {
3248 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
3249 "dump raw trace in ASCII"),
3250 OPT_INCR('v', "verbose", &verbose,
3251 "be more verbose (show symbol address, etc)"),
3252 OPT_BOOLEAN('L', "Latency", &latency_format,
3253 "show latency attributes (irqs/preemption disabled, etc)"),
3254 OPT_CALLBACK_NOOPT('l', "list", NULL, NULL, "list available scripts",
3255 list_available_scripts),
3256 OPT_CALLBACK('s', "script", NULL, "name",
3257 "script file name (lang:script name, script name, or *)",
3258 parse_scriptname),
3259 OPT_STRING('g', "gen-script", &generate_script_lang, "lang",
3260 "generate perf-script.xx script in specified language"),
3261 OPT_STRING('i', "input", &input_name, "file", "input file name"),
3262 OPT_BOOLEAN('d', "debug-mode", &debug_mode,
3263 "do various checks like samples ordering and lost events"),
Jiri Olsae90debd2013-12-09 11:02:50 +01003264 OPT_BOOLEAN(0, "header", &header, "Show data header."),
3265 OPT_BOOLEAN(0, "header-only", &header_only, "Show only data header."),
Arnaldo Carvalho de Melo69b64702012-10-01 15:20:58 -03003266 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
3267 "file", "vmlinux pathname"),
3268 OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name,
3269 "file", "kallsyms pathname"),
3270 OPT_BOOLEAN('G', "hide-call-graph", &no_callchain,
3271 "When printing symbols do not display call chain"),
He Kuanga7066702016-05-19 11:47:37 +00003272 OPT_CALLBACK(0, "symfs", NULL, "directory",
3273 "Look for files with symbols relative to this directory",
3274 symbol__config_symfs),
Yunlong Song06af0f22015-04-02 21:47:16 +08003275 OPT_CALLBACK('F', "fields", NULL, "str",
Arnaldo Carvalho de Melo69b64702012-10-01 15:20:58 -03003276 "comma separated output fields prepend with 'type:'. "
Andi Kleen36ce5652017-06-02 08:48:10 -07003277 "+field to add and -field to remove."
Adrian Hunter14057202017-06-21 13:17:19 +03003278 "Valid types: hw,sw,trace,raw,synth. "
Arnaldo Carvalho de Melo69b64702012-10-01 15:20:58 -03003279 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,"
Ravi Bangoria10e9cec2018-06-25 18:12:18 +05303280 "addr,symoff,srcline,period,iregs,uregs,brstack,"
3281 "brstacksym,flags,bpf-output,brstackinsn,brstackoff,"
3282 "callindent,insn,insnlen,synth,phys_addr,metric,misc",
Andi Kleen48d02a12017-02-23 15:46:34 -08003283 parse_output_fields),
Arnaldo Carvalho de Melo69b64702012-10-01 15:20:58 -03003284 OPT_BOOLEAN('a', "all-cpus", &system_wide,
3285 "system-wide collection from all CPUs"),
3286 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
3287 "only consider these symbols"),
Andi Kleenb585ebd2018-09-20 11:05:36 -07003288 OPT_CALLBACK_OPTARG(0, "insn-trace", &itrace_synth_opts, NULL, NULL,
3289 "Decode instructions from itrace", parse_insn_trace),
3290 OPT_CALLBACK_OPTARG(0, "xed", NULL, NULL, NULL,
3291 "Run xed disassembler on output", parse_xed),
Andi Kleend1b15522018-09-20 11:05:38 -07003292 OPT_CALLBACK_OPTARG(0, "call-trace", &itrace_synth_opts, NULL, NULL,
3293 "Decode calls from from itrace", parse_call_trace),
3294 OPT_CALLBACK_OPTARG(0, "call-ret-trace", &itrace_synth_opts, NULL, NULL,
3295 "Decode calls and returns from itrace", parse_callret_trace),
Andi Kleen99f753f2018-09-20 11:05:39 -07003296 OPT_STRING(0, "graph-function", &symbol_conf.graph_function, "symbol[,symbol...]",
3297 "Only print symbols and callees with --call-trace/--call-ret-trace"),
David Ahern64eff7d2016-11-25 13:00:21 -07003298 OPT_STRING(0, "stop-bt", &symbol_conf.bt_stop_list_str, "symbol[,symbol...]",
3299 "Stop display of callgraph at these symbols"),
Arnaldo Carvalho de Melo69b64702012-10-01 15:20:58 -03003300 OPT_STRING('C', "cpu", &cpu_list, "cpu", "list of cpus to profile"),
3301 OPT_STRING('c', "comms", &symbol_conf.comm_list_str, "comm[,comm...]",
3302 "only display events for these comms"),
David Aherne03eaa42015-03-24 09:52:41 -06003303 OPT_STRING(0, "pid", &symbol_conf.pid_list_str, "pid[,pid...]",
3304 "only consider symbols in these pids"),
3305 OPT_STRING(0, "tid", &symbol_conf.tid_list_str, "tid[,tid...]",
3306 "only consider symbols in these tids"),
Arnaldo Carvalho de Melo6125cc82016-04-14 18:15:18 -03003307 OPT_UINTEGER(0, "max-stack", &scripting_max_stack,
3308 "Set the maximum stack depth when parsing the callchain, "
3309 "anything beyond the specified depth will be ignored. "
Arnaldo Carvalho de Melo4cb93442016-04-27 10:16:24 -03003310 "Default: kernel.perf_event_max_stack or " __stringify(PERF_MAX_STACK_DEPTH)),
Arnaldo Carvalho de Melo69b64702012-10-01 15:20:58 -03003311 OPT_BOOLEAN('I', "show-info", &show_full_info,
3312 "display extended information from perf.data file"),
3313 OPT_BOOLEAN('\0', "show-kernel-path", &symbol_conf.show_kernel_path,
3314 "Show the path of [kernel.kallsyms]"),
Namhyung Kimad7ebb92013-11-26 17:51:12 +09003315 OPT_BOOLEAN('\0', "show-task-events", &script.show_task_events,
3316 "Show the fork/comm/exit events"),
Namhyung Kimba1ddf42013-11-26 17:54:26 +09003317 OPT_BOOLEAN('\0', "show-mmap-events", &script.show_mmap_events,
3318 "Show the mmap events"),
Adrian Hunter7c148982015-07-21 12:44:06 +03003319 OPT_BOOLEAN('\0', "show-switch-events", &script.show_switch_events,
3320 "Show context switch events (if recorded)"),
Hari Bathini96a44bb2017-03-08 02:12:06 +05303321 OPT_BOOLEAN('\0', "show-namespace-events", &script.show_namespace_events,
3322 "Show namespace events (if recorded)"),
Jiri Olsa3d7c27b2018-01-07 17:03:53 +01003323 OPT_BOOLEAN('\0', "show-lost-events", &script.show_lost_events,
3324 "Show lost events (if recorded)"),
Jiri Olsa3233b372018-02-06 19:17:59 +01003325 OPT_BOOLEAN('\0', "show-round-events", &script.show_round_events,
3326 "Show round events (if recorded)"),
Arnaldo Carvalho de Meloa14390f2017-10-26 10:30:20 -03003327 OPT_BOOLEAN('\0', "per-event-dump", &script.per_event_dump,
3328 "Dump trace output to files named by the monitored events"),
Yannick Brosseaube3d4662017-01-13 13:25:27 -05003329 OPT_BOOLEAN('f', "force", &symbol_conf.force, "don't complain, do it"),
Andi Kleen48d02a12017-02-23 15:46:34 -08003330 OPT_INTEGER(0, "max-blocks", &max_blocks,
3331 "Maximum number of code blocks to dump with brstackinsn"),
Adrian Hunter83e19862015-09-25 16:15:36 +03003332 OPT_BOOLEAN(0, "ns", &nanosecs,
3333 "Use 9 decimal places when displaying time"),
Adrian Hunter7a680eb2015-04-09 18:53:56 +03003334 OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts",
Andi Kleenc12e0392018-09-13 20:10:31 -07003335 "Instruction Tracing options\n" ITRACE_HELP,
Adrian Hunter7a680eb2015-04-09 18:53:56 +03003336 itrace_parse_synth_opts),
Andi Kleena9710ba2015-08-07 15:24:05 -07003337 OPT_BOOLEAN(0, "full-source-path", &srcline_full_filename,
3338 "Show full source file name path for source lines"),
Mark Drayton77e00702015-08-26 12:18:15 -07003339 OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle,
3340 "Enable symbol demangling"),
3341 OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel,
3342 "Enable kernel symbol demangling"),
David Aherna91f4c42016-11-29 10:15:43 -07003343 OPT_STRING(0, "time", &script.time_str, "str",
3344 "Time span of interest (start,stop)"),
Namhyung Kim325fbff2017-05-24 15:21:26 +09003345 OPT_BOOLEAN(0, "inline", &symbol_conf.inline_name,
3346 "Show inline function"),
Arnaldo Carvalho de Melo69b64702012-10-01 15:20:58 -03003347 OPT_END()
3348 };
Yunlong Song40cae2b2015-03-18 21:35:54 +08003349 const char * const script_subcommands[] = { "record", "report", NULL };
3350 const char *script_usage[] = {
Arnaldo Carvalho de Melo69b64702012-10-01 15:20:58 -03003351 "perf script [<options>]",
3352 "perf script [<options>] record <script> [<record-options>] <command>",
3353 "perf script [<options>] report <script> [script-args]",
3354 "perf script [<options>] <script> [<record-options>] <command>",
3355 "perf script [<options>] <top-script> [script-args]",
3356 NULL
3357 };
Tom Zanussi38752942009-12-15 02:53:39 -06003358
Arnaldo Carvalho de Melo0a7c74e2017-04-04 13:15:04 -03003359 perf_set_singlethreaded();
3360
Tom Zanussib5b87312010-11-10 08:16:51 -06003361 setup_scripting();
3362
Yunlong Song40cae2b2015-03-18 21:35:54 +08003363 argc = parse_options_subcommand(argc, argv, options, script_subcommands, script_usage,
Tom Zanussib5b87312010-11-10 08:16:51 -06003364 PARSE_OPT_STOP_AT_NON_OPTION);
3365
Jiri Olsaeae8ad82017-01-23 22:25:41 +01003366 data.file.path = input_name;
3367 data.force = symbol_conf.force;
Jiri Olsaf5fc14122013-10-15 16:27:32 +02003368
Tom Zanussib5b87312010-11-10 08:16:51 -06003369 if (argc > 1 && !strncmp(argv[0], "rec", strlen("rec"))) {
3370 rec_script_path = get_script_path(argv[1], RECORD_SUFFIX);
3371 if (!rec_script_path)
Arnaldo Carvalho de Melob0ad8ea2017-03-27 11:47:20 -03003372 return cmd_record(argc, argv);
Tom Zanussi38752942009-12-15 02:53:39 -06003373 }
3374
Tom Zanussib5b87312010-11-10 08:16:51 -06003375 if (argc > 1 && !strncmp(argv[0], "rep", strlen("rep"))) {
3376 rep_script_path = get_script_path(argv[1], REPORT_SUFFIX);
3377 if (!rep_script_path) {
Tom Zanussi38752942009-12-15 02:53:39 -06003378 fprintf(stderr,
Tom Zanussib5b87312010-11-10 08:16:51 -06003379 "Please specify a valid report script"
Ingo Molnar133dc4c2010-11-16 18:45:39 +01003380 "(see 'perf script -l' for listing)\n");
Tom Zanussi38752942009-12-15 02:53:39 -06003381 return -1;
3382 }
Tom Zanussi38752942009-12-15 02:53:39 -06003383 }
3384
Adrian Hunter3c5b6452015-09-25 16:15:51 +03003385 if (itrace_synth_opts.callchain &&
3386 itrace_synth_opts.callchain_sz > scripting_max_stack)
3387 scripting_max_stack = itrace_synth_opts.callchain_sz;
3388
Ben Hutchings44e668c2010-10-10 16:10:03 +01003389 /* make sure PERF_EXEC_PATH is set for scripts */
Josh Poimboeuf46113a52015-12-15 09:39:37 -06003390 set_argv_exec_path(get_argv_exec_path());
Ben Hutchings44e668c2010-10-10 16:10:03 +01003391
Tom Zanussib5b87312010-11-10 08:16:51 -06003392 if (argc && !script_name && !rec_script_path && !rep_script_path) {
Tom Zanussia0cccc22010-04-01 23:59:25 -05003393 int live_pipe[2];
Tom Zanussib5b87312010-11-10 08:16:51 -06003394 int rep_args;
Tom Zanussia0cccc22010-04-01 23:59:25 -05003395 pid_t pid;
3396
Tom Zanussib5b87312010-11-10 08:16:51 -06003397 rec_script_path = get_script_path(argv[0], RECORD_SUFFIX);
3398 rep_script_path = get_script_path(argv[0], REPORT_SUFFIX);
3399
3400 if (!rec_script_path && !rep_script_path) {
Namhyung Kimc7118362015-10-25 00:49:27 +09003401 usage_with_options_msg(script_usage, options,
3402 "Couldn't find script `%s'\n\n See perf"
Ingo Molnar133dc4c2010-11-16 18:45:39 +01003403 " script -l for available scripts.\n", argv[0]);
Tom Zanussia0cccc22010-04-01 23:59:25 -05003404 }
3405
Tom Zanussib5b87312010-11-10 08:16:51 -06003406 if (is_top_script(argv[0])) {
3407 rep_args = argc - 1;
3408 } else {
3409 int rec_args;
3410
3411 rep_args = has_required_arg(rep_script_path);
3412 rec_args = (argc - 1) - rep_args;
3413 if (rec_args < 0) {
Namhyung Kimc7118362015-10-25 00:49:27 +09003414 usage_with_options_msg(script_usage, options,
3415 "`%s' script requires options."
Ingo Molnar133dc4c2010-11-16 18:45:39 +01003416 "\n\n See perf script -l for available "
Tom Zanussib5b87312010-11-10 08:16:51 -06003417 "scripts and options.\n", argv[0]);
Tom Zanussib5b87312010-11-10 08:16:51 -06003418 }
Tom Zanussia0cccc22010-04-01 23:59:25 -05003419 }
3420
3421 if (pipe(live_pipe) < 0) {
3422 perror("failed to create pipe");
David Ahernd54b1a92012-08-26 12:24:46 -06003423 return -1;
Tom Zanussia0cccc22010-04-01 23:59:25 -05003424 }
3425
3426 pid = fork();
3427 if (pid < 0) {
3428 perror("failed to fork");
David Ahernd54b1a92012-08-26 12:24:46 -06003429 return -1;
Tom Zanussia0cccc22010-04-01 23:59:25 -05003430 }
3431
3432 if (!pid) {
Tom Zanussib5b87312010-11-10 08:16:51 -06003433 j = 0;
3434
Tom Zanussia0cccc22010-04-01 23:59:25 -05003435 dup2(live_pipe[1], 1);
3436 close(live_pipe[0]);
3437
Robert Richter317df652011-11-25 15:05:25 +01003438 if (is_top_script(argv[0])) {
3439 system_wide = true;
3440 } else if (!system_wide) {
David Ahernd54b1a92012-08-26 12:24:46 -06003441 if (have_cmd(argc - rep_args, &argv[rep_args]) != 0) {
3442 err = -1;
3443 goto out;
3444 }
Robert Richter317df652011-11-25 15:05:25 +01003445 }
Tom Zanussib5b87312010-11-10 08:16:51 -06003446
3447 __argv = malloc((argc + 6) * sizeof(const char *));
David Ahernd54b1a92012-08-26 12:24:46 -06003448 if (!__argv) {
3449 pr_err("malloc failed\n");
3450 err = -ENOMEM;
3451 goto out;
3452 }
Tom Zanussie8719ad2010-11-10 07:52:32 -06003453
Tom Zanussib5b87312010-11-10 08:16:51 -06003454 __argv[j++] = "/bin/sh";
3455 __argv[j++] = rec_script_path;
3456 if (system_wide)
3457 __argv[j++] = "-a";
3458 __argv[j++] = "-q";
3459 __argv[j++] = "-o";
3460 __argv[j++] = "-";
3461 for (i = rep_args + 1; i < argc; i++)
3462 __argv[j++] = argv[i];
3463 __argv[j++] = NULL;
Tom Zanussia0cccc22010-04-01 23:59:25 -05003464
3465 execvp("/bin/sh", (char **)__argv);
Tom Zanussie8719ad2010-11-10 07:52:32 -06003466 free(__argv);
Tom Zanussia0cccc22010-04-01 23:59:25 -05003467 exit(-1);
3468 }
3469
3470 dup2(live_pipe[0], 0);
3471 close(live_pipe[1]);
3472
Tom Zanussib5b87312010-11-10 08:16:51 -06003473 __argv = malloc((argc + 4) * sizeof(const char *));
David Ahernd54b1a92012-08-26 12:24:46 -06003474 if (!__argv) {
3475 pr_err("malloc failed\n");
3476 err = -ENOMEM;
3477 goto out;
3478 }
3479
Tom Zanussib5b87312010-11-10 08:16:51 -06003480 j = 0;
Tom Zanussi34c86ea2010-11-10 08:15:43 -06003481 __argv[j++] = "/bin/sh";
Tom Zanussib5b87312010-11-10 08:16:51 -06003482 __argv[j++] = rep_script_path;
3483 for (i = 1; i < rep_args + 1; i++)
Tom Zanussi34c86ea2010-11-10 08:15:43 -06003484 __argv[j++] = argv[i];
Tom Zanussib5b87312010-11-10 08:16:51 -06003485 __argv[j++] = "-i";
3486 __argv[j++] = "-";
Tom Zanussi34c86ea2010-11-10 08:15:43 -06003487 __argv[j++] = NULL;
Tom Zanussi38752942009-12-15 02:53:39 -06003488
3489 execvp("/bin/sh", (char **)__argv);
Tom Zanussie8719ad2010-11-10 07:52:32 -06003490 free(__argv);
Tom Zanussi38752942009-12-15 02:53:39 -06003491 exit(-1);
3492 }
Tom Zanussi956ffd02009-11-25 01:15:46 -06003493
Tom Zanussib5b87312010-11-10 08:16:51 -06003494 if (rec_script_path)
3495 script_path = rec_script_path;
3496 if (rep_script_path)
3497 script_path = rep_script_path;
Tom Zanussi956ffd02009-11-25 01:15:46 -06003498
Tom Zanussib5b87312010-11-10 08:16:51 -06003499 if (script_path) {
Tom Zanussib5b87312010-11-10 08:16:51 -06003500 j = 0;
3501
Robert Richter317df652011-11-25 15:05:25 +01003502 if (!rec_script_path)
3503 system_wide = false;
David Ahernd54b1a92012-08-26 12:24:46 -06003504 else if (!system_wide) {
3505 if (have_cmd(argc - 1, &argv[1]) != 0) {
3506 err = -1;
3507 goto out;
3508 }
3509 }
Tom Zanussib5b87312010-11-10 08:16:51 -06003510
3511 __argv = malloc((argc + 2) * sizeof(const char *));
David Ahernd54b1a92012-08-26 12:24:46 -06003512 if (!__argv) {
3513 pr_err("malloc failed\n");
3514 err = -ENOMEM;
3515 goto out;
3516 }
3517
Tom Zanussib5b87312010-11-10 08:16:51 -06003518 __argv[j++] = "/bin/sh";
3519 __argv[j++] = script_path;
3520 if (system_wide)
3521 __argv[j++] = "-a";
3522 for (i = 2; i < argc; i++)
3523 __argv[j++] = argv[i];
3524 __argv[j++] = NULL;
3525
3526 execvp("/bin/sh", (char **)__argv);
3527 free(__argv);
3528 exit(-1);
3529 }
Frederic Weisbecker5f9c39d2009-08-17 16:18:08 +02003530
Milian Wolffc1c9b962018-10-21 21:14:23 +02003531 if (!script_name) {
Tom Zanussicf4fee52010-03-03 01:04:33 -06003532 setup_pager();
Milian Wolffc1c9b962018-10-21 21:14:23 +02003533 use_browser = 0;
3534 }
Frederic Weisbecker5f9c39d2009-08-17 16:18:08 +02003535
Jiri Olsa8ceb41d2017-01-23 22:07:59 +01003536 session = perf_session__new(&data, false, &script.tool);
Arnaldo Carvalho de Melod8f66242009-12-13 19:50:24 -02003537 if (session == NULL)
Taeung Song52e028342014-09-24 10:33:37 +09003538 return -1;
Arnaldo Carvalho de Melod8f66242009-12-13 19:50:24 -02003539
Jiri Olsae90debd2013-12-09 11:02:50 +01003540 if (header || header_only) {
David Carrillo-Cisneros114f7092017-07-17 21:25:47 -07003541 script.tool.show_feat_hdr = SHOW_FEAT_HEADER;
Jiri Olsae90debd2013-12-09 11:02:50 +01003542 perf_session__fprintf_info(session, stdout, show_full_info);
3543 if (header_only)
Namhyung Kim6cc870f2014-08-12 15:40:33 +09003544 goto out_delete;
Jiri Olsae90debd2013-12-09 11:02:50 +01003545 }
David Carrillo-Cisneros114f7092017-07-17 21:25:47 -07003546 if (show_full_info)
3547 script.tool.show_feat_hdr = SHOW_FEAT_HEADER_FULL_INFO;
Jiri Olsae90debd2013-12-09 11:02:50 +01003548
Namhyung Kim0a7e6d12014-08-12 15:40:45 +09003549 if (symbol__init(&session->header.env) < 0)
Namhyung Kim38520dc2014-08-12 15:40:42 +09003550 goto out_delete;
3551
Adrian Hunter6f3e5ed2013-10-22 10:34:07 +03003552 script.session = session;
Jiri Olsa7322d6c2015-08-13 09:17:24 +02003553 script__setup_sample_type(&script);
Adrian Hunter6f3e5ed2013-10-22 10:34:07 +03003554
Andi Kleen99f753f2018-09-20 11:05:39 -07003555 if ((output[PERF_TYPE_HARDWARE].fields & PERF_OUTPUT_CALLINDENT) ||
3556 symbol_conf.graph_function)
Adrian Huntere2167082016-06-23 16:40:58 +03003557 itrace_synth_opts.thread_stack = true;
3558
Adrian Hunter7a680eb2015-04-09 18:53:56 +03003559 session->itrace_synth_opts = &itrace_synth_opts;
3560
Anton Blanchard5d67be92011-07-04 21:57:50 +10003561 if (cpu_list) {
Namhyung Kim6cc870f2014-08-12 15:40:33 +09003562 err = perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap);
3563 if (err < 0)
3564 goto out_delete;
Adrian Hunter644e0842017-05-26 11:17:38 +03003565 itrace_synth_opts.cpu_bitmap = cpu_bitmap;
Anton Blanchard5d67be92011-07-04 21:57:50 +10003566 }
3567
David Ahern1424dc92011-03-09 22:23:28 -07003568 if (!no_callchain)
David Ahernc0230b22011-03-09 22:23:27 -07003569 symbol_conf.use_callchain = true;
3570 else
3571 symbol_conf.use_callchain = false;
3572
Arnaldo Carvalho de Melo9ee67422015-08-03 16:27:40 -03003573 if (session->tevent.pevent &&
Tzvetomir Stoyanov (VMware)ece2a4f2018-08-08 14:02:55 -04003574 tep_set_function_resolver(session->tevent.pevent,
3575 machine__resolve_kernel_addr,
3576 &session->machines.host) < 0) {
Arnaldo Carvalho de Meloccb3a822015-07-22 16:43:37 -03003577 pr_err("%s: failed to set libtraceevent function resolver\n", __func__);
Christophe JAILLETdb49bc12017-09-16 08:25:37 +02003578 err = -1;
3579 goto out_delete;
Arnaldo Carvalho de Meloccb3a822015-07-22 16:43:37 -03003580 }
3581
Tom Zanussi956ffd02009-11-25 01:15:46 -06003582 if (generate_script_lang) {
3583 struct stat perf_stat;
David Ahern745f43e2011-03-09 22:23:26 -07003584 int input;
Tom Zanussi956ffd02009-11-25 01:15:46 -06003585
David Ahern2c9e45f72011-03-17 10:03:21 -06003586 if (output_set_by_user()) {
David Ahern745f43e2011-03-09 22:23:26 -07003587 fprintf(stderr,
3588 "custom fields not supported for generated scripts");
Namhyung Kim6cc870f2014-08-12 15:40:33 +09003589 err = -EINVAL;
3590 goto out_delete;
David Ahern745f43e2011-03-09 22:23:26 -07003591 }
3592
Jiri Olsaeae8ad82017-01-23 22:25:41 +01003593 input = open(data.file.path, O_RDONLY); /* input_name */
Tom Zanussi956ffd02009-11-25 01:15:46 -06003594 if (input < 0) {
Namhyung Kim6cc870f2014-08-12 15:40:33 +09003595 err = -errno;
Tom Zanussi956ffd02009-11-25 01:15:46 -06003596 perror("failed to open file");
Namhyung Kim6cc870f2014-08-12 15:40:33 +09003597 goto out_delete;
Tom Zanussi956ffd02009-11-25 01:15:46 -06003598 }
3599
3600 err = fstat(input, &perf_stat);
3601 if (err < 0) {
3602 perror("failed to stat file");
Namhyung Kim6cc870f2014-08-12 15:40:33 +09003603 goto out_delete;
Tom Zanussi956ffd02009-11-25 01:15:46 -06003604 }
3605
3606 if (!perf_stat.st_size) {
3607 fprintf(stderr, "zero-sized file, nothing to do!\n");
Namhyung Kim6cc870f2014-08-12 15:40:33 +09003608 goto out_delete;
Tom Zanussi956ffd02009-11-25 01:15:46 -06003609 }
3610
3611 scripting_ops = script_spec__lookup(generate_script_lang);
3612 if (!scripting_ops) {
3613 fprintf(stderr, "invalid language specifier");
Namhyung Kim6cc870f2014-08-12 15:40:33 +09003614 err = -ENOENT;
3615 goto out_delete;
Tom Zanussi956ffd02009-11-25 01:15:46 -06003616 }
3617
Jiri Olsa29f5ffd2013-12-03 14:09:23 +01003618 err = scripting_ops->generate_script(session->tevent.pevent,
Arnaldo Carvalho de Meloda378962012-06-27 13:08:42 -03003619 "perf-script");
Namhyung Kim6cc870f2014-08-12 15:40:33 +09003620 goto out_delete;
Tom Zanussi956ffd02009-11-25 01:15:46 -06003621 }
3622
3623 if (script_name) {
Tom Zanussi586bc5c2009-12-15 02:53:35 -06003624 err = scripting_ops->start_script(script_name, argc, argv);
Tom Zanussi956ffd02009-11-25 01:15:46 -06003625 if (err)
Namhyung Kim6cc870f2014-08-12 15:40:33 +09003626 goto out_delete;
Ingo Molnar133dc4c2010-11-16 18:45:39 +01003627 pr_debug("perf script started with script %s\n\n", script_name);
Namhyung Kim6cc870f2014-08-12 15:40:33 +09003628 script_started = true;
Tom Zanussi956ffd02009-11-25 01:15:46 -06003629 }
3630
David Ahern9cbdb702011-04-06 21:54:20 -06003631
3632 err = perf_session__check_output_opt(session);
3633 if (err < 0)
Namhyung Kim6cc870f2014-08-12 15:40:33 +09003634 goto out_delete;
David Ahern9cbdb702011-04-06 21:54:20 -06003635
Jin Yaocc2ef582018-01-10 23:00:33 +08003636 script.ptime_range = perf_time__range_alloc(script.time_str,
3637 &script.range_size);
3638 if (!script.ptime_range) {
3639 err = -ENOMEM;
3640 goto out_delete;
3641 }
3642
David Aherna91f4c42016-11-29 10:15:43 -07003643 /* needs to be parsed after looking up reference time */
Jin Yao2ab046c2017-12-08 21:13:46 +08003644 if (perf_time__parse_str(script.ptime_range, script.time_str) != 0) {
3645 if (session->evlist->first_sample_time == 0 &&
3646 session->evlist->last_sample_time == 0) {
Jin Yao1e2778e2018-01-10 23:00:27 +08003647 pr_err("HINT: no first/last sample time found in perf data.\n"
3648 "Please use latest perf binary to execute 'perf record'\n"
3649 "(if '--buildid-all' is enabled, please set '--timestamp-boundary').\n");
Jin Yao2ab046c2017-12-08 21:13:46 +08003650 err = -EINVAL;
3651 goto out_delete;
3652 }
3653
3654 script.range_num = perf_time__percent_parse_str(
Jin Yaocc2ef582018-01-10 23:00:33 +08003655 script.ptime_range, script.range_size,
Jin Yao2ab046c2017-12-08 21:13:46 +08003656 script.time_str,
3657 session->evlist->first_sample_time,
3658 session->evlist->last_sample_time);
3659
3660 if (script.range_num < 0) {
3661 pr_err("Invalid time string\n");
3662 err = -EINVAL;
3663 goto out_delete;
3664 }
3665 } else {
3666 script.range_num = 1;
David Aherna91f4c42016-11-29 10:15:43 -07003667 }
3668
Adrian Hunter6f3e5ed2013-10-22 10:34:07 +03003669 err = __cmd_script(&script);
Tom Zanussi956ffd02009-11-25 01:15:46 -06003670
Adrian Hunterd445dd22014-08-15 22:08:37 +03003671 flush_scripting();
3672
Namhyung Kim6cc870f2014-08-12 15:40:33 +09003673out_delete:
Jin Yaocc2ef582018-01-10 23:00:33 +08003674 zfree(&script.ptime_range);
3675
Jiri Olsacfc88742016-01-05 22:09:06 +01003676 perf_evlist__free_stats(session->evlist);
Arnaldo Carvalho de Melod8f66242009-12-13 19:50:24 -02003677 perf_session__delete(session);
Namhyung Kim6cc870f2014-08-12 15:40:33 +09003678
3679 if (script_started)
3680 cleanup_scripting();
Tom Zanussi956ffd02009-11-25 01:15:46 -06003681out:
3682 return err;
Frederic Weisbecker5f9c39d2009-08-17 16:18:08 +02003683}