blob: 2d8cb1d1682c45210cd8fef5c8a0a646376229e9 [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"
Arnaldo Carvalho de Melo1101f692019-01-27 13:42:37 +010013#include "util/map.h"
Frederic Weisbecker5f9c39d2009-08-17 16:18:08 +020014#include "util/symbol.h"
15#include "util/thread.h"
Ingo Molnarcf723442009-11-28 10:11:00 +010016#include "util/trace-event.h"
Andrea Gelminib7eead82010-08-05 15:51:38 +020017#include "util/util.h"
David Ahern1424dc92011-03-09 22:23:28 -070018#include "util/evlist.h"
19#include "util/evsel.h"
Feng Tang36385be2012-09-07 16:42:24 +080020#include "util/sort.h"
Jiri Olsaf5fc14122013-10-15 16:27:32 +020021#include "util/data.h"
Adrian Hunter7a680eb2015-04-09 18:53:56 +030022#include "util/auxtrace.h"
Jiri Olsacfc88742016-01-05 22:09:06 +010023#include "util/cpumap.h"
24#include "util/thread_map.h"
25#include "util/stat.h"
Andi Kleen4bd1bef2017-11-17 13:43:00 -080026#include "util/color.h"
Arnaldo Carvalho de Meloa0675582017-04-17 16:51:59 -030027#include "util/string2.h"
Adrian Huntere2167082016-06-23 16:40:58 +030028#include "util/thread-stack.h"
David Aherna91f4c42016-11-29 10:15:43 -070029#include "util/time-utils.h"
Jiri Olsa06c3f2a2017-12-06 18:45:35 +010030#include "util/path.h"
Arnaldo Carvalho de Melofea01392017-04-17 16:23:22 -030031#include "print_binary.h"
Anton Blanchard5d67be92011-07-04 21:57:50 +100032#include <linux/bitmap.h>
Arnaldo Carvalho de Melo877a7a12017-04-17 11:39:06 -030033#include <linux/kernel.h>
Arnaldo Carvalho de Melo6125cc82016-04-14 18:15:18 -030034#include <linux/stringify.h>
Arnaldo Carvalho de Melobd48c632016-08-05 15:40:30 -030035#include <linux/time64.h>
Jiri Olsacfc88742016-01-05 22:09:06 +010036#include "asm/bug.h"
Jiri Olsac19ac912016-02-24 09:46:54 +010037#include "util/mem-events.h"
Andi Kleen48d02a12017-02-23 15:46:34 -080038#include "util/dump-insn.h"
Arnaldo Carvalho de Melo76b31a22017-04-18 12:26:44 -030039#include <dirent.h>
Arnaldo Carvalho de Meloa43783a2017-04-18 10:46:11 -030040#include <errno.h>
Arnaldo Carvalho de Melofd20e812017-04-17 15:23:08 -030041#include <inttypes.h>
Arnaldo Carvalho de Melo9607ad32017-04-19 15:49:18 -030042#include <signal.h>
Arnaldo Carvalho de Melo391e4202017-04-19 18:51:14 -030043#include <sys/param.h>
Arnaldo Carvalho de Melo7a8ef4c2017-04-19 20:57:47 -030044#include <sys/types.h>
45#include <sys/stat.h>
Arnaldo Carvalho de Melobafae982018-01-22 16:42:16 -030046#include <fcntl.h>
Arnaldo Carvalho de Melo7a8ef4c2017-04-19 20:57:47 -030047#include <unistd.h>
Andi Kleenb585ebd2018-09-20 11:05:36 -070048#include <subcmd/pager.h>
Frederic Weisbecker5f9c39d2009-08-17 16:18:08 +020049
Arnaldo Carvalho de Melo3d689ed2017-04-17 16:10:49 -030050#include "sane_ctype.h"
51
Tom Zanussi956ffd02009-11-25 01:15:46 -060052static char const *script_name;
53static char const *generate_script_lang;
Frederic Weisbeckerffabd992010-05-27 16:27:47 +020054static bool debug_mode;
Frederic Weisbeckere1889d72010-04-24 01:55:09 +020055static u64 last_timestamp;
Frederic Weisbecker6fcf7dd2010-05-27 15:46:25 +020056static u64 nr_unordered;
David Ahernc0230b22011-03-09 22:23:27 -070057static bool no_callchain;
Namhyung Kim47390ae2013-06-04 14:20:28 +090058static bool latency_format;
Robert Richter317df652011-11-25 15:05:25 +010059static bool system_wide;
Adrian Hunter400ea6d2015-04-09 18:54:05 +030060static bool print_flags;
Adrian Hunter83e19862015-09-25 16:15:36 +030061static bool nanosecs;
Anton Blanchard5d67be92011-07-04 21:57:50 +100062static const char *cpu_list;
63static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
Jiri Olsa91a2c3d2016-01-05 22:09:07 +010064static struct perf_stat_config stat_config;
Andi Kleen48d02a12017-02-23 15:46:34 -080065static int max_blocks;
Tom Zanussi956ffd02009-11-25 01:15:46 -060066
Adrian Hunter44cbe722015-09-25 16:15:50 +030067unsigned int scripting_max_stack = PERF_MAX_STACK_DEPTH;
Adrian Hunter03cd1fe2015-09-25 16:15:49 +030068
David Ahern745f43e2011-03-09 22:23:26 -070069enum perf_output_field {
70 PERF_OUTPUT_COMM = 1U << 0,
71 PERF_OUTPUT_TID = 1U << 1,
72 PERF_OUTPUT_PID = 1U << 2,
73 PERF_OUTPUT_TIME = 1U << 3,
74 PERF_OUTPUT_CPU = 1U << 4,
75 PERF_OUTPUT_EVNAME = 1U << 5,
76 PERF_OUTPUT_TRACE = 1U << 6,
David Ahern787bef12011-05-27 14:28:43 -060077 PERF_OUTPUT_IP = 1U << 7,
78 PERF_OUTPUT_SYM = 1U << 8,
David Ahern610723f2011-05-27 14:28:44 -060079 PERF_OUTPUT_DSO = 1U << 9,
David Ahern7cec0922011-05-30 13:08:23 -060080 PERF_OUTPUT_ADDR = 1U << 10,
Akihiro Nagaia978f2a2012-01-30 13:43:15 +090081 PERF_OUTPUT_SYMOFFSET = 1U << 11,
Adrian Huntercc8fae12013-12-06 09:42:57 +020082 PERF_OUTPUT_SRCLINE = 1U << 12,
Jiri Olsa535aeaae2014-08-25 16:45:42 +020083 PERF_OUTPUT_PERIOD = 1U << 13,
Stephane Eranianfc36f942015-08-31 18:41:10 +020084 PERF_OUTPUT_IREGS = 1U << 14,
Stephane Eraniandc323ce2015-08-31 18:41:13 +020085 PERF_OUTPUT_BRSTACK = 1U << 15,
86 PERF_OUTPUT_BRSTACKSYM = 1U << 16,
Jiri Olsa94ddddf2016-02-15 09:34:51 +010087 PERF_OUTPUT_DATA_SRC = 1U << 17,
88 PERF_OUTPUT_WEIGHT = 1U << 18,
Wang Nan30372f02016-02-24 11:20:45 +000089 PERF_OUTPUT_BPF_OUTPUT = 1U << 19,
Adrian Huntere2167082016-06-23 16:40:58 +030090 PERF_OUTPUT_CALLINDENT = 1U << 20,
Andi Kleen224e2c92016-10-07 16:42:27 +030091 PERF_OUTPUT_INSN = 1U << 21,
92 PERF_OUTPUT_INSNLEN = 1U << 22,
Andi Kleen48d02a12017-02-23 15:46:34 -080093 PERF_OUTPUT_BRSTACKINSN = 1U << 23,
Mark Santaniello106dacd2017-06-19 09:38:25 -070094 PERF_OUTPUT_BRSTACKOFF = 1U << 24,
Adrian Hunter47e78082017-05-26 11:17:22 +030095 PERF_OUTPUT_SYNTH = 1U << 25,
Kan Liang49d58f02017-08-29 13:11:11 -040096 PERF_OUTPUT_PHYS_ADDR = 1U << 26,
Andi Kleenb1491ac2017-09-05 11:40:57 -070097 PERF_OUTPUT_UREGS = 1U << 27,
Andi Kleen4bd1bef2017-11-17 13:43:00 -080098 PERF_OUTPUT_METRIC = 1U << 28,
Jiri Olsa28a0b392018-01-07 17:03:52 +010099 PERF_OUTPUT_MISC = 1U << 29,
Andi Kleendd2e18e2018-12-03 16:18:48 -0800100 PERF_OUTPUT_SRCCODE = 1U << 30,
David Ahern745f43e2011-03-09 22:23:26 -0700101};
102
103struct output_option {
104 const char *str;
105 enum perf_output_field field;
106} all_output_options[] = {
107 {.str = "comm", .field = PERF_OUTPUT_COMM},
108 {.str = "tid", .field = PERF_OUTPUT_TID},
109 {.str = "pid", .field = PERF_OUTPUT_PID},
110 {.str = "time", .field = PERF_OUTPUT_TIME},
111 {.str = "cpu", .field = PERF_OUTPUT_CPU},
112 {.str = "event", .field = PERF_OUTPUT_EVNAME},
113 {.str = "trace", .field = PERF_OUTPUT_TRACE},
David Ahern787bef12011-05-27 14:28:43 -0600114 {.str = "ip", .field = PERF_OUTPUT_IP},
David Ahernc0230b22011-03-09 22:23:27 -0700115 {.str = "sym", .field = PERF_OUTPUT_SYM},
David Ahern610723f2011-05-27 14:28:44 -0600116 {.str = "dso", .field = PERF_OUTPUT_DSO},
David Ahern7cec0922011-05-30 13:08:23 -0600117 {.str = "addr", .field = PERF_OUTPUT_ADDR},
Akihiro Nagaia978f2a2012-01-30 13:43:15 +0900118 {.str = "symoff", .field = PERF_OUTPUT_SYMOFFSET},
Adrian Huntercc8fae12013-12-06 09:42:57 +0200119 {.str = "srcline", .field = PERF_OUTPUT_SRCLINE},
Jiri Olsa535aeaae2014-08-25 16:45:42 +0200120 {.str = "period", .field = PERF_OUTPUT_PERIOD},
Stephane Eranianfc36f942015-08-31 18:41:10 +0200121 {.str = "iregs", .field = PERF_OUTPUT_IREGS},
Andi Kleenb1491ac2017-09-05 11:40:57 -0700122 {.str = "uregs", .field = PERF_OUTPUT_UREGS},
Stephane Eraniandc323ce2015-08-31 18:41:13 +0200123 {.str = "brstack", .field = PERF_OUTPUT_BRSTACK},
124 {.str = "brstacksym", .field = PERF_OUTPUT_BRSTACKSYM},
Jiri Olsa94ddddf2016-02-15 09:34:51 +0100125 {.str = "data_src", .field = PERF_OUTPUT_DATA_SRC},
126 {.str = "weight", .field = PERF_OUTPUT_WEIGHT},
Wang Nan30372f02016-02-24 11:20:45 +0000127 {.str = "bpf-output", .field = PERF_OUTPUT_BPF_OUTPUT},
Adrian Huntere2167082016-06-23 16:40:58 +0300128 {.str = "callindent", .field = PERF_OUTPUT_CALLINDENT},
Andi Kleen224e2c92016-10-07 16:42:27 +0300129 {.str = "insn", .field = PERF_OUTPUT_INSN},
130 {.str = "insnlen", .field = PERF_OUTPUT_INSNLEN},
Andi Kleen48d02a12017-02-23 15:46:34 -0800131 {.str = "brstackinsn", .field = PERF_OUTPUT_BRSTACKINSN},
Mark Santaniello106dacd2017-06-19 09:38:25 -0700132 {.str = "brstackoff", .field = PERF_OUTPUT_BRSTACKOFF},
Adrian Hunter47e78082017-05-26 11:17:22 +0300133 {.str = "synth", .field = PERF_OUTPUT_SYNTH},
Kan Liang49d58f02017-08-29 13:11:11 -0400134 {.str = "phys_addr", .field = PERF_OUTPUT_PHYS_ADDR},
Andi Kleen4bd1bef2017-11-17 13:43:00 -0800135 {.str = "metric", .field = PERF_OUTPUT_METRIC},
Jiri Olsa28a0b392018-01-07 17:03:52 +0100136 {.str = "misc", .field = PERF_OUTPUT_MISC},
Andi Kleendd2e18e2018-12-03 16:18:48 -0800137 {.str = "srccode", .field = PERF_OUTPUT_SRCCODE},
David Ahern745f43e2011-03-09 22:23:26 -0700138};
139
Adrian Hunter14057202017-06-21 13:17:19 +0300140enum {
141 OUTPUT_TYPE_SYNTH = PERF_TYPE_MAX,
142 OUTPUT_TYPE_MAX
143};
144
David Ahern745f43e2011-03-09 22:23:26 -0700145/* default set to maintain compatibility with current format */
David Ahern2c9e45f72011-03-17 10:03:21 -0600146static struct {
147 bool user_set;
David Ahern9cbdb702011-04-06 21:54:20 -0600148 bool wildcard_set;
David Aherna6ffaf92013-08-07 22:50:51 -0400149 unsigned int print_ip_opts;
David Ahern2c9e45f72011-03-17 10:03:21 -0600150 u64 fields;
151 u64 invalid_fields;
Andi Kleen4b6ac812019-02-24 07:37:12 -0800152 u64 user_set_fields;
Adrian Hunter14057202017-06-21 13:17:19 +0300153} output[OUTPUT_TYPE_MAX] = {
David Ahern1424dc92011-03-09 22:23:28 -0700154
David Ahern2c9e45f72011-03-17 10:03:21 -0600155 [PERF_TYPE_HARDWARE] = {
156 .user_set = false,
David Ahern1424dc92011-03-09 22:23:28 -0700157
David Ahern2c9e45f72011-03-17 10:03:21 -0600158 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
159 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
David Ahern787bef12011-05-27 14:28:43 -0600160 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
Sandipan Das7903a702018-05-17 12:03:26 +0530161 PERF_OUTPUT_SYM | PERF_OUTPUT_SYMOFFSET |
162 PERF_OUTPUT_DSO | PERF_OUTPUT_PERIOD,
David Ahern2c9e45f72011-03-17 10:03:21 -0600163
Wang Nan30372f02016-02-24 11:20:45 +0000164 .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT,
David Ahern2c9e45f72011-03-17 10:03:21 -0600165 },
166
167 [PERF_TYPE_SOFTWARE] = {
168 .user_set = false,
169
170 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
171 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
David Ahern787bef12011-05-27 14:28:43 -0600172 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
Sandipan Das7903a702018-05-17 12:03:26 +0530173 PERF_OUTPUT_SYM | PERF_OUTPUT_SYMOFFSET |
174 PERF_OUTPUT_DSO | PERF_OUTPUT_PERIOD |
175 PERF_OUTPUT_BPF_OUTPUT,
David Ahern2c9e45f72011-03-17 10:03:21 -0600176
177 .invalid_fields = PERF_OUTPUT_TRACE,
178 },
179
180 [PERF_TYPE_TRACEPOINT] = {
181 .user_set = false,
182
183 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
184 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
Wang Nan30372f02016-02-24 11:20:45 +0000185 PERF_OUTPUT_EVNAME | PERF_OUTPUT_TRACE
David Ahern2c9e45f72011-03-17 10:03:21 -0600186 },
Arun Sharma0817a6a2011-04-14 10:38:18 -0700187
Seeteena Thoufeekfad76d42018-06-08 16:32:28 +0530188 [PERF_TYPE_HW_CACHE] = {
189 .user_set = false,
190
191 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
192 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
193 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
194 PERF_OUTPUT_SYM | PERF_OUTPUT_SYMOFFSET |
195 PERF_OUTPUT_DSO | PERF_OUTPUT_PERIOD,
196
197 .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT,
198 },
199
Arun Sharma0817a6a2011-04-14 10:38:18 -0700200 [PERF_TYPE_RAW] = {
201 .user_set = false,
202
203 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
204 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
David Ahern787bef12011-05-27 14:28:43 -0600205 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
Sandipan Das7903a702018-05-17 12:03:26 +0530206 PERF_OUTPUT_SYM | PERF_OUTPUT_SYMOFFSET |
207 PERF_OUTPUT_DSO | PERF_OUTPUT_PERIOD |
208 PERF_OUTPUT_ADDR | PERF_OUTPUT_DATA_SRC |
209 PERF_OUTPUT_WEIGHT | PERF_OUTPUT_PHYS_ADDR,
Arun Sharma0817a6a2011-04-14 10:38:18 -0700210
Wang Nan30372f02016-02-24 11:20:45 +0000211 .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT,
Arun Sharma0817a6a2011-04-14 10:38:18 -0700212 },
Wang Nan27cfef02015-12-08 02:25:43 +0000213
214 [PERF_TYPE_BREAKPOINT] = {
215 .user_set = false,
216
217 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
218 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
219 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
Sandipan Das7903a702018-05-17 12:03:26 +0530220 PERF_OUTPUT_SYM | PERF_OUTPUT_SYMOFFSET |
221 PERF_OUTPUT_DSO | PERF_OUTPUT_PERIOD,
Wang Nan27cfef02015-12-08 02:25:43 +0000222
Wang Nan30372f02016-02-24 11:20:45 +0000223 .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT,
Wang Nan27cfef02015-12-08 02:25:43 +0000224 },
Adrian Hunter14057202017-06-21 13:17:19 +0300225
226 [OUTPUT_TYPE_SYNTH] = {
227 .user_set = false,
228
229 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
230 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
231 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
Sandipan Das7903a702018-05-17 12:03:26 +0530232 PERF_OUTPUT_SYM | PERF_OUTPUT_SYMOFFSET |
233 PERF_OUTPUT_DSO | PERF_OUTPUT_SYNTH,
Adrian Hunter14057202017-06-21 13:17:19 +0300234
235 .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT,
236 },
David Ahern1424dc92011-03-09 22:23:28 -0700237};
David Ahern745f43e2011-03-09 22:23:26 -0700238
Arnaldo Carvalho de Melo642ee1c2017-10-30 13:11:15 -0300239struct perf_evsel_script {
240 char *filename;
241 FILE *fp;
242 u64 samples;
Andi Kleen4bd1bef2017-11-17 13:43:00 -0800243 /* For metric output */
244 u64 val;
245 int gnum;
Arnaldo Carvalho de Melo642ee1c2017-10-30 13:11:15 -0300246};
247
Andi Kleen4bd1bef2017-11-17 13:43:00 -0800248static inline struct perf_evsel_script *evsel_script(struct perf_evsel *evsel)
249{
250 return (struct perf_evsel_script *)evsel->priv;
251}
252
Arnaldo Carvalho de Melo642ee1c2017-10-30 13:11:15 -0300253static struct perf_evsel_script *perf_evsel_script__new(struct perf_evsel *evsel,
Jiri Olsa8ceb41d2017-01-23 22:07:59 +0100254 struct perf_data *data)
Arnaldo Carvalho de Melo642ee1c2017-10-30 13:11:15 -0300255{
Andi Kleen4bd1bef2017-11-17 13:43:00 -0800256 struct perf_evsel_script *es = zalloc(sizeof(*es));
Arnaldo Carvalho de Melo642ee1c2017-10-30 13:11:15 -0300257
258 if (es != NULL) {
Jiri Olsaeae8ad82017-01-23 22:25:41 +0100259 if (asprintf(&es->filename, "%s.%s.dump", data->file.path, perf_evsel__name(evsel)) < 0)
Arnaldo Carvalho de Melo642ee1c2017-10-30 13:11:15 -0300260 goto out_free;
261 es->fp = fopen(es->filename, "w");
262 if (es->fp == NULL)
263 goto out_free_filename;
Arnaldo Carvalho de Melo642ee1c2017-10-30 13:11:15 -0300264 }
265
266 return es;
267out_free_filename:
268 zfree(&es->filename);
269out_free:
270 free(es);
271 return NULL;
272}
273
274static void perf_evsel_script__delete(struct perf_evsel_script *es)
275{
276 zfree(&es->filename);
277 fclose(es->fp);
278 es->fp = NULL;
279 free(es);
280}
281
282static int perf_evsel_script__fprintf(struct perf_evsel_script *es, FILE *fp)
283{
284 struct stat st;
285
286 fstat(fileno(es->fp), &st);
287 return fprintf(fp, "[ perf script: Wrote %.3f MB %s (%" PRIu64 " samples) ]\n",
288 st.st_size / 1024.0 / 1024.0, es->filename, es->samples);
289}
290
Adrian Hunter14057202017-06-21 13:17:19 +0300291static inline int output_type(unsigned int type)
292{
293 switch (type) {
294 case PERF_TYPE_SYNTH:
295 return OUTPUT_TYPE_SYNTH;
296 default:
297 return type;
298 }
299}
300
301static inline unsigned int attr_type(unsigned int type)
302{
303 switch (type) {
304 case OUTPUT_TYPE_SYNTH:
305 return PERF_TYPE_SYNTH;
306 default:
307 return type;
308 }
309}
310
David Ahern2c9e45f72011-03-17 10:03:21 -0600311static bool output_set_by_user(void)
312{
313 int j;
Adrian Hunter14057202017-06-21 13:17:19 +0300314 for (j = 0; j < OUTPUT_TYPE_MAX; ++j) {
David Ahern2c9e45f72011-03-17 10:03:21 -0600315 if (output[j].user_set)
316 return true;
317 }
318 return false;
319}
David Ahern745f43e2011-03-09 22:23:26 -0700320
David Ahern9cbdb702011-04-06 21:54:20 -0600321static const char *output_field2str(enum perf_output_field field)
322{
323 int i, imax = ARRAY_SIZE(all_output_options);
324 const char *str = "";
325
326 for (i = 0; i < imax; ++i) {
327 if (all_output_options[i].field == field) {
328 str = all_output_options[i].str;
329 break;
330 }
331 }
332 return str;
333}
334
Adrian Hunter14057202017-06-21 13:17:19 +0300335#define PRINT_FIELD(x) (output[output_type(attr->type)].fields & PERF_OUTPUT_##x)
David Ahern1424dc92011-03-09 22:23:28 -0700336
Adrian Hunter6d5cdd62015-04-24 22:29:44 +0300337static int perf_evsel__do_check_stype(struct perf_evsel *evsel,
338 u64 sample_type, const char *sample_msg,
339 enum perf_output_field field,
340 bool allow_user_set)
David Ahern1424dc92011-03-09 22:23:28 -0700341{
Arnaldo Carvalho de Melo5bff01f2012-06-12 13:35:44 -0300342 struct perf_event_attr *attr = &evsel->attr;
Adrian Hunter14057202017-06-21 13:17:19 +0300343 int type = output_type(attr->type);
David Ahern9cbdb702011-04-06 21:54:20 -0600344 const char *evname;
345
346 if (attr->sample_type & sample_type)
347 return 0;
348
Andi Kleen4b6ac812019-02-24 07:37:12 -0800349 if (output[type].user_set_fields & field) {
Adrian Hunter6d5cdd62015-04-24 22:29:44 +0300350 if (allow_user_set)
351 return 0;
Arnaldo Carvalho de Melo5bff01f2012-06-12 13:35:44 -0300352 evname = perf_evsel__name(evsel);
David Ahern9cbdb702011-04-06 21:54:20 -0600353 pr_err("Samples for '%s' event do not have %s attribute set. "
354 "Cannot print '%s' field.\n",
355 evname, sample_msg, output_field2str(field));
356 return -1;
357 }
358
359 /* user did not ask for it explicitly so remove from the default list */
360 output[type].fields &= ~field;
Arnaldo Carvalho de Melo5bff01f2012-06-12 13:35:44 -0300361 evname = perf_evsel__name(evsel);
David Ahern9cbdb702011-04-06 21:54:20 -0600362 pr_debug("Samples for '%s' event do not have %s attribute set. "
363 "Skipping '%s' field.\n",
364 evname, sample_msg, output_field2str(field));
365
366 return 0;
367}
368
Adrian Hunter6d5cdd62015-04-24 22:29:44 +0300369static int perf_evsel__check_stype(struct perf_evsel *evsel,
370 u64 sample_type, const char *sample_msg,
371 enum perf_output_field field)
372{
373 return perf_evsel__do_check_stype(evsel, sample_type, sample_msg, field,
374 false);
375}
376
David Ahern9cbdb702011-04-06 21:54:20 -0600377static int perf_evsel__check_attr(struct perf_evsel *evsel,
378 struct perf_session *session)
379{
380 struct perf_event_attr *attr = &evsel->attr;
Adrian Hunter6d5cdd62015-04-24 22:29:44 +0300381 bool allow_user_set;
382
Jiri Olsae099eba2016-01-05 22:09:09 +0100383 if (perf_header__has_feat(&session->header, HEADER_STAT))
384 return 0;
385
Adrian Hunter6d5cdd62015-04-24 22:29:44 +0300386 allow_user_set = perf_header__has_feat(&session->header,
387 HEADER_AUXTRACE);
David Ahern9cbdb702011-04-06 21:54:20 -0600388
David Ahern1424dc92011-03-09 22:23:28 -0700389 if (PRINT_FIELD(TRACE) &&
390 !perf_session__has_traces(session, "record -R"))
391 return -EINVAL;
392
David Ahern787bef12011-05-27 14:28:43 -0600393 if (PRINT_FIELD(IP)) {
Arnaldo Carvalho de Melo5bff01f2012-06-12 13:35:44 -0300394 if (perf_evsel__check_stype(evsel, PERF_SAMPLE_IP, "IP",
395 PERF_OUTPUT_IP))
David Ahern1424dc92011-03-09 22:23:28 -0700396 return -EINVAL;
David Ahern1424dc92011-03-09 22:23:28 -0700397 }
David Ahern7cec0922011-05-30 13:08:23 -0600398
399 if (PRINT_FIELD(ADDR) &&
Adrian Hunter6d5cdd62015-04-24 22:29:44 +0300400 perf_evsel__do_check_stype(evsel, PERF_SAMPLE_ADDR, "ADDR",
401 PERF_OUTPUT_ADDR, allow_user_set))
David Ahern7cec0922011-05-30 13:08:23 -0600402 return -EINVAL;
403
Jiri Olsa94ddddf2016-02-15 09:34:51 +0100404 if (PRINT_FIELD(DATA_SRC) &&
405 perf_evsel__check_stype(evsel, PERF_SAMPLE_DATA_SRC, "DATA_SRC",
406 PERF_OUTPUT_DATA_SRC))
407 return -EINVAL;
408
409 if (PRINT_FIELD(WEIGHT) &&
410 perf_evsel__check_stype(evsel, PERF_SAMPLE_WEIGHT, "WEIGHT",
411 PERF_OUTPUT_WEIGHT))
412 return -EINVAL;
413
Andi Kleen37fed3d2018-09-18 05:32:09 -0700414 if (PRINT_FIELD(SYM) &&
415 !(evsel->attr.sample_type & (PERF_SAMPLE_IP|PERF_SAMPLE_ADDR))) {
David Ahern7cec0922011-05-30 13:08:23 -0600416 pr_err("Display of symbols requested but neither sample IP nor "
Andi Kleen37fed3d2018-09-18 05:32:09 -0700417 "sample address\navailable. Hence, no addresses to convert "
David Ahern7cec0922011-05-30 13:08:23 -0600418 "to symbols.\n");
David Ahern787bef12011-05-27 14:28:43 -0600419 return -EINVAL;
420 }
Akihiro Nagaia978f2a2012-01-30 13:43:15 +0900421 if (PRINT_FIELD(SYMOFFSET) && !PRINT_FIELD(SYM)) {
422 pr_err("Display of offsets requested but symbol is not"
423 "selected.\n");
424 return -EINVAL;
425 }
Andi Kleen37fed3d2018-09-18 05:32:09 -0700426 if (PRINT_FIELD(DSO) &&
427 !(evsel->attr.sample_type & (PERF_SAMPLE_IP|PERF_SAMPLE_ADDR))) {
428 pr_err("Display of DSO requested but no address to convert.\n");
David Ahern610723f2011-05-27 14:28:44 -0600429 return -EINVAL;
430 }
Andi Kleendd2e18e2018-12-03 16:18:48 -0800431 if ((PRINT_FIELD(SRCLINE) || PRINT_FIELD(SRCCODE)) && !PRINT_FIELD(IP)) {
Adrian Huntercc8fae12013-12-06 09:42:57 +0200432 pr_err("Display of source line number requested but sample IP is not\n"
433 "selected. Hence, no address to lookup the source line number.\n");
434 return -EINVAL;
435 }
Andi Kleen48d02a12017-02-23 15:46:34 -0800436 if (PRINT_FIELD(BRSTACKINSN) &&
437 !(perf_evlist__combined_branch_type(session->evlist) &
438 PERF_SAMPLE_BRANCH_ANY)) {
439 pr_err("Display of branch stack assembler requested, but non all-branch filter set\n"
440 "Hint: run 'perf record -b ...'\n");
441 return -EINVAL;
442 }
David Ahern1424dc92011-03-09 22:23:28 -0700443 if ((PRINT_FIELD(PID) || PRINT_FIELD(TID)) &&
Arnaldo Carvalho de Melo5bff01f2012-06-12 13:35:44 -0300444 perf_evsel__check_stype(evsel, PERF_SAMPLE_TID, "TID",
445 PERF_OUTPUT_TID|PERF_OUTPUT_PID))
David Ahern1424dc92011-03-09 22:23:28 -0700446 return -EINVAL;
David Ahern1424dc92011-03-09 22:23:28 -0700447
448 if (PRINT_FIELD(TIME) &&
Arnaldo Carvalho de Melo5bff01f2012-06-12 13:35:44 -0300449 perf_evsel__check_stype(evsel, PERF_SAMPLE_TIME, "TIME",
450 PERF_OUTPUT_TIME))
David Ahern1424dc92011-03-09 22:23:28 -0700451 return -EINVAL;
David Ahern1424dc92011-03-09 22:23:28 -0700452
453 if (PRINT_FIELD(CPU) &&
Adrian Hunter6d5cdd62015-04-24 22:29:44 +0300454 perf_evsel__do_check_stype(evsel, PERF_SAMPLE_CPU, "CPU",
455 PERF_OUTPUT_CPU, allow_user_set))
David Ahern1424dc92011-03-09 22:23:28 -0700456 return -EINVAL;
David Ahern9cbdb702011-04-06 21:54:20 -0600457
Stephane Eranianfc36f942015-08-31 18:41:10 +0200458 if (PRINT_FIELD(IREGS) &&
459 perf_evsel__check_stype(evsel, PERF_SAMPLE_REGS_INTR, "IREGS",
460 PERF_OUTPUT_IREGS))
461 return -EINVAL;
462
Andi Kleenb1491ac2017-09-05 11:40:57 -0700463 if (PRINT_FIELD(UREGS) &&
464 perf_evsel__check_stype(evsel, PERF_SAMPLE_REGS_USER, "UREGS",
465 PERF_OUTPUT_UREGS))
466 return -EINVAL;
467
Kan Liang49d58f02017-08-29 13:11:11 -0400468 if (PRINT_FIELD(PHYS_ADDR) &&
469 perf_evsel__check_stype(evsel, PERF_SAMPLE_PHYS_ADDR, "PHYS_ADDR",
470 PERF_OUTPUT_PHYS_ADDR))
471 return -EINVAL;
472
David Ahern9cbdb702011-04-06 21:54:20 -0600473 return 0;
474}
475
Adrian Hunter7ea95722013-11-01 15:51:30 +0200476static void set_print_ip_opts(struct perf_event_attr *attr)
477{
Adrian Hunter14057202017-06-21 13:17:19 +0300478 unsigned int type = output_type(attr->type);
Adrian Hunter7ea95722013-11-01 15:51:30 +0200479
480 output[type].print_ip_opts = 0;
481 if (PRINT_FIELD(IP))
Arnaldo Carvalho de Meloe20ab862016-04-12 15:16:15 -0300482 output[type].print_ip_opts |= EVSEL__PRINT_IP;
Adrian Hunter7ea95722013-11-01 15:51:30 +0200483
484 if (PRINT_FIELD(SYM))
Arnaldo Carvalho de Meloe20ab862016-04-12 15:16:15 -0300485 output[type].print_ip_opts |= EVSEL__PRINT_SYM;
Adrian Hunter7ea95722013-11-01 15:51:30 +0200486
487 if (PRINT_FIELD(DSO))
Arnaldo Carvalho de Meloe20ab862016-04-12 15:16:15 -0300488 output[type].print_ip_opts |= EVSEL__PRINT_DSO;
Adrian Hunter7ea95722013-11-01 15:51:30 +0200489
490 if (PRINT_FIELD(SYMOFFSET))
Arnaldo Carvalho de Meloe20ab862016-04-12 15:16:15 -0300491 output[type].print_ip_opts |= EVSEL__PRINT_SYMOFFSET;
Adrian Huntercc8fae12013-12-06 09:42:57 +0200492
493 if (PRINT_FIELD(SRCLINE))
Arnaldo Carvalho de Meloe20ab862016-04-12 15:16:15 -0300494 output[type].print_ip_opts |= EVSEL__PRINT_SRCLINE;
Adrian Hunter7ea95722013-11-01 15:51:30 +0200495}
496
David Ahern9cbdb702011-04-06 21:54:20 -0600497/*
498 * verify all user requested events exist and the samples
499 * have the expected data
500 */
501static int perf_session__check_output_opt(struct perf_session *session)
502{
He Kuang40f20e52016-05-16 04:51:19 +0000503 unsigned int j;
David Ahern9cbdb702011-04-06 21:54:20 -0600504 struct perf_evsel *evsel;
505
Adrian Hunter14057202017-06-21 13:17:19 +0300506 for (j = 0; j < OUTPUT_TYPE_MAX; ++j) {
507 evsel = perf_session__find_first_evtype(session, attr_type(j));
David Ahern9cbdb702011-04-06 21:54:20 -0600508
509 /*
510 * even if fields is set to 0 (ie., show nothing) event must
511 * exist if user explicitly includes it on the command line
512 */
Adrian Hunter14057202017-06-21 13:17:19 +0300513 if (!evsel && output[j].user_set && !output[j].wildcard_set &&
514 j != OUTPUT_TYPE_SYNTH) {
David Ahern9cbdb702011-04-06 21:54:20 -0600515 pr_err("%s events do not exist. "
Adrian Hunter701516a2017-05-26 11:17:20 +0300516 "Remove corresponding -F option to proceed.\n",
David Ahern9cbdb702011-04-06 21:54:20 -0600517 event_type(j));
518 return -1;
519 }
520
521 if (evsel && output[j].fields &&
522 perf_evsel__check_attr(evsel, session))
523 return -1;
David Aherna6ffaf92013-08-07 22:50:51 -0400524
525 if (evsel == NULL)
526 continue;
527
Adrian Hunter7ea95722013-11-01 15:51:30 +0200528 set_print_ip_opts(&evsel->attr);
David Ahern1424dc92011-03-09 22:23:28 -0700529 }
530
Adrian Hunter98526ee2014-07-31 09:00:59 +0300531 if (!no_callchain) {
532 bool use_callchain = false;
He Kuang71ac8992016-08-04 11:25:43 +0000533 bool not_pipe = false;
Adrian Hunter98526ee2014-07-31 09:00:59 +0300534
Arnaldo Carvalho de Meloe5cadb92016-06-23 11:26:15 -0300535 evlist__for_each_entry(session->evlist, evsel) {
He Kuang71ac8992016-08-04 11:25:43 +0000536 not_pipe = true;
Arnaldo Carvalho de Melo27de9b22018-05-28 16:00:29 -0300537 if (evsel__has_callchain(evsel)) {
Adrian Hunter98526ee2014-07-31 09:00:59 +0300538 use_callchain = true;
539 break;
540 }
541 }
He Kuang71ac8992016-08-04 11:25:43 +0000542 if (not_pipe && !use_callchain)
Adrian Hunter98526ee2014-07-31 09:00:59 +0300543 symbol_conf.use_callchain = false;
544 }
545
David Ahern80b8b492013-11-19 21:07:37 -0700546 /*
547 * set default for tracepoints to print symbols only
548 * if callchains are present
549 */
550 if (symbol_conf.use_callchain &&
551 !output[PERF_TYPE_TRACEPOINT].user_set) {
David Ahern80b8b492013-11-19 21:07:37 -0700552 j = PERF_TYPE_TRACEPOINT;
David Ahern80b8b492013-11-19 21:07:37 -0700553
Arnaldo Carvalho de Meloe5cadb92016-06-23 11:26:15 -0300554 evlist__for_each_entry(session->evlist, evsel) {
He Kuang40f20e52016-05-16 04:51:19 +0000555 if (evsel->attr.type != j)
556 continue;
David Ahern80b8b492013-11-19 21:07:37 -0700557
Arnaldo Carvalho de Melo27de9b22018-05-28 16:00:29 -0300558 if (evsel__has_callchain(evsel)) {
He Kuang40f20e52016-05-16 04:51:19 +0000559 output[j].fields |= PERF_OUTPUT_IP;
560 output[j].fields |= PERF_OUTPUT_SYM;
Sandipan Das7903a702018-05-17 12:03:26 +0530561 output[j].fields |= PERF_OUTPUT_SYMOFFSET;
He Kuang40f20e52016-05-16 04:51:19 +0000562 output[j].fields |= PERF_OUTPUT_DSO;
Arnaldo Carvalho de Melo27de9b22018-05-28 16:00:29 -0300563 set_print_ip_opts(&evsel->attr);
He Kuang40f20e52016-05-16 04:51:19 +0000564 goto out;
565 }
David Ahern80b8b492013-11-19 21:07:37 -0700566 }
567 }
568
569out:
David Ahern1424dc92011-03-09 22:23:28 -0700570 return 0;
571}
David Ahern745f43e2011-03-09 22:23:26 -0700572
Milian Wolff9add8fe2018-11-07 23:34:37 +0100573static int perf_sample__fprintf_regs(struct regs_dump *regs, uint64_t mask,
574 FILE *fp
575)
Stephane Eranianfc36f942015-08-31 18:41:10 +0200576{
Andi Kleenb1491ac2017-09-05 11:40:57 -0700577 unsigned i = 0, r;
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300578 int printed = 0;
Andi Kleenb1491ac2017-09-05 11:40:57 -0700579
580 if (!regs || !regs->regs)
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300581 return 0;
Andi Kleenb1491ac2017-09-05 11:40:57 -0700582
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300583 printed += fprintf(fp, " ABI:%" PRIu64 " ", regs->abi);
Andi Kleenb1491ac2017-09-05 11:40:57 -0700584
585 for_each_set_bit(r, (unsigned long *) &mask, sizeof(mask) * 8) {
586 u64 val = regs->regs[i++];
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300587 printed += fprintf(fp, "%5s:0x%"PRIx64" ", perf_reg_name(r), val);
Andi Kleenb1491ac2017-09-05 11:40:57 -0700588 }
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300589
Milian Wolffb07d16f2018-11-07 10:37:05 +0100590 fprintf(fp, "\n");
591
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300592 return printed;
Andi Kleenb1491ac2017-09-05 11:40:57 -0700593}
594
Milian Wolff9add8fe2018-11-07 23:34:37 +0100595static int perf_sample__fprintf_iregs(struct perf_sample *sample,
596 struct perf_event_attr *attr, FILE *fp)
597{
598 return perf_sample__fprintf_regs(&sample->intr_regs,
599 attr->sample_regs_intr, fp);
600}
601
602static int perf_sample__fprintf_uregs(struct perf_sample *sample,
603 struct perf_event_attr *attr, FILE *fp)
604{
605 return perf_sample__fprintf_regs(&sample->user_regs,
606 attr->sample_regs_user, fp);
607}
608
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300609static int perf_sample__fprintf_start(struct perf_sample *sample,
610 struct thread *thread,
Jiri Olsa28a0b392018-01-07 17:03:52 +0100611 struct perf_evsel *evsel,
612 u32 type, FILE *fp)
David Ahernc70c94b2011-03-09 22:23:25 -0700613{
Arnaldo Carvalho de Melo5bff01f2012-06-12 13:35:44 -0300614 struct perf_event_attr *attr = &evsel->attr;
David Ahernc70c94b2011-03-09 22:23:25 -0700615 unsigned long secs;
David Ahern745f43e2011-03-09 22:23:26 -0700616 unsigned long long nsecs;
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300617 int printed = 0;
David Ahernc70c94b2011-03-09 22:23:25 -0700618
David Ahern745f43e2011-03-09 22:23:26 -0700619 if (PRINT_FIELD(COMM)) {
620 if (latency_format)
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300621 printed += fprintf(fp, "%8.8s ", thread__comm_str(thread));
Arnaldo Carvalho de Melob8798332018-06-04 10:34:20 -0300622 else if (PRINT_FIELD(IP) && evsel__has_callchain(evsel) && symbol_conf.use_callchain)
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300623 printed += fprintf(fp, "%s ", thread__comm_str(thread));
David Ahern745f43e2011-03-09 22:23:26 -0700624 else
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300625 printed += fprintf(fp, "%16s ", thread__comm_str(thread));
David Ahern745f43e2011-03-09 22:23:26 -0700626 }
David Ahernc70c94b2011-03-09 22:23:25 -0700627
David Ahern745f43e2011-03-09 22:23:26 -0700628 if (PRINT_FIELD(PID) && PRINT_FIELD(TID))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300629 printed += fprintf(fp, "%5d/%-5d ", sample->pid, sample->tid);
David Ahern745f43e2011-03-09 22:23:26 -0700630 else if (PRINT_FIELD(PID))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300631 printed += fprintf(fp, "%5d ", sample->pid);
David Ahern745f43e2011-03-09 22:23:26 -0700632 else if (PRINT_FIELD(TID))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300633 printed += fprintf(fp, "%5d ", sample->tid);
David Ahernc70c94b2011-03-09 22:23:25 -0700634
David Ahern745f43e2011-03-09 22:23:26 -0700635 if (PRINT_FIELD(CPU)) {
636 if (latency_format)
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300637 printed += fprintf(fp, "%3d ", sample->cpu);
David Ahern745f43e2011-03-09 22:23:26 -0700638 else
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300639 printed += fprintf(fp, "[%03d] ", sample->cpu);
David Ahern745f43e2011-03-09 22:23:26 -0700640 }
David Ahernc70c94b2011-03-09 22:23:25 -0700641
Jiri Olsa28a0b392018-01-07 17:03:52 +0100642 if (PRINT_FIELD(MISC)) {
643 int ret = 0;
644
645 #define has(m) \
646 (sample->misc & PERF_RECORD_MISC_##m) == PERF_RECORD_MISC_##m
647
648 if (has(KERNEL))
649 ret += fprintf(fp, "K");
650 if (has(USER))
651 ret += fprintf(fp, "U");
652 if (has(HYPERVISOR))
653 ret += fprintf(fp, "H");
654 if (has(GUEST_KERNEL))
655 ret += fprintf(fp, "G");
656 if (has(GUEST_USER))
657 ret += fprintf(fp, "g");
658
659 switch (type) {
660 case PERF_RECORD_MMAP:
661 case PERF_RECORD_MMAP2:
662 if (has(MMAP_DATA))
663 ret += fprintf(fp, "M");
664 break;
665 case PERF_RECORD_COMM:
666 if (has(COMM_EXEC))
667 ret += fprintf(fp, "E");
668 break;
669 case PERF_RECORD_SWITCH:
670 case PERF_RECORD_SWITCH_CPU_WIDE:
Alexey Budankovbf30cc12018-04-09 10:26:46 +0300671 if (has(SWITCH_OUT)) {
Jiri Olsa28a0b392018-01-07 17:03:52 +0100672 ret += fprintf(fp, "S");
Alexey Budankovbf30cc12018-04-09 10:26:46 +0300673 if (sample->misc & PERF_RECORD_MISC_SWITCH_OUT_PREEMPT)
674 ret += fprintf(fp, "p");
675 }
Jiri Olsa28a0b392018-01-07 17:03:52 +0100676 default:
677 break;
678 }
679
680 #undef has
681
682 ret += fprintf(fp, "%*s", 6 - ret, " ");
683 printed += ret;
684 }
685
David Ahern745f43e2011-03-09 22:23:26 -0700686 if (PRINT_FIELD(TIME)) {
687 nsecs = sample->time;
Arnaldo Carvalho de Melobd48c632016-08-05 15:40:30 -0300688 secs = nsecs / NSEC_PER_SEC;
689 nsecs -= secs * NSEC_PER_SEC;
Namhyung Kim99620a52016-10-24 11:02:45 +0900690
Adrian Hunter83e19862015-09-25 16:15:36 +0300691 if (nanosecs)
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300692 printed += fprintf(fp, "%5lu.%09llu: ", secs, nsecs);
Namhyung Kim99620a52016-10-24 11:02:45 +0900693 else {
694 char sample_time[32];
695 timestamp__scnprintf_usec(sample->time, sample_time, sizeof(sample_time));
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300696 printed += fprintf(fp, "%12s: ", sample_time);
Namhyung Kim99620a52016-10-24 11:02:45 +0900697 }
David Ahern745f43e2011-03-09 22:23:26 -0700698 }
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300699
700 return printed;
David Ahernc70c94b2011-03-09 22:23:25 -0700701}
702
Stephane Eraniandc323ce2015-08-31 18:41:13 +0200703static inline char
704mispred_str(struct branch_entry *br)
705{
706 if (!(br->flags.mispred || br->flags.predicted))
707 return '-';
708
709 return br->flags.predicted ? 'P' : 'M';
710}
711
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300712static int perf_sample__fprintf_brstack(struct perf_sample *sample,
713 struct thread *thread,
714 struct perf_event_attr *attr, FILE *fp)
Stephane Eraniandc323ce2015-08-31 18:41:13 +0200715{
716 struct branch_stack *br = sample->branch_stack;
Mark Santaniello55b9b502017-06-19 09:38:24 -0700717 struct addr_location alf, alt;
718 u64 i, from, to;
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300719 int printed = 0;
Stephane Eraniandc323ce2015-08-31 18:41:13 +0200720
721 if (!(br && br->nr))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300722 return 0;
Stephane Eraniandc323ce2015-08-31 18:41:13 +0200723
724 for (i = 0; i < br->nr; i++) {
Mark Santaniello55b9b502017-06-19 09:38:24 -0700725 from = br->entries[i].from;
726 to = br->entries[i].to;
727
728 if (PRINT_FIELD(DSO)) {
729 memset(&alf, 0, sizeof(alf));
730 memset(&alt, 0, sizeof(alt));
Adrian Hunter692d0e62018-11-06 23:07:12 +0200731 thread__find_map_fb(thread, sample->cpumode, from, &alf);
732 thread__find_map_fb(thread, sample->cpumode, to, &alt);
Mark Santaniello55b9b502017-06-19 09:38:24 -0700733 }
734
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300735 printed += fprintf(fp, " 0x%"PRIx64, from);
Mark Santaniello55b9b502017-06-19 09:38:24 -0700736 if (PRINT_FIELD(DSO)) {
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300737 printed += fprintf(fp, "(");
738 printed += map__fprintf_dsoname(alf.map, fp);
739 printed += fprintf(fp, ")");
Mark Santaniello55b9b502017-06-19 09:38:24 -0700740 }
741
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300742 printed += fprintf(fp, "/0x%"PRIx64, to);
Mark Santaniello55b9b502017-06-19 09:38:24 -0700743 if (PRINT_FIELD(DSO)) {
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300744 printed += fprintf(fp, "(");
745 printed += map__fprintf_dsoname(alt.map, fp);
746 printed += fprintf(fp, ")");
Mark Santaniello55b9b502017-06-19 09:38:24 -0700747 }
748
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300749 printed += fprintf(fp, "/%c/%c/%c/%d ",
Stephane Eraniandc323ce2015-08-31 18:41:13 +0200750 mispred_str( br->entries + i),
751 br->entries[i].flags.in_tx? 'X' : '-',
752 br->entries[i].flags.abort? 'A' : '-',
753 br->entries[i].flags.cycles);
754 }
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300755
756 return printed;
Stephane Eraniandc323ce2015-08-31 18:41:13 +0200757}
758
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300759static int perf_sample__fprintf_brstacksym(struct perf_sample *sample,
760 struct thread *thread,
761 struct perf_event_attr *attr, FILE *fp)
Stephane Eraniandc323ce2015-08-31 18:41:13 +0200762{
763 struct branch_stack *br = sample->branch_stack;
764 struct addr_location alf, alt;
Stephane Eraniandc323ce2015-08-31 18:41:13 +0200765 u64 i, from, to;
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300766 int printed = 0;
Stephane Eraniandc323ce2015-08-31 18:41:13 +0200767
768 if (!(br && br->nr))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300769 return 0;
Stephane Eraniandc323ce2015-08-31 18:41:13 +0200770
771 for (i = 0; i < br->nr; i++) {
772
773 memset(&alf, 0, sizeof(alf));
774 memset(&alt, 0, sizeof(alt));
775 from = br->entries[i].from;
776 to = br->entries[i].to;
777
Adrian Hunter692d0e62018-11-06 23:07:12 +0200778 thread__find_symbol_fb(thread, sample->cpumode, from, &alf);
779 thread__find_symbol_fb(thread, sample->cpumode, to, &alt);
Stephane Eraniandc323ce2015-08-31 18:41:13 +0200780
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300781 printed += symbol__fprintf_symname_offs(alf.sym, &alf, fp);
Mark Santaniello55b9b502017-06-19 09:38:24 -0700782 if (PRINT_FIELD(DSO)) {
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300783 printed += fprintf(fp, "(");
784 printed += map__fprintf_dsoname(alf.map, fp);
785 printed += fprintf(fp, ")");
Mark Santaniello55b9b502017-06-19 09:38:24 -0700786 }
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300787 printed += fprintf(fp, "%c", '/');
788 printed += symbol__fprintf_symname_offs(alt.sym, &alt, fp);
Mark Santaniello55b9b502017-06-19 09:38:24 -0700789 if (PRINT_FIELD(DSO)) {
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300790 printed += fprintf(fp, "(");
791 printed += map__fprintf_dsoname(alt.map, fp);
792 printed += fprintf(fp, ")");
Mark Santaniello55b9b502017-06-19 09:38:24 -0700793 }
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300794 printed += fprintf(fp, "/%c/%c/%c/%d ",
Stephane Eraniandc323ce2015-08-31 18:41:13 +0200795 mispred_str( br->entries + i),
796 br->entries[i].flags.in_tx? 'X' : '-',
797 br->entries[i].flags.abort? 'A' : '-',
798 br->entries[i].flags.cycles);
799 }
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300800
801 return printed;
Stephane Eraniandc323ce2015-08-31 18:41:13 +0200802}
803
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300804static int perf_sample__fprintf_brstackoff(struct perf_sample *sample,
805 struct thread *thread,
806 struct perf_event_attr *attr, FILE *fp)
Mark Santaniello106dacd2017-06-19 09:38:25 -0700807{
808 struct branch_stack *br = sample->branch_stack;
809 struct addr_location alf, alt;
810 u64 i, from, to;
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300811 int printed = 0;
Mark Santaniello106dacd2017-06-19 09:38:25 -0700812
813 if (!(br && br->nr))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300814 return 0;
Mark Santaniello106dacd2017-06-19 09:38:25 -0700815
816 for (i = 0; i < br->nr; i++) {
817
818 memset(&alf, 0, sizeof(alf));
819 memset(&alt, 0, sizeof(alt));
820 from = br->entries[i].from;
821 to = br->entries[i].to;
822
Adrian Hunter692d0e62018-11-06 23:07:12 +0200823 if (thread__find_map_fb(thread, sample->cpumode, from, &alf) &&
Arnaldo Carvalho de Melo71a84b52018-04-24 11:58:56 -0300824 !alf.map->dso->adjust_symbols)
Mark Santaniello106dacd2017-06-19 09:38:25 -0700825 from = map__map_ip(alf.map, from);
826
Adrian Hunter692d0e62018-11-06 23:07:12 +0200827 if (thread__find_map_fb(thread, sample->cpumode, to, &alt) &&
Arnaldo Carvalho de Melo71a84b52018-04-24 11:58:56 -0300828 !alt.map->dso->adjust_symbols)
Mark Santaniello106dacd2017-06-19 09:38:25 -0700829 to = map__map_ip(alt.map, to);
830
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300831 printed += fprintf(fp, " 0x%"PRIx64, from);
Mark Santaniello106dacd2017-06-19 09:38:25 -0700832 if (PRINT_FIELD(DSO)) {
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300833 printed += fprintf(fp, "(");
834 printed += map__fprintf_dsoname(alf.map, fp);
835 printed += fprintf(fp, ")");
Mark Santaniello106dacd2017-06-19 09:38:25 -0700836 }
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300837 printed += fprintf(fp, "/0x%"PRIx64, to);
Mark Santaniello106dacd2017-06-19 09:38:25 -0700838 if (PRINT_FIELD(DSO)) {
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300839 printed += fprintf(fp, "(");
840 printed += map__fprintf_dsoname(alt.map, fp);
841 printed += fprintf(fp, ")");
Mark Santaniello106dacd2017-06-19 09:38:25 -0700842 }
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300843 printed += fprintf(fp, "/%c/%c/%c/%d ",
Mark Santaniello106dacd2017-06-19 09:38:25 -0700844 mispred_str(br->entries + i),
845 br->entries[i].flags.in_tx ? 'X' : '-',
846 br->entries[i].flags.abort ? 'A' : '-',
847 br->entries[i].flags.cycles);
848 }
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300849
850 return printed;
Mark Santaniello106dacd2017-06-19 09:38:25 -0700851}
Andi Kleen48d02a12017-02-23 15:46:34 -0800852#define MAXBB 16384UL
853
854static int grab_bb(u8 *buffer, u64 start, u64 end,
855 struct machine *machine, struct thread *thread,
856 bool *is64bit, u8 *cpumode, bool last)
857{
858 long offset, len;
859 struct addr_location al;
860 bool kernel;
861
862 if (!start || !end)
863 return 0;
864
865 kernel = machine__kernel_ip(machine, start);
866 if (kernel)
867 *cpumode = PERF_RECORD_MISC_KERNEL;
868 else
869 *cpumode = PERF_RECORD_MISC_USER;
870
871 /*
872 * Block overlaps between kernel and user.
873 * This can happen due to ring filtering
874 * On Intel CPUs the entry into the kernel is filtered,
875 * but the exit is not. Let the caller patch it up.
876 */
877 if (kernel != machine__kernel_ip(machine, end)) {
Arnaldo Carvalho de Melo5ce2c5b2017-10-26 09:55:22 -0300878 pr_debug("\tblock %" PRIx64 "-%" PRIx64 " transfers between kernel and user\n", start, end);
Andi Kleen48d02a12017-02-23 15:46:34 -0800879 return -ENXIO;
880 }
881
882 memset(&al, 0, sizeof(al));
883 if (end - start > MAXBB - MAXINSN) {
884 if (last)
Arnaldo Carvalho de Melo5ce2c5b2017-10-26 09:55:22 -0300885 pr_debug("\tbrstack does not reach to final jump (%" PRIx64 "-%" PRIx64 ")\n", start, end);
Andi Kleen48d02a12017-02-23 15:46:34 -0800886 else
Arnaldo Carvalho de Melo5ce2c5b2017-10-26 09:55:22 -0300887 pr_debug("\tblock %" PRIx64 "-%" PRIx64 " (%" PRIu64 ") too long to dump\n", start, end, end - start);
Andi Kleen48d02a12017-02-23 15:46:34 -0800888 return 0;
889 }
890
Arnaldo Carvalho de Melo71a84b52018-04-24 11:58:56 -0300891 if (!thread__find_map(thread, *cpumode, start, &al) || !al.map->dso) {
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 if (al.map->dso->data.status == DSO_DATA_STATUS_ERROR) {
Arnaldo Carvalho de Melo5ce2c5b2017-10-26 09:55:22 -0300896 pr_debug("\tcannot resolve %" PRIx64 "-%" PRIx64 "\n", start, end);
Andi Kleen48d02a12017-02-23 15:46:34 -0800897 return 0;
898 }
899
900 /* Load maps to ensure dso->is_64_bit has been updated */
901 map__load(al.map);
902
903 offset = al.map->map_ip(al.map, start);
904 len = dso__data_read_offset(al.map->dso, machine, offset, (u8 *)buffer,
905 end - start + MAXINSN);
906
907 *is64bit = al.map->dso->is_64_bit;
908 if (len <= 0)
Arnaldo Carvalho de Melo5ce2c5b2017-10-26 09:55:22 -0300909 pr_debug("\tcannot fetch code for block at %" PRIx64 "-%" PRIx64 "\n",
Andi Kleen48d02a12017-02-23 15:46:34 -0800910 start, end);
911 return len;
912}
913
Andi Kleendd2e18e2018-12-03 16:18:48 -0800914static int print_srccode(struct thread *thread, u8 cpumode, uint64_t addr)
915{
916 struct addr_location al;
917 int ret = 0;
918
919 memset(&al, 0, sizeof(al));
920 thread__find_map(thread, cpumode, addr, &al);
921 if (!al.map)
922 return 0;
923 ret = map__fprintf_srccode(al.map, al.addr, stdout,
924 &thread->srccode_state);
925 if (ret)
926 ret += printf("\n");
927 return ret;
928}
929
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300930static int ip__fprintf_jump(uint64_t ip, struct branch_entry *en,
931 struct perf_insn *x, u8 *inbuf, int len,
Andi Kleenfe571202018-09-24 10:07:32 -0700932 int insn, FILE *fp, int *total_cycles)
Andi Kleen48d02a12017-02-23 15:46:34 -0800933{
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300934 int printed = fprintf(fp, "\t%016" PRIx64 "\t%-30s\t#%s%s%s%s", ip,
935 dump_insn(x, ip, inbuf, len, NULL),
936 en->flags.predicted ? " PRED" : "",
937 en->flags.mispred ? " MISPRED" : "",
938 en->flags.in_tx ? " INTX" : "",
939 en->flags.abort ? " ABORT" : "");
Andi Kleen48d02a12017-02-23 15:46:34 -0800940 if (en->flags.cycles) {
Andi Kleenfe571202018-09-24 10:07:32 -0700941 *total_cycles += en->flags.cycles;
942 printed += fprintf(fp, " %d cycles [%d]", en->flags.cycles, *total_cycles);
Andi Kleen48d02a12017-02-23 15:46:34 -0800943 if (insn)
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300944 printed += fprintf(fp, " %.2f IPC", (float)insn / en->flags.cycles);
Andi Kleen48d02a12017-02-23 15:46:34 -0800945 }
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300946 return printed + fprintf(fp, "\n");
Andi Kleen48d02a12017-02-23 15:46:34 -0800947}
948
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300949static int ip__fprintf_sym(uint64_t addr, struct thread *thread,
950 u8 cpumode, int cpu, struct symbol **lastsym,
951 struct perf_event_attr *attr, FILE *fp)
Andi Kleen48d02a12017-02-23 15:46:34 -0800952{
953 struct addr_location al;
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300954 int off, printed = 0;
Andi Kleen48d02a12017-02-23 15:46:34 -0800955
956 memset(&al, 0, sizeof(al));
957
Arnaldo Carvalho de Melo404eb5a2018-04-26 09:34:37 -0300958 thread__find_map(thread, cpumode, addr, &al);
959
Andi Kleen48d02a12017-02-23 15:46:34 -0800960 if ((*lastsym) && al.addr >= (*lastsym)->start && al.addr < (*lastsym)->end)
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300961 return 0;
Andi Kleen48d02a12017-02-23 15:46:34 -0800962
963 al.cpu = cpu;
964 al.sym = NULL;
965 if (al.map)
966 al.sym = map__find_symbol(al.map, al.addr);
967
968 if (!al.sym)
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300969 return 0;
Andi Kleen48d02a12017-02-23 15:46:34 -0800970
971 if (al.addr < al.sym->end)
972 off = al.addr - al.sym->start;
973 else
974 off = al.addr - al.map->start - al.sym->start;
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300975 printed += fprintf(fp, "\t%s", al.sym->name);
Andi Kleen48d02a12017-02-23 15:46:34 -0800976 if (off)
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300977 printed += fprintf(fp, "%+d", off);
978 printed += fprintf(fp, ":");
Andi Kleen48d02a12017-02-23 15:46:34 -0800979 if (PRINT_FIELD(SRCLINE))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300980 printed += map__fprintf_srcline(al.map, al.addr, "\t", fp);
981 printed += fprintf(fp, "\n");
Andi Kleen48d02a12017-02-23 15:46:34 -0800982 *lastsym = al.sym;
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300983
984 return printed;
Andi Kleen48d02a12017-02-23 15:46:34 -0800985}
986
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300987static int perf_sample__fprintf_brstackinsn(struct perf_sample *sample,
988 struct thread *thread,
989 struct perf_event_attr *attr,
990 struct machine *machine, FILE *fp)
Andi Kleen48d02a12017-02-23 15:46:34 -0800991{
992 struct branch_stack *br = sample->branch_stack;
993 u64 start, end;
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -0300994 int i, insn, len, nr, ilen, printed = 0;
Andi Kleen48d02a12017-02-23 15:46:34 -0800995 struct perf_insn x;
996 u8 buffer[MAXBB];
997 unsigned off;
998 struct symbol *lastsym = NULL;
Andi Kleenfe571202018-09-24 10:07:32 -0700999 int total_cycles = 0;
Andi Kleen48d02a12017-02-23 15:46:34 -08001000
1001 if (!(br && br->nr))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001002 return 0;
Andi Kleen48d02a12017-02-23 15:46:34 -08001003 nr = br->nr;
1004 if (max_blocks && nr > max_blocks + 1)
1005 nr = max_blocks + 1;
1006
1007 x.thread = thread;
1008 x.cpu = sample->cpu;
1009
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001010 printed += fprintf(fp, "%c", '\n');
Andi Kleen48d02a12017-02-23 15:46:34 -08001011
1012 /* Handle first from jump, of which we don't know the entry. */
1013 len = grab_bb(buffer, br->entries[nr-1].from,
1014 br->entries[nr-1].from,
1015 machine, thread, &x.is64bit, &x.cpumode, false);
1016 if (len > 0) {
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001017 printed += ip__fprintf_sym(br->entries[nr - 1].from, thread,
1018 x.cpumode, x.cpu, &lastsym, attr, fp);
1019 printed += ip__fprintf_jump(br->entries[nr - 1].from, &br->entries[nr - 1],
Andi Kleenfe571202018-09-24 10:07:32 -07001020 &x, buffer, len, 0, fp, &total_cycles);
Andi Kleendd2e18e2018-12-03 16:18:48 -08001021 if (PRINT_FIELD(SRCCODE))
1022 printed += print_srccode(thread, x.cpumode, br->entries[nr - 1].from);
Andi Kleen48d02a12017-02-23 15:46:34 -08001023 }
1024
1025 /* Print all blocks */
1026 for (i = nr - 2; i >= 0; i--) {
1027 if (br->entries[i].from || br->entries[i].to)
1028 pr_debug("%d: %" PRIx64 "-%" PRIx64 "\n", i,
1029 br->entries[i].from,
1030 br->entries[i].to);
1031 start = br->entries[i + 1].to;
1032 end = br->entries[i].from;
1033
1034 len = grab_bb(buffer, start, end, machine, thread, &x.is64bit, &x.cpumode, false);
1035 /* Patch up missing kernel transfers due to ring filters */
1036 if (len == -ENXIO && i > 0) {
1037 end = br->entries[--i].from;
1038 pr_debug("\tpatching up to %" PRIx64 "-%" PRIx64 "\n", start, end);
1039 len = grab_bb(buffer, start, end, machine, thread, &x.is64bit, &x.cpumode, false);
1040 }
1041 if (len <= 0)
1042 continue;
1043
1044 insn = 0;
1045 for (off = 0;; off += ilen) {
1046 uint64_t ip = start + off;
1047
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001048 printed += ip__fprintf_sym(ip, thread, x.cpumode, x.cpu, &lastsym, attr, fp);
Andi Kleen48d02a12017-02-23 15:46:34 -08001049 if (ip == end) {
Andi Kleenfe571202018-09-24 10:07:32 -07001050 printed += ip__fprintf_jump(ip, &br->entries[i], &x, buffer + off, len - off, insn, fp,
1051 &total_cycles);
Andi Kleendd2e18e2018-12-03 16:18:48 -08001052 if (PRINT_FIELD(SRCCODE))
1053 printed += print_srccode(thread, x.cpumode, ip);
Andi Kleen48d02a12017-02-23 15:46:34 -08001054 break;
1055 } else {
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001056 printed += fprintf(fp, "\t%016" PRIx64 "\t%s\n", ip,
1057 dump_insn(&x, ip, buffer + off, len - off, &ilen));
Andi Kleen48d02a12017-02-23 15:46:34 -08001058 if (ilen == 0)
1059 break;
Andi Kleendd2e18e2018-12-03 16:18:48 -08001060 if (PRINT_FIELD(SRCCODE))
1061 print_srccode(thread, x.cpumode, ip);
Andi Kleen48d02a12017-02-23 15:46:34 -08001062 insn++;
1063 }
1064 }
1065 }
1066
1067 /*
1068 * Hit the branch? In this case we are already done, and the target
1069 * has not been executed yet.
1070 */
1071 if (br->entries[0].from == sample->ip)
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001072 goto out;
Andi Kleen48d02a12017-02-23 15:46:34 -08001073 if (br->entries[0].flags.abort)
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001074 goto out;
Andi Kleen48d02a12017-02-23 15:46:34 -08001075
1076 /*
1077 * Print final block upto sample
Andi Kleen61f61152018-11-19 21:06:17 -08001078 *
1079 * Due to pipeline delays the LBRs might be missing a branch
1080 * or two, which can result in very large or negative blocks
1081 * between final branch and sample. When this happens just
1082 * continue walking after the last TO until we hit a branch.
Andi Kleen48d02a12017-02-23 15:46:34 -08001083 */
1084 start = br->entries[0].to;
1085 end = sample->ip;
Andi Kleen61f61152018-11-19 21:06:17 -08001086 if (end < start) {
1087 /* Missing jump. Scan 128 bytes for the next branch */
1088 end = start + 128;
1089 }
Andi Kleen48d02a12017-02-23 15:46:34 -08001090 len = grab_bb(buffer, start, end, machine, thread, &x.is64bit, &x.cpumode, true);
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001091 printed += ip__fprintf_sym(start, thread, x.cpumode, x.cpu, &lastsym, attr, fp);
Andi Kleen48d02a12017-02-23 15:46:34 -08001092 if (len <= 0) {
1093 /* Print at least last IP if basic block did not work */
1094 len = grab_bb(buffer, sample->ip, sample->ip,
1095 machine, thread, &x.is64bit, &x.cpumode, false);
1096 if (len <= 0)
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001097 goto out;
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001098 printed += fprintf(fp, "\t%016" PRIx64 "\t%s\n", sample->ip,
Andi Kleen48d02a12017-02-23 15:46:34 -08001099 dump_insn(&x, sample->ip, buffer, len, NULL));
Andi Kleendd2e18e2018-12-03 16:18:48 -08001100 if (PRINT_FIELD(SRCCODE))
1101 print_srccode(thread, x.cpumode, sample->ip);
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001102 goto out;
Andi Kleen48d02a12017-02-23 15:46:34 -08001103 }
1104 for (off = 0; off <= end - start; off += ilen) {
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001105 printed += fprintf(fp, "\t%016" PRIx64 "\t%s\n", start + off,
1106 dump_insn(&x, start + off, buffer + off, len - off, &ilen));
Andi Kleen48d02a12017-02-23 15:46:34 -08001107 if (ilen == 0)
1108 break;
Andi Kleen61f61152018-11-19 21:06:17 -08001109 if (arch_is_branch(buffer + off, len - off, x.is64bit) && start + off != sample->ip) {
1110 /*
1111 * Hit a missing branch. Just stop.
1112 */
1113 printed += fprintf(fp, "\t... not reaching sample ...\n");
1114 break;
1115 }
Andi Kleendd2e18e2018-12-03 16:18:48 -08001116 if (PRINT_FIELD(SRCCODE))
1117 print_srccode(thread, x.cpumode, start + off);
Andi Kleen48d02a12017-02-23 15:46:34 -08001118 }
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001119out:
1120 return printed;
Andi Kleen48d02a12017-02-23 15:46:34 -08001121}
Stephane Eraniandc323ce2015-08-31 18:41:13 +02001122
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001123static int perf_sample__fprintf_addr(struct perf_sample *sample,
1124 struct thread *thread,
1125 struct perf_event_attr *attr, FILE *fp)
David Ahern7cec0922011-05-30 13:08:23 -06001126{
1127 struct addr_location al;
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001128 int printed = fprintf(fp, "%16" PRIx64, sample->addr);
David Ahern7cec0922011-05-30 13:08:23 -06001129
1130 if (!sample_addr_correlates_sym(attr))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001131 goto out;
David Ahern7cec0922011-05-30 13:08:23 -06001132
Arnaldo Carvalho de Meloc2740a82016-03-22 18:44:46 -03001133 thread__resolve(thread, &al, sample);
David Ahern7cec0922011-05-30 13:08:23 -06001134
1135 if (PRINT_FIELD(SYM)) {
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001136 printed += fprintf(fp, " ");
Akihiro Nagaia978f2a2012-01-30 13:43:15 +09001137 if (PRINT_FIELD(SYMOFFSET))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001138 printed += symbol__fprintf_symname_offs(al.sym, &al, fp);
Akihiro Nagaia978f2a2012-01-30 13:43:15 +09001139 else
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001140 printed += symbol__fprintf_symname(al.sym, fp);
David Ahern7cec0922011-05-30 13:08:23 -06001141 }
1142
1143 if (PRINT_FIELD(DSO)) {
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001144 printed += fprintf(fp, " (");
1145 printed += map__fprintf_dsoname(al.map, fp);
1146 printed += fprintf(fp, ")");
David Ahern7cec0922011-05-30 13:08:23 -06001147 }
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001148out:
1149 return printed;
David Ahern7cec0922011-05-30 13:08:23 -06001150}
1151
Andi Kleen99f753f2018-09-20 11:05:39 -07001152static const char *resolve_branch_sym(struct perf_sample *sample,
1153 struct perf_evsel *evsel,
1154 struct thread *thread,
1155 struct addr_location *al,
1156 u64 *ip)
1157{
1158 struct addr_location addr_al;
1159 struct perf_event_attr *attr = &evsel->attr;
1160 const char *name = NULL;
1161
1162 if (sample->flags & (PERF_IP_FLAG_CALL | PERF_IP_FLAG_TRACE_BEGIN)) {
1163 if (sample_addr_correlates_sym(attr)) {
1164 thread__resolve(thread, &addr_al, sample);
1165 if (addr_al.sym)
1166 name = addr_al.sym->name;
1167 else
1168 *ip = sample->addr;
1169 } else {
1170 *ip = sample->addr;
1171 }
1172 } else if (sample->flags & (PERF_IP_FLAG_RETURN | PERF_IP_FLAG_TRACE_END)) {
1173 if (al->sym)
1174 name = al->sym->name;
1175 else
1176 *ip = sample->ip;
1177 }
1178 return name;
1179}
1180
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001181static int perf_sample__fprintf_callindent(struct perf_sample *sample,
1182 struct perf_evsel *evsel,
1183 struct thread *thread,
1184 struct addr_location *al, FILE *fp)
Adrian Huntere2167082016-06-23 16:40:58 +03001185{
1186 struct perf_event_attr *attr = &evsel->attr;
Adrian Hunter256d92b2018-12-21 14:06:19 +02001187 size_t depth = thread_stack__depth(thread, sample->cpu);
Adrian Huntere2167082016-06-23 16:40:58 +03001188 const char *name = NULL;
1189 static int spacing;
1190 int len = 0;
Andi Kleena78cdee2018-09-18 05:32:10 -07001191 int dlen = 0;
Adrian Huntere2167082016-06-23 16:40:58 +03001192 u64 ip = 0;
1193
1194 /*
1195 * The 'return' has already been popped off the stack so the depth has
1196 * to be adjusted to match the 'call'.
1197 */
1198 if (thread->ts && sample->flags & PERF_IP_FLAG_RETURN)
1199 depth += 1;
1200
Andi Kleen99f753f2018-09-20 11:05:39 -07001201 name = resolve_branch_sym(sample, evsel, thread, al, &ip);
Adrian Huntere2167082016-06-23 16:40:58 +03001202
Andi Kleena78cdee2018-09-18 05:32:10 -07001203 if (PRINT_FIELD(DSO) && !(PRINT_FIELD(IP) || PRINT_FIELD(ADDR))) {
1204 dlen += fprintf(fp, "(");
1205 dlen += map__fprintf_dsoname(al->map, fp);
1206 dlen += fprintf(fp, ")\t");
1207 }
1208
Adrian Huntere2167082016-06-23 16:40:58 +03001209 if (name)
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001210 len = fprintf(fp, "%*s%s", (int)depth * 4, "", name);
Adrian Huntere2167082016-06-23 16:40:58 +03001211 else if (ip)
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001212 len = fprintf(fp, "%*s%16" PRIx64, (int)depth * 4, "", ip);
Adrian Huntere2167082016-06-23 16:40:58 +03001213
1214 if (len < 0)
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001215 return len;
Adrian Huntere2167082016-06-23 16:40:58 +03001216
1217 /*
1218 * Try to keep the output length from changing frequently so that the
1219 * output lines up more nicely.
1220 */
1221 if (len > spacing || (len && len < spacing - 52))
1222 spacing = round_up(len + 4, 32);
1223
1224 if (len < spacing)
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001225 len += fprintf(fp, "%*s", spacing - len, "");
1226
Andi Kleena78cdee2018-09-18 05:32:10 -07001227 return len + dlen;
Adrian Huntere2167082016-06-23 16:40:58 +03001228}
1229
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001230static int perf_sample__fprintf_insn(struct perf_sample *sample,
1231 struct perf_event_attr *attr,
1232 struct thread *thread,
1233 struct machine *machine, FILE *fp)
Andi Kleen224e2c92016-10-07 16:42:27 +03001234{
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001235 int printed = 0;
1236
Andi Kleen224e2c92016-10-07 16:42:27 +03001237 if (PRINT_FIELD(INSNLEN))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001238 printed += fprintf(fp, " ilen: %d", sample->insn_len);
Andi Kleen224e2c92016-10-07 16:42:27 +03001239 if (PRINT_FIELD(INSN)) {
1240 int i;
1241
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001242 printed += fprintf(fp, " insn:");
Andi Kleen224e2c92016-10-07 16:42:27 +03001243 for (i = 0; i < sample->insn_len; i++)
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001244 printed += fprintf(fp, " %02x", (unsigned char)sample->insn[i]);
Andi Kleen224e2c92016-10-07 16:42:27 +03001245 }
Andi Kleen48d02a12017-02-23 15:46:34 -08001246 if (PRINT_FIELD(BRSTACKINSN))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001247 printed += perf_sample__fprintf_brstackinsn(sample, thread, attr, machine, fp);
1248
1249 return printed;
Andi Kleen224e2c92016-10-07 16:42:27 +03001250}
1251
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001252static int perf_sample__fprintf_bts(struct perf_sample *sample,
1253 struct perf_evsel *evsel,
1254 struct thread *thread,
1255 struct addr_location *al,
1256 struct machine *machine, FILE *fp)
Akihiro Nagai95582592012-01-30 13:43:09 +09001257{
1258 struct perf_event_attr *attr = &evsel->attr;
Adrian Hunter14057202017-06-21 13:17:19 +03001259 unsigned int type = output_type(attr->type);
Adrian Hunter8066be5f2014-07-22 16:17:15 +03001260 bool print_srcline_last = false;
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001261 int printed = 0;
Akihiro Nagai95582592012-01-30 13:43:09 +09001262
Adrian Huntere2167082016-06-23 16:40:58 +03001263 if (PRINT_FIELD(CALLINDENT))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001264 printed += perf_sample__fprintf_callindent(sample, evsel, thread, al, fp);
Adrian Huntere2167082016-06-23 16:40:58 +03001265
Akihiro Nagai95582592012-01-30 13:43:09 +09001266 /* print branch_from information */
1267 if (PRINT_FIELD(IP)) {
Adrian Hunter14057202017-06-21 13:17:19 +03001268 unsigned int print_opts = output[type].print_ip_opts;
Chris Phlipote557b672016-04-19 19:32:11 -07001269 struct callchain_cursor *cursor = NULL;
Adrian Hunter8066be5f2014-07-22 16:17:15 +03001270
Arnaldo Carvalho de Melo6f736732016-04-14 17:45:51 -03001271 if (symbol_conf.use_callchain && sample->callchain &&
Chris Phlipote557b672016-04-19 19:32:11 -07001272 thread__resolve_callchain(al->thread, &callchain_cursor, evsel,
Arnaldo Carvalho de Melo6f736732016-04-14 17:45:51 -03001273 sample, NULL, NULL, scripting_max_stack) == 0)
Chris Phlipote557b672016-04-19 19:32:11 -07001274 cursor = &callchain_cursor;
Arnaldo Carvalho de Melo6f736732016-04-14 17:45:51 -03001275
1276 if (cursor == NULL) {
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001277 printed += fprintf(fp, " ");
Arnaldo Carvalho de Meloe20ab862016-04-12 15:16:15 -03001278 if (print_opts & EVSEL__PRINT_SRCLINE) {
Adrian Hunter8066be5f2014-07-22 16:17:15 +03001279 print_srcline_last = true;
Arnaldo Carvalho de Meloe20ab862016-04-12 15:16:15 -03001280 print_opts &= ~EVSEL__PRINT_SRCLINE;
Adrian Hunter8066be5f2014-07-22 16:17:15 +03001281 }
Arnaldo Carvalho de Melo6f736732016-04-14 17:45:51 -03001282 } else
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001283 printed += fprintf(fp, "\n");
Arnaldo Carvalho de Melo6f736732016-04-14 17:45:51 -03001284
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001285 printed += sample__fprintf_sym(sample, al, 0, print_opts, cursor, fp);
Akihiro Nagai95582592012-01-30 13:43:09 +09001286 }
1287
Akihiro Nagai95582592012-01-30 13:43:09 +09001288 /* print branch_to information */
Adrian Hunter243be3d2013-10-18 15:29:14 +03001289 if (PRINT_FIELD(ADDR) ||
1290 ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) &&
Adrian Hunter14057202017-06-21 13:17:19 +03001291 !output[type].user_set)) {
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001292 printed += fprintf(fp, " => ");
1293 printed += perf_sample__fprintf_addr(sample, thread, attr, fp);
Adrian Hunter578bea42014-07-22 16:17:16 +03001294 }
Akihiro Nagai95582592012-01-30 13:43:09 +09001295
Adrian Hunter8066be5f2014-07-22 16:17:15 +03001296 if (print_srcline_last)
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001297 printed += map__fprintf_srcline(al->map, al->addr, "\n ", fp);
Adrian Hunter8066be5f2014-07-22 16:17:15 +03001298
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001299 printed += perf_sample__fprintf_insn(sample, attr, thread, machine, fp);
Andi Kleendd2e18e2018-12-03 16:18:48 -08001300 printed += fprintf(fp, "\n");
1301 if (PRINT_FIELD(SRCCODE)) {
1302 int ret = map__fprintf_srccode(al->map, al->addr, stdout,
1303 &thread->srccode_state);
1304 if (ret) {
1305 printed += ret;
1306 printed += printf("\n");
1307 }
1308 }
1309 return printed;
Akihiro Nagai95582592012-01-30 13:43:09 +09001310}
1311
Adrian Hunter055cd332016-06-23 16:40:56 +03001312static struct {
1313 u32 flags;
1314 const char *name;
1315} sample_flags[] = {
1316 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL, "call"},
1317 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN, "return"},
1318 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CONDITIONAL, "jcc"},
1319 {PERF_IP_FLAG_BRANCH, "jmp"},
1320 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_INTERRUPT, "int"},
1321 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN | PERF_IP_FLAG_INTERRUPT, "iret"},
1322 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_SYSCALLRET, "syscall"},
1323 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN | PERF_IP_FLAG_SYSCALLRET, "sysret"},
1324 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_ASYNC, "async"},
1325 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_ASYNC | PERF_IP_FLAG_INTERRUPT, "hw int"},
1326 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TX_ABORT, "tx abrt"},
1327 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TRACE_BEGIN, "tr strt"},
1328 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TRACE_END, "tr end"},
1329 {0, NULL}
1330};
1331
Adrian Hunter62cb1b82018-09-20 16:00:43 +03001332static const char *sample_flags_to_name(u32 flags)
1333{
1334 int i;
1335
1336 for (i = 0; sample_flags[i].name ; i++) {
1337 if (sample_flags[i].flags == flags)
1338 return sample_flags[i].name;
1339 }
1340
1341 return NULL;
1342}
1343
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001344static int perf_sample__fprintf_flags(u32 flags, FILE *fp)
Adrian Hunter400ea6d2015-04-09 18:54:05 +03001345{
1346 const char *chars = PERF_IP_FLAG_CHARS;
1347 const int n = strlen(PERF_IP_FLAG_CHARS);
Adrian Hunter055cd332016-06-23 16:40:56 +03001348 bool in_tx = flags & PERF_IP_FLAG_IN_TX;
1349 const char *name = NULL;
Adrian Hunter400ea6d2015-04-09 18:54:05 +03001350 char str[33];
1351 int i, pos = 0;
1352
Adrian Hunter62cb1b82018-09-20 16:00:43 +03001353 name = sample_flags_to_name(flags & ~PERF_IP_FLAG_IN_TX);
1354 if (name)
1355 return fprintf(fp, " %-15s%4s ", name, in_tx ? "(x)" : "");
1356
1357 if (flags & PERF_IP_FLAG_TRACE_BEGIN) {
1358 name = sample_flags_to_name(flags & ~(PERF_IP_FLAG_IN_TX | PERF_IP_FLAG_TRACE_BEGIN));
1359 if (name)
1360 return fprintf(fp, " tr strt %-7s%4s ", name, in_tx ? "(x)" : "");
1361 }
1362
1363 if (flags & PERF_IP_FLAG_TRACE_END) {
1364 name = sample_flags_to_name(flags & ~(PERF_IP_FLAG_IN_TX | PERF_IP_FLAG_TRACE_END));
1365 if (name)
1366 return fprintf(fp, " tr end %-7s%4s ", name, in_tx ? "(x)" : "");
Adrian Hunter055cd332016-06-23 16:40:56 +03001367 }
1368
Adrian Hunter400ea6d2015-04-09 18:54:05 +03001369 for (i = 0; i < n; i++, flags >>= 1) {
1370 if (flags & 1)
1371 str[pos++] = chars[i];
1372 }
1373 for (; i < 32; i++, flags >>= 1) {
1374 if (flags & 1)
1375 str[pos++] = '?';
1376 }
1377 str[pos] = 0;
Adrian Hunter055cd332016-06-23 16:40:56 +03001378
Adrian Hunter62cb1b82018-09-20 16:00:43 +03001379 return fprintf(fp, " %-19s ", str);
Adrian Hunter400ea6d2015-04-09 18:54:05 +03001380}
1381
Wang Nan30372f02016-02-24 11:20:45 +00001382struct printer_data {
1383 int line_no;
1384 bool hit_nul;
1385 bool is_printable;
1386};
1387
Arnaldo Carvalho de Melo923d0c92017-10-17 10:35:00 -03001388static int sample__fprintf_bpf_output(enum binary_printer_ops op,
1389 unsigned int val,
1390 void *extra, FILE *fp)
Wang Nan30372f02016-02-24 11:20:45 +00001391{
1392 unsigned char ch = (unsigned char)val;
1393 struct printer_data *printer_data = extra;
Arnaldo Carvalho de Melo923d0c92017-10-17 10:35:00 -03001394 int printed = 0;
Wang Nan30372f02016-02-24 11:20:45 +00001395
1396 switch (op) {
1397 case BINARY_PRINT_DATA_BEGIN:
Arnaldo Carvalho de Melo923d0c92017-10-17 10:35:00 -03001398 printed += fprintf(fp, "\n");
Wang Nan30372f02016-02-24 11:20:45 +00001399 break;
1400 case BINARY_PRINT_LINE_BEGIN:
Arnaldo Carvalho de Melo923d0c92017-10-17 10:35:00 -03001401 printed += fprintf(fp, "%17s", !printer_data->line_no ? "BPF output:" :
Wang Nan30372f02016-02-24 11:20:45 +00001402 " ");
1403 break;
1404 case BINARY_PRINT_ADDR:
Arnaldo Carvalho de Melo923d0c92017-10-17 10:35:00 -03001405 printed += fprintf(fp, " %04x:", val);
Wang Nan30372f02016-02-24 11:20:45 +00001406 break;
1407 case BINARY_PRINT_NUM_DATA:
Arnaldo Carvalho de Melo923d0c92017-10-17 10:35:00 -03001408 printed += fprintf(fp, " %02x", val);
Wang Nan30372f02016-02-24 11:20:45 +00001409 break;
1410 case BINARY_PRINT_NUM_PAD:
Arnaldo Carvalho de Melo923d0c92017-10-17 10:35:00 -03001411 printed += fprintf(fp, " ");
Wang Nan30372f02016-02-24 11:20:45 +00001412 break;
1413 case BINARY_PRINT_SEP:
Arnaldo Carvalho de Melo923d0c92017-10-17 10:35:00 -03001414 printed += fprintf(fp, " ");
Wang Nan30372f02016-02-24 11:20:45 +00001415 break;
1416 case BINARY_PRINT_CHAR_DATA:
1417 if (printer_data->hit_nul && ch)
1418 printer_data->is_printable = false;
1419
1420 if (!isprint(ch)) {
Arnaldo Carvalho de Melo923d0c92017-10-17 10:35:00 -03001421 printed += fprintf(fp, "%c", '.');
Wang Nan30372f02016-02-24 11:20:45 +00001422
1423 if (!printer_data->is_printable)
1424 break;
1425
1426 if (ch == '\0')
1427 printer_data->hit_nul = true;
1428 else
1429 printer_data->is_printable = false;
1430 } else {
Arnaldo Carvalho de Melo923d0c92017-10-17 10:35:00 -03001431 printed += fprintf(fp, "%c", ch);
Wang Nan30372f02016-02-24 11:20:45 +00001432 }
1433 break;
1434 case BINARY_PRINT_CHAR_PAD:
Arnaldo Carvalho de Melo923d0c92017-10-17 10:35:00 -03001435 printed += fprintf(fp, " ");
Wang Nan30372f02016-02-24 11:20:45 +00001436 break;
1437 case BINARY_PRINT_LINE_END:
Arnaldo Carvalho de Melo923d0c92017-10-17 10:35:00 -03001438 printed += fprintf(fp, "\n");
Wang Nan30372f02016-02-24 11:20:45 +00001439 printer_data->line_no++;
1440 break;
1441 case BINARY_PRINT_DATA_END:
1442 default:
1443 break;
1444 }
Arnaldo Carvalho de Melo923d0c92017-10-17 10:35:00 -03001445
1446 return printed;
Wang Nan30372f02016-02-24 11:20:45 +00001447}
1448
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001449static int perf_sample__fprintf_bpf_output(struct perf_sample *sample, FILE *fp)
Wang Nan30372f02016-02-24 11:20:45 +00001450{
1451 unsigned int nr_bytes = sample->raw_size;
1452 struct printer_data printer_data = {0, false, true};
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001453 int printed = binary__fprintf(sample->raw_data, nr_bytes, 8,
1454 sample__fprintf_bpf_output, &printer_data, fp);
Wang Nan30372f02016-02-24 11:20:45 +00001455
1456 if (printer_data.is_printable && printer_data.hit_nul)
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001457 printed += fprintf(fp, "%17s \"%s\"\n", "BPF string:", (char *)(sample->raw_data));
1458
1459 return printed;
Wang Nan30372f02016-02-24 11:20:45 +00001460}
1461
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001462static int perf_sample__fprintf_spacing(int len, int spacing, FILE *fp)
Adrian Hunter65c5e182017-06-30 11:36:42 +03001463{
1464 if (len > 0 && len < spacing)
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001465 return fprintf(fp, "%*s", spacing - len, "");
1466
1467 return 0;
Adrian Hunter65c5e182017-06-30 11:36:42 +03001468}
1469
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001470static int perf_sample__fprintf_pt_spacing(int len, FILE *fp)
Adrian Hunter65c5e182017-06-30 11:36:42 +03001471{
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001472 return perf_sample__fprintf_spacing(len, 34, fp);
Adrian Hunter65c5e182017-06-30 11:36:42 +03001473}
1474
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001475static int perf_sample__fprintf_synth_ptwrite(struct perf_sample *sample, FILE *fp)
Adrian Hunter65c5e182017-06-30 11:36:42 +03001476{
1477 struct perf_synth_intel_ptwrite *data = perf_sample__synth_ptr(sample);
1478 int len;
1479
1480 if (perf_sample__bad_synth_size(sample, *data))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001481 return 0;
Adrian Hunter65c5e182017-06-30 11:36:42 +03001482
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001483 len = fprintf(fp, " IP: %u payload: %#" PRIx64 " ",
Adrian Hunter65c5e182017-06-30 11:36:42 +03001484 data->ip, le64_to_cpu(data->payload));
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001485 return len + perf_sample__fprintf_pt_spacing(len, fp);
Adrian Hunter65c5e182017-06-30 11:36:42 +03001486}
1487
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001488static int perf_sample__fprintf_synth_mwait(struct perf_sample *sample, FILE *fp)
Adrian Hunter65c5e182017-06-30 11:36:42 +03001489{
1490 struct perf_synth_intel_mwait *data = perf_sample__synth_ptr(sample);
1491 int len;
1492
1493 if (perf_sample__bad_synth_size(sample, *data))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001494 return 0;
Adrian Hunter65c5e182017-06-30 11:36:42 +03001495
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001496 len = fprintf(fp, " hints: %#x extensions: %#x ",
1497 data->hints, data->extensions);
1498 return len + perf_sample__fprintf_pt_spacing(len, fp);
Adrian Hunter65c5e182017-06-30 11:36:42 +03001499}
1500
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001501static int perf_sample__fprintf_synth_pwre(struct perf_sample *sample, FILE *fp)
Adrian Hunter65c5e182017-06-30 11:36:42 +03001502{
1503 struct perf_synth_intel_pwre *data = perf_sample__synth_ptr(sample);
1504 int len;
1505
1506 if (perf_sample__bad_synth_size(sample, *data))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001507 return 0;
Adrian Hunter65c5e182017-06-30 11:36:42 +03001508
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001509 len = fprintf(fp, " hw: %u cstate: %u sub-cstate: %u ",
1510 data->hw, data->cstate, data->subcstate);
1511 return len + perf_sample__fprintf_pt_spacing(len, fp);
Adrian Hunter65c5e182017-06-30 11:36:42 +03001512}
1513
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001514static int perf_sample__fprintf_synth_exstop(struct perf_sample *sample, FILE *fp)
Adrian Hunter65c5e182017-06-30 11:36:42 +03001515{
1516 struct perf_synth_intel_exstop *data = perf_sample__synth_ptr(sample);
1517 int len;
1518
1519 if (perf_sample__bad_synth_size(sample, *data))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001520 return 0;
Adrian Hunter65c5e182017-06-30 11:36:42 +03001521
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001522 len = fprintf(fp, " IP: %u ", data->ip);
1523 return len + perf_sample__fprintf_pt_spacing(len, fp);
Adrian Hunter65c5e182017-06-30 11:36:42 +03001524}
1525
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001526static int perf_sample__fprintf_synth_pwrx(struct perf_sample *sample, FILE *fp)
Adrian Hunter65c5e182017-06-30 11:36:42 +03001527{
1528 struct perf_synth_intel_pwrx *data = perf_sample__synth_ptr(sample);
1529 int len;
1530
1531 if (perf_sample__bad_synth_size(sample, *data))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001532 return 0;
Adrian Hunter65c5e182017-06-30 11:36:42 +03001533
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001534 len = fprintf(fp, " deepest cstate: %u last cstate: %u wake reason: %#x ",
Adrian Hunter65c5e182017-06-30 11:36:42 +03001535 data->deepest_cstate, data->last_cstate,
1536 data->wake_reason);
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001537 return len + perf_sample__fprintf_pt_spacing(len, fp);
Adrian Hunter65c5e182017-06-30 11:36:42 +03001538}
1539
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001540static int perf_sample__fprintf_synth_cbr(struct perf_sample *sample, FILE *fp)
Adrian Hunter65c5e182017-06-30 11:36:42 +03001541{
1542 struct perf_synth_intel_cbr *data = perf_sample__synth_ptr(sample);
1543 unsigned int percent, freq;
1544 int len;
1545
1546 if (perf_sample__bad_synth_size(sample, *data))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001547 return 0;
Adrian Hunter65c5e182017-06-30 11:36:42 +03001548
1549 freq = (le32_to_cpu(data->freq) + 500) / 1000;
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001550 len = fprintf(fp, " cbr: %2u freq: %4u MHz ", data->cbr, freq);
Adrian Hunter65c5e182017-06-30 11:36:42 +03001551 if (data->max_nonturbo) {
1552 percent = (5 + (1000 * data->cbr) / data->max_nonturbo) / 10;
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001553 len += fprintf(fp, "(%3u%%) ", percent);
Adrian Hunter65c5e182017-06-30 11:36:42 +03001554 }
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001555 return len + perf_sample__fprintf_pt_spacing(len, fp);
Adrian Hunter65c5e182017-06-30 11:36:42 +03001556}
1557
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001558static int perf_sample__fprintf_synth(struct perf_sample *sample,
1559 struct perf_evsel *evsel, FILE *fp)
Adrian Hunter47e78082017-05-26 11:17:22 +03001560{
1561 switch (evsel->attr.config) {
Adrian Hunter65c5e182017-06-30 11:36:42 +03001562 case PERF_SYNTH_INTEL_PTWRITE:
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001563 return perf_sample__fprintf_synth_ptwrite(sample, fp);
Adrian Hunter65c5e182017-06-30 11:36:42 +03001564 case PERF_SYNTH_INTEL_MWAIT:
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001565 return perf_sample__fprintf_synth_mwait(sample, fp);
Adrian Hunter65c5e182017-06-30 11:36:42 +03001566 case PERF_SYNTH_INTEL_PWRE:
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001567 return perf_sample__fprintf_synth_pwre(sample, fp);
Adrian Hunter65c5e182017-06-30 11:36:42 +03001568 case PERF_SYNTH_INTEL_EXSTOP:
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001569 return perf_sample__fprintf_synth_exstop(sample, fp);
Adrian Hunter65c5e182017-06-30 11:36:42 +03001570 case PERF_SYNTH_INTEL_PWRX:
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001571 return perf_sample__fprintf_synth_pwrx(sample, fp);
Adrian Hunter65c5e182017-06-30 11:36:42 +03001572 case PERF_SYNTH_INTEL_CBR:
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001573 return perf_sample__fprintf_synth_cbr(sample, fp);
Adrian Hunter47e78082017-05-26 11:17:22 +03001574 default:
1575 break;
1576 }
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001577
1578 return 0;
Adrian Hunter47e78082017-05-26 11:17:22 +03001579}
1580
Jiri Olsa809e9422015-11-26 18:55:21 +01001581struct perf_script {
1582 struct perf_tool tool;
1583 struct perf_session *session;
1584 bool show_task_events;
1585 bool show_mmap_events;
1586 bool show_switch_events;
Hari Bathini96a44bb2017-03-08 02:12:06 +05301587 bool show_namespace_events;
Jiri Olsa3d7c27b2018-01-07 17:03:53 +01001588 bool show_lost_events;
Jiri Olsa3233b372018-02-06 19:17:59 +01001589 bool show_round_events;
Jiri Olsacfc88742016-01-05 22:09:06 +01001590 bool allocated;
Arnaldo Carvalho de Meloa14390f2017-10-26 10:30:20 -03001591 bool per_event_dump;
Jiri Olsacfc88742016-01-05 22:09:06 +01001592 struct cpu_map *cpus;
1593 struct thread_map *threads;
Jiri Olsa9cdbc402016-01-07 10:14:05 +01001594 int name_width;
David Aherna91f4c42016-11-29 10:15:43 -07001595 const char *time_str;
Jin Yaocc2ef582018-01-10 23:00:33 +08001596 struct perf_time_interval *ptime_range;
1597 int range_size;
Jin Yao2ab046c2017-12-08 21:13:46 +08001598 int range_num;
Jiri Olsa809e9422015-11-26 18:55:21 +01001599};
1600
Jiri Olsa9cdbc402016-01-07 10:14:05 +01001601static int perf_evlist__max_name_len(struct perf_evlist *evlist)
1602{
1603 struct perf_evsel *evsel;
1604 int max = 0;
1605
Arnaldo Carvalho de Meloe5cadb92016-06-23 11:26:15 -03001606 evlist__for_each_entry(evlist, evsel) {
Jiri Olsa9cdbc402016-01-07 10:14:05 +01001607 int len = strlen(perf_evsel__name(evsel));
1608
1609 max = MAX(len, max);
1610 }
1611
1612 return max;
1613}
1614
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001615static int data_src__fprintf(u64 data_src, FILE *fp)
Jiri Olsac19ac912016-02-24 09:46:54 +01001616{
1617 struct mem_info mi = { .data_src.val = data_src };
1618 char decode[100];
1619 char out[100];
1620 static int maxlen;
1621 int len;
1622
1623 perf_script__meminfo_scnprintf(decode, 100, &mi);
1624
1625 len = scnprintf(out, 100, "%16" PRIx64 " %s", data_src, decode);
1626 if (maxlen < len)
1627 maxlen = len;
1628
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001629 return fprintf(fp, "%-*s", maxlen, out);
Jiri Olsac19ac912016-02-24 09:46:54 +01001630}
1631
Andi Kleen4bd1bef2017-11-17 13:43:00 -08001632struct metric_ctx {
1633 struct perf_sample *sample;
1634 struct thread *thread;
1635 struct perf_evsel *evsel;
1636 FILE *fp;
1637};
1638
Jiri Olsa6ca9a082018-08-30 08:32:28 +02001639static void script_print_metric(struct perf_stat_config *config __maybe_unused,
1640 void *ctx, const char *color,
Andi Kleen4bd1bef2017-11-17 13:43:00 -08001641 const char *fmt,
1642 const char *unit, double val)
1643{
1644 struct metric_ctx *mctx = ctx;
1645
1646 if (!fmt)
1647 return;
1648 perf_sample__fprintf_start(mctx->sample, mctx->thread, mctx->evsel,
Jiri Olsa28a0b392018-01-07 17:03:52 +01001649 PERF_RECORD_SAMPLE, mctx->fp);
Andi Kleen4bd1bef2017-11-17 13:43:00 -08001650 fputs("\tmetric: ", mctx->fp);
1651 if (color)
1652 color_fprintf(mctx->fp, color, fmt, val);
1653 else
1654 printf(fmt, val);
1655 fprintf(mctx->fp, " %s\n", unit);
1656}
1657
Jiri Olsa6ca9a082018-08-30 08:32:28 +02001658static void script_new_line(struct perf_stat_config *config __maybe_unused,
1659 void *ctx)
Andi Kleen4bd1bef2017-11-17 13:43:00 -08001660{
1661 struct metric_ctx *mctx = ctx;
1662
1663 perf_sample__fprintf_start(mctx->sample, mctx->thread, mctx->evsel,
Jiri Olsa28a0b392018-01-07 17:03:52 +01001664 PERF_RECORD_SAMPLE, mctx->fp);
Andi Kleen4bd1bef2017-11-17 13:43:00 -08001665 fputs("\tmetric: ", mctx->fp);
1666}
1667
1668static void perf_sample__fprint_metric(struct perf_script *script,
1669 struct thread *thread,
1670 struct perf_evsel *evsel,
1671 struct perf_sample *sample,
1672 FILE *fp)
1673{
1674 struct perf_stat_output_ctx ctx = {
1675 .print_metric = script_print_metric,
1676 .new_line = script_new_line,
1677 .ctx = &(struct metric_ctx) {
1678 .sample = sample,
1679 .thread = thread,
1680 .evsel = evsel,
1681 .fp = fp,
1682 },
1683 .force_header = false,
1684 };
1685 struct perf_evsel *ev2;
Andi Kleen4bd1bef2017-11-17 13:43:00 -08001686 u64 val;
1687
Andi Kleen4bd1bef2017-11-17 13:43:00 -08001688 if (!evsel->stats)
1689 perf_evlist__alloc_stats(script->session->evlist, false);
1690 if (evsel_script(evsel->leader)->gnum++ == 0)
1691 perf_stat__reset_shadow_stats();
1692 val = sample->period * evsel->scale;
1693 perf_stat__update_shadow_stats(evsel,
1694 val,
Jin Yao1fcd0392017-12-05 22:03:04 +08001695 sample->cpu,
1696 &rt_stat);
Andi Kleen4bd1bef2017-11-17 13:43:00 -08001697 evsel_script(evsel)->val = val;
1698 if (evsel_script(evsel->leader)->gnum == evsel->leader->nr_members) {
1699 for_each_group_member (ev2, evsel->leader) {
Jiri Olsa6ca9a082018-08-30 08:32:28 +02001700 perf_stat__print_shadow_stats(&stat_config, ev2,
Andi Kleen4bd1bef2017-11-17 13:43:00 -08001701 evsel_script(ev2)->val,
1702 sample->cpu,
1703 &ctx,
Jin Yaoe0128b32017-12-05 22:03:05 +08001704 NULL,
1705 &rt_stat);
Andi Kleen4bd1bef2017-11-17 13:43:00 -08001706 }
1707 evsel_script(evsel->leader)->gnum = 0;
1708 }
1709}
1710
Andi Kleen99f753f2018-09-20 11:05:39 -07001711static bool show_event(struct perf_sample *sample,
1712 struct perf_evsel *evsel,
1713 struct thread *thread,
1714 struct addr_location *al)
1715{
Adrian Hunter256d92b2018-12-21 14:06:19 +02001716 int depth = thread_stack__depth(thread, sample->cpu);
Andi Kleen99f753f2018-09-20 11:05:39 -07001717
1718 if (!symbol_conf.graph_function)
1719 return true;
1720
1721 if (thread->filter) {
1722 if (depth <= thread->filter_entry_depth) {
1723 thread->filter = false;
1724 return false;
1725 }
1726 return true;
1727 } else {
1728 const char *s = symbol_conf.graph_function;
1729 u64 ip;
1730 const char *name = resolve_branch_sym(sample, evsel, thread, al,
1731 &ip);
1732 unsigned nlen;
1733
1734 if (!name)
1735 return false;
1736 nlen = strlen(name);
1737 while (*s) {
1738 unsigned len = strcspn(s, ",");
1739 if (nlen == len && !strncmp(name, s, len)) {
1740 thread->filter = true;
1741 thread->filter_entry_depth = depth;
1742 return true;
1743 }
1744 s += len;
1745 if (*s == ',')
1746 s++;
1747 }
1748 return false;
1749 }
1750}
1751
Arnaldo Carvalho de Meloa3dff302016-03-23 11:55:24 -03001752static void process_event(struct perf_script *script,
Jiri Olsa809e9422015-11-26 18:55:21 +01001753 struct perf_sample *sample, struct perf_evsel *evsel,
Andi Kleen48d02a12017-02-23 15:46:34 -08001754 struct addr_location *al,
1755 struct machine *machine)
David Ahernbe6d8422011-03-09 22:23:23 -07001756{
Arnaldo Carvalho de Melof9d5d542015-04-01 13:29:25 -03001757 struct thread *thread = al->thread;
Arnaldo Carvalho de Melo9e69c212011-03-15 15:44:01 -03001758 struct perf_event_attr *attr = &evsel->attr;
Adrian Hunter14057202017-06-21 13:17:19 +03001759 unsigned int type = output_type(attr->type);
Arnaldo Carvalho de Melo642ee1c2017-10-30 13:11:15 -03001760 struct perf_evsel_script *es = evsel->priv;
1761 FILE *fp = es->fp;
David Ahern1424dc92011-03-09 22:23:28 -07001762
Adrian Hunter14057202017-06-21 13:17:19 +03001763 if (output[type].fields == 0)
David Ahern1424dc92011-03-09 22:23:28 -07001764 return;
1765
Andi Kleen99f753f2018-09-20 11:05:39 -07001766 if (!show_event(sample, evsel, thread, al))
1767 return;
1768
Arnaldo Carvalho de Melo642ee1c2017-10-30 13:11:15 -03001769 ++es->samples;
1770
Jiri Olsa28a0b392018-01-07 17:03:52 +01001771 perf_sample__fprintf_start(sample, thread, evsel,
1772 PERF_RECORD_SAMPLE, fp);
David Ahern745f43e2011-03-09 22:23:26 -07001773
Jiri Olsa535aeaae2014-08-25 16:45:42 +02001774 if (PRINT_FIELD(PERIOD))
Arnaldo Carvalho de Melo69c71252017-10-26 09:51:13 -03001775 fprintf(fp, "%10" PRIu64 " ", sample->period);
Jiri Olsa535aeaae2014-08-25 16:45:42 +02001776
Namhyung Kime944d3d2013-11-18 14:34:52 +09001777 if (PRINT_FIELD(EVNAME)) {
1778 const char *evname = perf_evsel__name(evsel);
Jiri Olsa9cdbc402016-01-07 10:14:05 +01001779
1780 if (!script->name_width)
1781 script->name_width = perf_evlist__max_name_len(script->session->evlist);
1782
Arnaldo Carvalho de Melo69c71252017-10-26 09:51:13 -03001783 fprintf(fp, "%*s: ", script->name_width, evname ?: "[unknown]");
Namhyung Kime944d3d2013-11-18 14:34:52 +09001784 }
1785
Adrian Hunter400ea6d2015-04-09 18:54:05 +03001786 if (print_flags)
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001787 perf_sample__fprintf_flags(sample->flags, fp);
Adrian Hunter400ea6d2015-04-09 18:54:05 +03001788
Akihiro Nagai95582592012-01-30 13:43:09 +09001789 if (is_bts_event(attr)) {
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001790 perf_sample__fprintf_bts(sample, evsel, thread, al, machine, fp);
Akihiro Nagai95582592012-01-30 13:43:09 +09001791 return;
1792 }
1793
Andi Kleen96167162019-01-17 11:48:34 -08001794 if (PRINT_FIELD(TRACE) && sample->raw_data) {
Arnaldo Carvalho de Melo894f3f12017-10-26 10:26:52 -03001795 event_format__fprintf(evsel->tp_format, sample->cpu,
1796 sample->raw_data, sample->raw_size, fp);
1797 }
Adrian Hunter47e78082017-05-26 11:17:22 +03001798
1799 if (attr->type == PERF_TYPE_SYNTH && PRINT_FIELD(SYNTH))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001800 perf_sample__fprintf_synth(sample, evsel, fp);
Adrian Hunter47e78082017-05-26 11:17:22 +03001801
David Ahern7cec0922011-05-30 13:08:23 -06001802 if (PRINT_FIELD(ADDR))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001803 perf_sample__fprintf_addr(sample, thread, attr, fp);
David Ahern7cec0922011-05-30 13:08:23 -06001804
Jiri Olsa94ddddf2016-02-15 09:34:51 +01001805 if (PRINT_FIELD(DATA_SRC))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001806 data_src__fprintf(sample->data_src, fp);
Jiri Olsa94ddddf2016-02-15 09:34:51 +01001807
1808 if (PRINT_FIELD(WEIGHT))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001809 fprintf(fp, "%16" PRIu64, sample->weight);
Jiri Olsa94ddddf2016-02-15 09:34:51 +01001810
David Ahern787bef12011-05-27 14:28:43 -06001811 if (PRINT_FIELD(IP)) {
Chris Phlipote557b672016-04-19 19:32:11 -07001812 struct callchain_cursor *cursor = NULL;
David Aherna6ffaf92013-08-07 22:50:51 -04001813
Arnaldo Carvalho de Melo92231522016-04-18 11:31:46 -03001814 if (symbol_conf.use_callchain && sample->callchain &&
Chris Phlipote557b672016-04-19 19:32:11 -07001815 thread__resolve_callchain(al->thread, &callchain_cursor, evsel,
Arnaldo Carvalho de Melo6f736732016-04-14 17:45:51 -03001816 sample, NULL, NULL, scripting_max_stack) == 0)
Chris Phlipote557b672016-04-19 19:32:11 -07001817 cursor = &callchain_cursor;
Arnaldo Carvalho de Melo6f736732016-04-14 17:45:51 -03001818
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001819 fputc(cursor ? '\n' : ' ', fp);
1820 sample__fprintf_sym(sample, al, 0, output[type].print_ip_opts, cursor, fp);
David Ahernc0230b22011-03-09 22:23:27 -07001821 }
1822
Stephane Eranianfc36f942015-08-31 18:41:10 +02001823 if (PRINT_FIELD(IREGS))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001824 perf_sample__fprintf_iregs(sample, attr, fp);
Stephane Eranianfc36f942015-08-31 18:41:10 +02001825
Andi Kleenb1491ac2017-09-05 11:40:57 -07001826 if (PRINT_FIELD(UREGS))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001827 perf_sample__fprintf_uregs(sample, attr, fp);
Andi Kleenb1491ac2017-09-05 11:40:57 -07001828
Stephane Eraniandc323ce2015-08-31 18:41:13 +02001829 if (PRINT_FIELD(BRSTACK))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001830 perf_sample__fprintf_brstack(sample, thread, attr, fp);
Stephane Eraniandc323ce2015-08-31 18:41:13 +02001831 else if (PRINT_FIELD(BRSTACKSYM))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001832 perf_sample__fprintf_brstacksym(sample, thread, attr, fp);
Mark Santaniello106dacd2017-06-19 09:38:25 -07001833 else if (PRINT_FIELD(BRSTACKOFF))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001834 perf_sample__fprintf_brstackoff(sample, thread, attr, fp);
Stephane Eraniandc323ce2015-08-31 18:41:13 +02001835
Wang Nan30372f02016-02-24 11:20:45 +00001836 if (perf_evsel__is_bpf_output(evsel) && PRINT_FIELD(BPF_OUTPUT))
Arnaldo Carvalho de Meloa1a58702017-10-17 10:54:24 -03001837 perf_sample__fprintf_bpf_output(sample, fp);
1838 perf_sample__fprintf_insn(sample, attr, thread, machine, fp);
Kan Liang49d58f02017-08-29 13:11:11 -04001839
1840 if (PRINT_FIELD(PHYS_ADDR))
Arnaldo Carvalho de Melo69c71252017-10-26 09:51:13 -03001841 fprintf(fp, "%16" PRIx64, sample->phys_addr);
1842 fprintf(fp, "\n");
Andi Kleen4bd1bef2017-11-17 13:43:00 -08001843
Andi Kleendd2e18e2018-12-03 16:18:48 -08001844 if (PRINT_FIELD(SRCCODE)) {
1845 if (map__fprintf_srccode(al->map, al->addr, stdout,
1846 &thread->srccode_state))
1847 printf("\n");
1848 }
1849
Andi Kleen4bd1bef2017-11-17 13:43:00 -08001850 if (PRINT_FIELD(METRIC))
1851 perf_sample__fprint_metric(script, thread, evsel, sample, fp);
Milian Wolff7ee40672018-10-21 21:14:24 +02001852
1853 if (verbose)
1854 fflush(fp);
David Ahernbe6d8422011-03-09 22:23:23 -07001855}
1856
Tom Zanussi956ffd02009-11-25 01:15:46 -06001857static struct scripting_ops *scripting_ops;
1858
Jiri Olsa36e33c52016-01-06 11:49:56 +01001859static void __process_stat(struct perf_evsel *counter, u64 tstamp)
1860{
1861 int nthreads = thread_map__nr(counter->threads);
1862 int ncpus = perf_evsel__nr_cpus(counter);
1863 int cpu, thread;
1864 static int header_printed;
1865
1866 if (counter->system_wide)
1867 nthreads = 1;
1868
1869 if (!header_printed) {
1870 printf("%3s %8s %15s %15s %15s %15s %s\n",
1871 "CPU", "THREAD", "VAL", "ENA", "RUN", "TIME", "EVENT");
1872 header_printed = 1;
1873 }
1874
1875 for (thread = 0; thread < nthreads; thread++) {
1876 for (cpu = 0; cpu < ncpus; cpu++) {
1877 struct perf_counts_values *counts;
1878
1879 counts = perf_counts(counter->counts, cpu, thread);
1880
1881 printf("%3d %8d %15" PRIu64 " %15" PRIu64 " %15" PRIu64 " %15" PRIu64 " %s\n",
1882 counter->cpus->map[cpu],
1883 thread_map__pid(counter->threads, thread),
1884 counts->val,
1885 counts->ena,
1886 counts->run,
1887 tstamp,
1888 perf_evsel__name(counter));
1889 }
1890 }
1891}
1892
Jiri Olsae099eba2016-01-05 22:09:09 +01001893static void process_stat(struct perf_evsel *counter, u64 tstamp)
1894{
1895 if (scripting_ops && scripting_ops->process_stat)
1896 scripting_ops->process_stat(&stat_config, counter, tstamp);
Jiri Olsa36e33c52016-01-06 11:49:56 +01001897 else
1898 __process_stat(counter, tstamp);
Jiri Olsae099eba2016-01-05 22:09:09 +01001899}
1900
1901static void process_stat_interval(u64 tstamp)
1902{
1903 if (scripting_ops && scripting_ops->process_stat_interval)
1904 scripting_ops->process_stat_interval(tstamp);
1905}
1906
Tom Zanussi956ffd02009-11-25 01:15:46 -06001907static void setup_scripting(void)
1908{
Tom Zanussi16c632d2009-11-25 01:15:48 -06001909 setup_perl_scripting();
Tom Zanussi7e4b21b2010-01-27 02:27:57 -06001910 setup_python_scripting();
Tom Zanussi956ffd02009-11-25 01:15:46 -06001911}
1912
Adrian Hunterd445dd22014-08-15 22:08:37 +03001913static int flush_scripting(void)
1914{
Jiri Olsa2aaecfc2015-11-26 14:55:23 +01001915 return scripting_ops ? scripting_ops->flush_script() : 0;
Adrian Hunterd445dd22014-08-15 22:08:37 +03001916}
1917
Tom Zanussi956ffd02009-11-25 01:15:46 -06001918static int cleanup_scripting(void)
1919{
Ingo Molnar133dc4c2010-11-16 18:45:39 +01001920 pr_debug("\nperf script stopped\n");
Tom Zanussi3824a4e2010-05-09 23:46:57 -05001921
Jiri Olsa2aaecfc2015-11-26 14:55:23 +01001922 return scripting_ops ? scripting_ops->stop_script() : 0;
Tom Zanussi956ffd02009-11-25 01:15:46 -06001923}
1924
Jiri Olsa809e9422015-11-26 18:55:21 +01001925static int process_sample_event(struct perf_tool *tool,
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -02001926 union perf_event *event,
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -02001927 struct perf_sample *sample,
Arnaldo Carvalho de Melo9e69c212011-03-15 15:44:01 -03001928 struct perf_evsel *evsel,
Arnaldo Carvalho de Melo743eb862011-11-28 07:56:39 -02001929 struct machine *machine)
Frederic Weisbecker5f9c39d2009-08-17 16:18:08 +02001930{
Jiri Olsa809e9422015-11-26 18:55:21 +01001931 struct perf_script *scr = container_of(tool, struct perf_script, tool);
David Aherne7984b72011-11-21 10:02:52 -07001932 struct addr_location al;
Frederic Weisbecker5f9c39d2009-08-17 16:18:08 +02001933
Jin Yao2ab046c2017-12-08 21:13:46 +08001934 if (perf_time__ranges_skip_sample(scr->ptime_range, scr->range_num,
1935 sample->time)) {
David Aherna91f4c42016-11-29 10:15:43 -07001936 return 0;
Jin Yao2ab046c2017-12-08 21:13:46 +08001937 }
David Aherna91f4c42016-11-29 10:15:43 -07001938
David Ahern1424dc92011-03-09 22:23:28 -07001939 if (debug_mode) {
1940 if (sample->time < last_timestamp) {
1941 pr_err("Samples misordered, previous: %" PRIu64
1942 " this: %" PRIu64 "\n", last_timestamp,
1943 sample->time);
1944 nr_unordered++;
Frederic Weisbeckere1889d72010-04-24 01:55:09 +02001945 }
David Ahern1424dc92011-03-09 22:23:28 -07001946 last_timestamp = sample->time;
1947 return 0;
Frederic Weisbecker5f9c39d2009-08-17 16:18:08 +02001948 }
Anton Blanchard5d67be92011-07-04 21:57:50 +10001949
Arnaldo Carvalho de Melobb3eb562016-03-22 18:39:09 -03001950 if (machine__resolve(machine, &al, sample) < 0) {
David Aherne7984b72011-11-21 10:02:52 -07001951 pr_err("problem processing %d event, skipping it.\n",
1952 event->header.type);
1953 return -1;
1954 }
1955
1956 if (al.filtered)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001957 goto out_put;
David Aherne7984b72011-11-21 10:02:52 -07001958
Anton Blanchard5d67be92011-07-04 21:57:50 +10001959 if (cpu_list && !test_bit(sample->cpu, cpu_bitmap))
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001960 goto out_put;
Anton Blanchard5d67be92011-07-04 21:57:50 +10001961
Jiri Olsa2aaecfc2015-11-26 14:55:23 +01001962 if (scripting_ops)
1963 scripting_ops->process_event(event, sample, evsel, &al);
1964 else
Andi Kleen48d02a12017-02-23 15:46:34 -08001965 process_event(scr, sample, evsel, &al, machine);
Jiri Olsa2aaecfc2015-11-26 14:55:23 +01001966
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03001967out_put:
1968 addr_location__put(&al);
Frederic Weisbecker5f9c39d2009-08-17 16:18:08 +02001969 return 0;
1970}
1971
Adrian Hunter7ea95722013-11-01 15:51:30 +02001972static int process_attr(struct perf_tool *tool, union perf_event *event,
1973 struct perf_evlist **pevlist)
1974{
1975 struct perf_script *scr = container_of(tool, struct perf_script, tool);
1976 struct perf_evlist *evlist;
1977 struct perf_evsel *evsel, *pos;
1978 int err;
Ravi Bangoriaa3af66f2018-06-25 18:12:19 +05301979 static struct perf_evsel_script *es;
Adrian Hunter7ea95722013-11-01 15:51:30 +02001980
1981 err = perf_event__process_attr(tool, event, pevlist);
1982 if (err)
1983 return err;
1984
1985 evlist = *pevlist;
1986 evsel = perf_evlist__last(*pevlist);
1987
Ravi Bangoriaa3af66f2018-06-25 18:12:19 +05301988 if (!evsel->priv) {
1989 if (scr->per_event_dump) {
1990 evsel->priv = perf_evsel_script__new(evsel,
1991 scr->session->data);
1992 } else {
1993 es = zalloc(sizeof(*es));
1994 if (!es)
1995 return -ENOMEM;
1996 es->fp = stdout;
1997 evsel->priv = es;
1998 }
1999 }
2000
Adrian Hunter14057202017-06-21 13:17:19 +03002001 if (evsel->attr.type >= PERF_TYPE_MAX &&
2002 evsel->attr.type != PERF_TYPE_SYNTH)
Adrian Hunter7ea95722013-11-01 15:51:30 +02002003 return 0;
2004
Arnaldo Carvalho de Meloe5cadb92016-06-23 11:26:15 -03002005 evlist__for_each_entry(evlist, pos) {
Adrian Hunter7ea95722013-11-01 15:51:30 +02002006 if (pos->attr.type == evsel->attr.type && pos != evsel)
2007 return 0;
2008 }
2009
2010 set_print_ip_opts(&evsel->attr);
2011
Jiri Olsad2b5a312015-10-16 12:41:25 +02002012 if (evsel->attr.sample_type)
2013 err = perf_evsel__check_attr(evsel, scr->session);
2014
2015 return err;
Adrian Hunter7ea95722013-11-01 15:51:30 +02002016}
2017
Namhyung Kimad7ebb92013-11-26 17:51:12 +09002018static int process_comm_event(struct perf_tool *tool,
2019 union perf_event *event,
2020 struct perf_sample *sample,
2021 struct machine *machine)
2022{
2023 struct thread *thread;
2024 struct perf_script *script = container_of(tool, struct perf_script, tool);
2025 struct perf_session *session = script->session;
Adrian Hunter06b234e2015-07-21 12:44:05 +03002026 struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
Namhyung Kimad7ebb92013-11-26 17:51:12 +09002027 int ret = -1;
2028
2029 thread = machine__findnew_thread(machine, event->comm.pid, event->comm.tid);
2030 if (thread == NULL) {
2031 pr_debug("problem processing COMM event, skipping it.\n");
2032 return -1;
2033 }
2034
2035 if (perf_event__process_comm(tool, event, sample, machine) < 0)
2036 goto out;
2037
2038 if (!evsel->attr.sample_id_all) {
2039 sample->cpu = 0;
2040 sample->time = 0;
2041 sample->tid = event->comm.tid;
2042 sample->pid = event->comm.pid;
2043 }
Jiri Olsa28a0b392018-01-07 17:03:52 +01002044 perf_sample__fprintf_start(sample, thread, evsel,
2045 PERF_RECORD_COMM, stdout);
Namhyung Kimad7ebb92013-11-26 17:51:12 +09002046 perf_event__fprintf(event, stdout);
2047 ret = 0;
Namhyung Kimad7ebb92013-11-26 17:51:12 +09002048out:
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002049 thread__put(thread);
Namhyung Kimad7ebb92013-11-26 17:51:12 +09002050 return ret;
2051}
2052
Hari Bathini96a44bb2017-03-08 02:12:06 +05302053static int process_namespaces_event(struct perf_tool *tool,
2054 union perf_event *event,
2055 struct perf_sample *sample,
2056 struct machine *machine)
2057{
2058 struct thread *thread;
2059 struct perf_script *script = container_of(tool, struct perf_script, tool);
2060 struct perf_session *session = script->session;
2061 struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
2062 int ret = -1;
2063
2064 thread = machine__findnew_thread(machine, event->namespaces.pid,
2065 event->namespaces.tid);
2066 if (thread == NULL) {
2067 pr_debug("problem processing NAMESPACES event, skipping it.\n");
2068 return -1;
2069 }
2070
2071 if (perf_event__process_namespaces(tool, event, sample, machine) < 0)
2072 goto out;
2073
2074 if (!evsel->attr.sample_id_all) {
2075 sample->cpu = 0;
2076 sample->time = 0;
2077 sample->tid = event->namespaces.tid;
2078 sample->pid = event->namespaces.pid;
2079 }
Jiri Olsa28a0b392018-01-07 17:03:52 +01002080 perf_sample__fprintf_start(sample, thread, evsel,
2081 PERF_RECORD_NAMESPACES, stdout);
Hari Bathini96a44bb2017-03-08 02:12:06 +05302082 perf_event__fprintf(event, stdout);
2083 ret = 0;
2084out:
2085 thread__put(thread);
2086 return ret;
2087}
2088
Namhyung Kimad7ebb92013-11-26 17:51:12 +09002089static int process_fork_event(struct perf_tool *tool,
2090 union perf_event *event,
2091 struct perf_sample *sample,
2092 struct machine *machine)
2093{
2094 struct thread *thread;
2095 struct perf_script *script = container_of(tool, struct perf_script, tool);
2096 struct perf_session *session = script->session;
Adrian Hunter06b234e2015-07-21 12:44:05 +03002097 struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
Namhyung Kimad7ebb92013-11-26 17:51:12 +09002098
2099 if (perf_event__process_fork(tool, event, sample, machine) < 0)
2100 return -1;
2101
2102 thread = machine__findnew_thread(machine, event->fork.pid, event->fork.tid);
2103 if (thread == NULL) {
2104 pr_debug("problem processing FORK event, skipping it.\n");
2105 return -1;
2106 }
2107
2108 if (!evsel->attr.sample_id_all) {
2109 sample->cpu = 0;
2110 sample->time = event->fork.time;
2111 sample->tid = event->fork.tid;
2112 sample->pid = event->fork.pid;
2113 }
Jiri Olsa28a0b392018-01-07 17:03:52 +01002114 perf_sample__fprintf_start(sample, thread, evsel,
2115 PERF_RECORD_FORK, stdout);
Namhyung Kimad7ebb92013-11-26 17:51:12 +09002116 perf_event__fprintf(event, stdout);
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002117 thread__put(thread);
Namhyung Kimad7ebb92013-11-26 17:51:12 +09002118
2119 return 0;
2120}
2121static int process_exit_event(struct perf_tool *tool,
2122 union perf_event *event,
2123 struct perf_sample *sample,
2124 struct machine *machine)
2125{
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002126 int err = 0;
Namhyung Kimad7ebb92013-11-26 17:51:12 +09002127 struct thread *thread;
2128 struct perf_script *script = container_of(tool, struct perf_script, tool);
2129 struct perf_session *session = script->session;
Adrian Hunter06b234e2015-07-21 12:44:05 +03002130 struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
Namhyung Kimad7ebb92013-11-26 17:51:12 +09002131
2132 thread = machine__findnew_thread(machine, event->fork.pid, event->fork.tid);
2133 if (thread == NULL) {
2134 pr_debug("problem processing EXIT event, skipping it.\n");
2135 return -1;
2136 }
2137
2138 if (!evsel->attr.sample_id_all) {
2139 sample->cpu = 0;
2140 sample->time = 0;
Adrian Hunter53ff6bc2015-08-18 12:07:05 +03002141 sample->tid = event->fork.tid;
2142 sample->pid = event->fork.pid;
Namhyung Kimad7ebb92013-11-26 17:51:12 +09002143 }
Jiri Olsa28a0b392018-01-07 17:03:52 +01002144 perf_sample__fprintf_start(sample, thread, evsel,
2145 PERF_RECORD_EXIT, stdout);
Namhyung Kimad7ebb92013-11-26 17:51:12 +09002146 perf_event__fprintf(event, stdout);
2147
2148 if (perf_event__process_exit(tool, event, sample, machine) < 0)
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002149 err = -1;
Namhyung Kimad7ebb92013-11-26 17:51:12 +09002150
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002151 thread__put(thread);
2152 return err;
Namhyung Kimad7ebb92013-11-26 17:51:12 +09002153}
2154
Namhyung Kimba1ddf42013-11-26 17:54:26 +09002155static int process_mmap_event(struct perf_tool *tool,
2156 union perf_event *event,
2157 struct perf_sample *sample,
2158 struct machine *machine)
2159{
2160 struct thread *thread;
2161 struct perf_script *script = container_of(tool, struct perf_script, tool);
2162 struct perf_session *session = script->session;
Adrian Hunter06b234e2015-07-21 12:44:05 +03002163 struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
Namhyung Kimba1ddf42013-11-26 17:54:26 +09002164
2165 if (perf_event__process_mmap(tool, event, sample, machine) < 0)
2166 return -1;
2167
2168 thread = machine__findnew_thread(machine, event->mmap.pid, event->mmap.tid);
2169 if (thread == NULL) {
2170 pr_debug("problem processing MMAP event, skipping it.\n");
2171 return -1;
2172 }
2173
2174 if (!evsel->attr.sample_id_all) {
2175 sample->cpu = 0;
2176 sample->time = 0;
2177 sample->tid = event->mmap.tid;
2178 sample->pid = event->mmap.pid;
2179 }
Jiri Olsa28a0b392018-01-07 17:03:52 +01002180 perf_sample__fprintf_start(sample, thread, evsel,
2181 PERF_RECORD_MMAP, stdout);
Namhyung Kimba1ddf42013-11-26 17:54:26 +09002182 perf_event__fprintf(event, stdout);
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002183 thread__put(thread);
Namhyung Kimba1ddf42013-11-26 17:54:26 +09002184 return 0;
2185}
2186
2187static int process_mmap2_event(struct perf_tool *tool,
2188 union perf_event *event,
2189 struct perf_sample *sample,
2190 struct machine *machine)
2191{
2192 struct thread *thread;
2193 struct perf_script *script = container_of(tool, struct perf_script, tool);
2194 struct perf_session *session = script->session;
Adrian Hunter06b234e2015-07-21 12:44:05 +03002195 struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
Namhyung Kimba1ddf42013-11-26 17:54:26 +09002196
2197 if (perf_event__process_mmap2(tool, event, sample, machine) < 0)
2198 return -1;
2199
2200 thread = machine__findnew_thread(machine, event->mmap2.pid, event->mmap2.tid);
2201 if (thread == NULL) {
2202 pr_debug("problem processing MMAP2 event, skipping it.\n");
2203 return -1;
2204 }
2205
2206 if (!evsel->attr.sample_id_all) {
2207 sample->cpu = 0;
2208 sample->time = 0;
2209 sample->tid = event->mmap2.tid;
2210 sample->pid = event->mmap2.pid;
2211 }
Jiri Olsa28a0b392018-01-07 17:03:52 +01002212 perf_sample__fprintf_start(sample, thread, evsel,
2213 PERF_RECORD_MMAP2, stdout);
Namhyung Kimba1ddf42013-11-26 17:54:26 +09002214 perf_event__fprintf(event, stdout);
Arnaldo Carvalho de Melob91fc392015-04-06 20:43:22 -03002215 thread__put(thread);
Namhyung Kimba1ddf42013-11-26 17:54:26 +09002216 return 0;
2217}
2218
Adrian Hunter7c148982015-07-21 12:44:06 +03002219static int process_switch_event(struct perf_tool *tool,
2220 union perf_event *event,
2221 struct perf_sample *sample,
2222 struct machine *machine)
2223{
2224 struct thread *thread;
2225 struct perf_script *script = container_of(tool, struct perf_script, tool);
2226 struct perf_session *session = script->session;
2227 struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
2228
2229 if (perf_event__process_switch(tool, event, sample, machine) < 0)
2230 return -1;
2231
2232 thread = machine__findnew_thread(machine, sample->pid,
2233 sample->tid);
2234 if (thread == NULL) {
2235 pr_debug("problem processing SWITCH event, skipping it.\n");
2236 return -1;
2237 }
2238
Jiri Olsa28a0b392018-01-07 17:03:52 +01002239 perf_sample__fprintf_start(sample, thread, evsel,
2240 PERF_RECORD_SWITCH, stdout);
Adrian Hunter7c148982015-07-21 12:44:06 +03002241 perf_event__fprintf(event, stdout);
2242 thread__put(thread);
2243 return 0;
2244}
2245
Jiri Olsa3d7c27b2018-01-07 17:03:53 +01002246static int
2247process_lost_event(struct perf_tool *tool,
2248 union perf_event *event,
2249 struct perf_sample *sample,
2250 struct machine *machine)
2251{
2252 struct perf_script *script = container_of(tool, struct perf_script, tool);
2253 struct perf_session *session = script->session;
2254 struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
2255 struct thread *thread;
2256
2257 thread = machine__findnew_thread(machine, sample->pid,
2258 sample->tid);
2259 if (thread == NULL)
2260 return -1;
2261
2262 perf_sample__fprintf_start(sample, thread, evsel,
2263 PERF_RECORD_LOST, stdout);
2264 perf_event__fprintf(event, stdout);
2265 thread__put(thread);
2266 return 0;
2267}
2268
Jiri Olsa3233b372018-02-06 19:17:59 +01002269static int
2270process_finished_round_event(struct perf_tool *tool __maybe_unused,
2271 union perf_event *event,
2272 struct ordered_events *oe __maybe_unused)
2273
2274{
2275 perf_event__fprintf(event, stdout);
2276 return 0;
2277}
2278
Irina Tirdea1d037ca2012-09-11 01:15:03 +03002279static void sig_handler(int sig __maybe_unused)
Tom Zanussic239da32010-04-01 23:59:18 -05002280{
2281 session_done = 1;
2282}
2283
Arnaldo Carvalho de Meloa14390f2017-10-26 10:30:20 -03002284static void perf_script__fclose_per_event_dump(struct perf_script *script)
2285{
2286 struct perf_evlist *evlist = script->session->evlist;
2287 struct perf_evsel *evsel;
2288
2289 evlist__for_each_entry(evlist, evsel) {
2290 if (!evsel->priv)
2291 break;
Arnaldo Carvalho de Melo642ee1c2017-10-30 13:11:15 -03002292 perf_evsel_script__delete(evsel->priv);
Arnaldo Carvalho de Meloa14390f2017-10-26 10:30:20 -03002293 evsel->priv = NULL;
2294 }
2295}
2296
2297static int perf_script__fopen_per_event_dump(struct perf_script *script)
2298{
2299 struct perf_evsel *evsel;
2300
2301 evlist__for_each_entry(script->session->evlist, evsel) {
Arnaldo Carvalho de Melofa48c892017-11-09 16:04:26 -03002302 /*
2303 * Already setup? I.e. we may be called twice in cases like
2304 * Intel PT, one for the intel_pt// and dummy events, then
2305 * for the evsels syntheized from the auxtrace info.
2306 *
2307 * Ses perf_script__process_auxtrace_info.
2308 */
2309 if (evsel->priv != NULL)
2310 continue;
2311
Jiri Olsa8ceb41d2017-01-23 22:07:59 +01002312 evsel->priv = perf_evsel_script__new(evsel, script->session->data);
Arnaldo Carvalho de Meloa14390f2017-10-26 10:30:20 -03002313 if (evsel->priv == NULL)
2314 goto out_err_fclose;
2315 }
2316
2317 return 0;
2318
2319out_err_fclose:
2320 perf_script__fclose_per_event_dump(script);
2321 return -1;
2322}
2323
2324static int perf_script__setup_per_event_dump(struct perf_script *script)
2325{
2326 struct perf_evsel *evsel;
Arnaldo Carvalho de Melo642ee1c2017-10-30 13:11:15 -03002327 static struct perf_evsel_script es_stdout;
Arnaldo Carvalho de Meloa14390f2017-10-26 10:30:20 -03002328
2329 if (script->per_event_dump)
2330 return perf_script__fopen_per_event_dump(script);
2331
Arnaldo Carvalho de Melo642ee1c2017-10-30 13:11:15 -03002332 es_stdout.fp = stdout;
2333
Arnaldo Carvalho de Meloa14390f2017-10-26 10:30:20 -03002334 evlist__for_each_entry(script->session->evlist, evsel)
Arnaldo Carvalho de Melo642ee1c2017-10-30 13:11:15 -03002335 evsel->priv = &es_stdout;
Arnaldo Carvalho de Meloa14390f2017-10-26 10:30:20 -03002336
2337 return 0;
2338}
2339
Arnaldo Carvalho de Melo642ee1c2017-10-30 13:11:15 -03002340static void perf_script__exit_per_event_dump_stats(struct perf_script *script)
2341{
2342 struct perf_evsel *evsel;
2343
2344 evlist__for_each_entry(script->session->evlist, evsel) {
2345 struct perf_evsel_script *es = evsel->priv;
2346
2347 perf_evsel_script__fprintf(es, stdout);
2348 perf_evsel_script__delete(es);
2349 evsel->priv = NULL;
2350 }
2351}
2352
Adrian Hunter6f3e5ed2013-10-22 10:34:07 +03002353static int __cmd_script(struct perf_script *script)
Frederic Weisbecker5f9c39d2009-08-17 16:18:08 +02002354{
Frederic Weisbecker6fcf7dd2010-05-27 15:46:25 +02002355 int ret;
2356
Tom Zanussic239da32010-04-01 23:59:18 -05002357 signal(SIGINT, sig_handler);
2358
Tony Jones8bf8c6d2019-01-20 11:14:14 -08002359 perf_stat__init_shadow_stats();
2360
Namhyung Kimad7ebb92013-11-26 17:51:12 +09002361 /* override event processing functions */
2362 if (script->show_task_events) {
2363 script->tool.comm = process_comm_event;
2364 script->tool.fork = process_fork_event;
2365 script->tool.exit = process_exit_event;
2366 }
Namhyung Kimba1ddf42013-11-26 17:54:26 +09002367 if (script->show_mmap_events) {
2368 script->tool.mmap = process_mmap_event;
2369 script->tool.mmap2 = process_mmap2_event;
2370 }
Adrian Hunter7c148982015-07-21 12:44:06 +03002371 if (script->show_switch_events)
2372 script->tool.context_switch = process_switch_event;
Hari Bathini96a44bb2017-03-08 02:12:06 +05302373 if (script->show_namespace_events)
2374 script->tool.namespaces = process_namespaces_event;
Jiri Olsa3d7c27b2018-01-07 17:03:53 +01002375 if (script->show_lost_events)
2376 script->tool.lost = process_lost_event;
Jiri Olsa3233b372018-02-06 19:17:59 +01002377 if (script->show_round_events) {
2378 script->tool.ordered_events = false;
2379 script->tool.finished_round = process_finished_round_event;
2380 }
Namhyung Kimad7ebb92013-11-26 17:51:12 +09002381
Arnaldo Carvalho de Meloa14390f2017-10-26 10:30:20 -03002382 if (perf_script__setup_per_event_dump(script)) {
2383 pr_err("Couldn't create the per event dump files\n");
2384 return -1;
2385 }
2386
Arnaldo Carvalho de Melob7b61cb2015-03-03 11:58:45 -03002387 ret = perf_session__process_events(script->session);
Frederic Weisbecker6fcf7dd2010-05-27 15:46:25 +02002388
Arnaldo Carvalho de Meloa14390f2017-10-26 10:30:20 -03002389 if (script->per_event_dump)
Arnaldo Carvalho de Melo642ee1c2017-10-30 13:11:15 -03002390 perf_script__exit_per_event_dump_stats(script);
Arnaldo Carvalho de Meloa14390f2017-10-26 10:30:20 -03002391
Arnaldo Carvalho de Melo6d8afb52011-01-04 16:27:30 -02002392 if (debug_mode)
Arnaldo Carvalho de Melo9486aa32011-01-22 20:37:02 -02002393 pr_err("Misordered timestamps: %" PRIu64 "\n", nr_unordered);
Frederic Weisbecker6fcf7dd2010-05-27 15:46:25 +02002394
2395 return ret;
Frederic Weisbecker5f9c39d2009-08-17 16:18:08 +02002396}
2397
Tom Zanussi956ffd02009-11-25 01:15:46 -06002398struct script_spec {
2399 struct list_head node;
2400 struct scripting_ops *ops;
2401 char spec[0];
2402};
2403
Arnaldo Carvalho de Meloeccdfe22011-01-04 16:32:52 -02002404static LIST_HEAD(script_specs);
Tom Zanussi956ffd02009-11-25 01:15:46 -06002405
2406static struct script_spec *script_spec__new(const char *spec,
2407 struct scripting_ops *ops)
2408{
2409 struct script_spec *s = malloc(sizeof(*s) + strlen(spec) + 1);
2410
2411 if (s != NULL) {
2412 strcpy(s->spec, spec);
2413 s->ops = ops;
2414 }
2415
2416 return s;
2417}
2418
Tom Zanussi956ffd02009-11-25 01:15:46 -06002419static void script_spec__add(struct script_spec *s)
2420{
2421 list_add_tail(&s->node, &script_specs);
2422}
2423
2424static struct script_spec *script_spec__find(const char *spec)
2425{
2426 struct script_spec *s;
2427
2428 list_for_each_entry(s, &script_specs, node)
2429 if (strcasecmp(s->spec, spec) == 0)
2430 return s;
2431 return NULL;
2432}
2433
Tom Zanussi956ffd02009-11-25 01:15:46 -06002434int script_spec_register(const char *spec, struct scripting_ops *ops)
2435{
2436 struct script_spec *s;
2437
2438 s = script_spec__find(spec);
2439 if (s)
2440 return -1;
2441
Taeung Song8560bae2016-02-26 00:13:10 +09002442 s = script_spec__new(spec, ops);
Tom Zanussi956ffd02009-11-25 01:15:46 -06002443 if (!s)
2444 return -1;
Taeung Song8560bae2016-02-26 00:13:10 +09002445 else
2446 script_spec__add(s);
Tom Zanussi956ffd02009-11-25 01:15:46 -06002447
2448 return 0;
2449}
2450
2451static struct scripting_ops *script_spec__lookup(const char *spec)
2452{
2453 struct script_spec *s = script_spec__find(spec);
2454 if (!s)
2455 return NULL;
2456
2457 return s->ops;
2458}
2459
2460static void list_available_languages(void)
2461{
2462 struct script_spec *s;
2463
2464 fprintf(stderr, "\n");
2465 fprintf(stderr, "Scripting language extensions (used in "
Ingo Molnar133dc4c2010-11-16 18:45:39 +01002466 "perf script -s [spec:]script.[spec]):\n\n");
Tom Zanussi956ffd02009-11-25 01:15:46 -06002467
2468 list_for_each_entry(s, &script_specs, node)
2469 fprintf(stderr, " %-42s [%s]\n", s->spec, s->ops->name);
2470
2471 fprintf(stderr, "\n");
2472}
2473
Irina Tirdea1d037ca2012-09-11 01:15:03 +03002474static int parse_scriptname(const struct option *opt __maybe_unused,
2475 const char *str, int unset __maybe_unused)
Tom Zanussi956ffd02009-11-25 01:15:46 -06002476{
2477 char spec[PATH_MAX];
2478 const char *script, *ext;
2479 int len;
2480
Tom Zanussif526d682010-01-27 02:27:52 -06002481 if (strcmp(str, "lang") == 0) {
Tom Zanussi956ffd02009-11-25 01:15:46 -06002482 list_available_languages();
Tom Zanussif526d682010-01-27 02:27:52 -06002483 exit(0);
Tom Zanussi956ffd02009-11-25 01:15:46 -06002484 }
2485
2486 script = strchr(str, ':');
2487 if (script) {
2488 len = script - str;
2489 if (len >= PATH_MAX) {
2490 fprintf(stderr, "invalid language specifier");
2491 return -1;
2492 }
2493 strncpy(spec, str, len);
2494 spec[len] = '\0';
2495 scripting_ops = script_spec__lookup(spec);
2496 if (!scripting_ops) {
2497 fprintf(stderr, "invalid language specifier");
2498 return -1;
2499 }
2500 script++;
2501 } else {
2502 script = str;
Ben Hutchingsd1e95bb2010-10-10 16:11:02 +01002503 ext = strrchr(script, '.');
Tom Zanussi956ffd02009-11-25 01:15:46 -06002504 if (!ext) {
2505 fprintf(stderr, "invalid script extension");
2506 return -1;
2507 }
2508 scripting_ops = script_spec__lookup(++ext);
2509 if (!scripting_ops) {
2510 fprintf(stderr, "invalid script extension");
2511 return -1;
2512 }
2513 }
2514
2515 script_name = strdup(script);
2516
2517 return 0;
2518}
2519
Irina Tirdea1d037ca2012-09-11 01:15:03 +03002520static int parse_output_fields(const struct option *opt __maybe_unused,
2521 const char *arg, int unset __maybe_unused)
David Ahern745f43e2011-03-09 22:23:26 -07002522{
Arnaldo Carvalho de Melo49346e82017-04-05 11:43:41 -03002523 char *tok, *strtok_saveptr = NULL;
Sasha Levin50ca19a2012-12-20 14:11:19 -05002524 int i, imax = ARRAY_SIZE(all_output_options);
David Ahern2c9e45f72011-03-17 10:03:21 -06002525 int j;
David Ahern745f43e2011-03-09 22:23:26 -07002526 int rc = 0;
2527 char *str = strdup(arg);
David Ahern1424dc92011-03-09 22:23:28 -07002528 int type = -1;
Andi Kleen36ce5652017-06-02 08:48:10 -07002529 enum { DEFAULT, SET, ADD, REMOVE } change = DEFAULT;
David Ahern745f43e2011-03-09 22:23:26 -07002530
2531 if (!str)
2532 return -ENOMEM;
2533
David Ahern2c9e45f72011-03-17 10:03:21 -06002534 /* first word can state for which event type the user is specifying
2535 * the fields. If no type exists, the specified fields apply to all
2536 * event types found in the file minus the invalid fields for a type.
David Ahern1424dc92011-03-09 22:23:28 -07002537 */
David Ahern2c9e45f72011-03-17 10:03:21 -06002538 tok = strchr(str, ':');
2539 if (tok) {
2540 *tok = '\0';
2541 tok++;
2542 if (!strcmp(str, "hw"))
2543 type = PERF_TYPE_HARDWARE;
2544 else if (!strcmp(str, "sw"))
2545 type = PERF_TYPE_SOFTWARE;
2546 else if (!strcmp(str, "trace"))
2547 type = PERF_TYPE_TRACEPOINT;
Arun Sharma0817a6a2011-04-14 10:38:18 -07002548 else if (!strcmp(str, "raw"))
2549 type = PERF_TYPE_RAW;
Wang Nan27cfef02015-12-08 02:25:43 +00002550 else if (!strcmp(str, "break"))
2551 type = PERF_TYPE_BREAKPOINT;
Adrian Hunter14057202017-06-21 13:17:19 +03002552 else if (!strcmp(str, "synth"))
2553 type = OUTPUT_TYPE_SYNTH;
David Ahern2c9e45f72011-03-17 10:03:21 -06002554 else {
2555 fprintf(stderr, "Invalid event type in field string.\n");
Robert Richter38efb532011-11-25 11:38:40 +01002556 rc = -EINVAL;
2557 goto out;
David Ahern2c9e45f72011-03-17 10:03:21 -06002558 }
2559
2560 if (output[type].user_set)
2561 pr_warning("Overriding previous field request for %s events.\n",
2562 event_type(type));
2563
Jiri Olsa6ef362f2019-02-20 13:27:57 +01002564 /* Don't override defaults for +- */
2565 if (strchr(tok, '+') || strchr(tok, '-'))
2566 goto parse;
2567
David Ahern2c9e45f72011-03-17 10:03:21 -06002568 output[type].fields = 0;
2569 output[type].user_set = true;
David Ahern9cbdb702011-04-06 21:54:20 -06002570 output[type].wildcard_set = false;
David Ahern2c9e45f72011-03-17 10:03:21 -06002571
2572 } else {
2573 tok = str;
2574 if (strlen(str) == 0) {
2575 fprintf(stderr,
2576 "Cannot set fields to 'none' for all event types.\n");
2577 rc = -EINVAL;
2578 goto out;
2579 }
2580
Andi Kleen36ce5652017-06-02 08:48:10 -07002581 /* Don't override defaults for +- */
2582 if (strchr(str, '+') || strchr(str, '-'))
2583 goto parse;
2584
David Ahern2c9e45f72011-03-17 10:03:21 -06002585 if (output_set_by_user())
2586 pr_warning("Overriding previous field request for all events.\n");
2587
Adrian Hunter14057202017-06-21 13:17:19 +03002588 for (j = 0; j < OUTPUT_TYPE_MAX; ++j) {
David Ahern2c9e45f72011-03-17 10:03:21 -06002589 output[j].fields = 0;
2590 output[j].user_set = true;
David Ahern9cbdb702011-04-06 21:54:20 -06002591 output[j].wildcard_set = true;
David Ahern2c9e45f72011-03-17 10:03:21 -06002592 }
David Ahern1424dc92011-03-09 22:23:28 -07002593 }
2594
Andi Kleen36ce5652017-06-02 08:48:10 -07002595parse:
Arnaldo Carvalho de Melo49346e82017-04-05 11:43:41 -03002596 for (tok = strtok_r(tok, ",", &strtok_saveptr); tok; tok = strtok_r(NULL, ",", &strtok_saveptr)) {
Andi Kleen36ce5652017-06-02 08:48:10 -07002597 if (*tok == '+') {
2598 if (change == SET)
2599 goto out_badmix;
2600 change = ADD;
2601 tok++;
2602 } else if (*tok == '-') {
2603 if (change == SET)
2604 goto out_badmix;
2605 change = REMOVE;
2606 tok++;
2607 } else {
2608 if (change != SET && change != DEFAULT)
2609 goto out_badmix;
2610 change = SET;
2611 }
2612
David Ahern745f43e2011-03-09 22:23:26 -07002613 for (i = 0; i < imax; ++i) {
David Ahern2c9e45f72011-03-17 10:03:21 -06002614 if (strcmp(tok, all_output_options[i].str) == 0)
David Ahern745f43e2011-03-09 22:23:26 -07002615 break;
David Ahern745f43e2011-03-09 22:23:26 -07002616 }
Adrian Hunter400ea6d2015-04-09 18:54:05 +03002617 if (i == imax && strcmp(tok, "flags") == 0) {
Andi Kleen36ce5652017-06-02 08:48:10 -07002618 print_flags = change == REMOVE ? false : true;
Adrian Hunter400ea6d2015-04-09 18:54:05 +03002619 continue;
2620 }
David Ahern745f43e2011-03-09 22:23:26 -07002621 if (i == imax) {
David Ahern2c9e45f72011-03-17 10:03:21 -06002622 fprintf(stderr, "Invalid field requested.\n");
David Ahern745f43e2011-03-09 22:23:26 -07002623 rc = -EINVAL;
David Ahern2c9e45f72011-03-17 10:03:21 -06002624 goto out;
2625 }
2626
2627 if (type == -1) {
2628 /* add user option to all events types for
2629 * which it is valid
2630 */
Adrian Hunter14057202017-06-21 13:17:19 +03002631 for (j = 0; j < OUTPUT_TYPE_MAX; ++j) {
David Ahern2c9e45f72011-03-17 10:03:21 -06002632 if (output[j].invalid_fields & all_output_options[i].field) {
2633 pr_warning("\'%s\' not valid for %s events. Ignoring.\n",
2634 all_output_options[i].str, event_type(j));
Andi Kleen36ce5652017-06-02 08:48:10 -07002635 } else {
Andi Kleen4b6ac812019-02-24 07:37:12 -08002636 if (change == REMOVE) {
Andi Kleen36ce5652017-06-02 08:48:10 -07002637 output[j].fields &= ~all_output_options[i].field;
Andi Kleen4b6ac812019-02-24 07:37:12 -08002638 output[j].user_set_fields &= ~all_output_options[i].field;
2639 } else {
Andi Kleen36ce5652017-06-02 08:48:10 -07002640 output[j].fields |= all_output_options[i].field;
Andi Kleen4b6ac812019-02-24 07:37:12 -08002641 output[j].user_set_fields |= all_output_options[i].field;
2642 }
Andi Kleen37fed3d2018-09-18 05:32:09 -07002643 output[j].user_set = true;
2644 output[j].wildcard_set = true;
Andi Kleen36ce5652017-06-02 08:48:10 -07002645 }
David Ahern2c9e45f72011-03-17 10:03:21 -06002646 }
2647 } else {
2648 if (output[type].invalid_fields & all_output_options[i].field) {
2649 fprintf(stderr, "\'%s\' not valid for %s events.\n",
2650 all_output_options[i].str, event_type(type));
2651
2652 rc = -EINVAL;
2653 goto out;
2654 }
Jiri Olsa6ef362f2019-02-20 13:27:57 +01002655 if (change == REMOVE)
2656 output[type].fields &= ~all_output_options[i].field;
2657 else
2658 output[type].fields |= all_output_options[i].field;
Andi Kleen37fed3d2018-09-18 05:32:09 -07002659 output[type].user_set = true;
2660 output[type].wildcard_set = true;
David Ahern2c9e45f72011-03-17 10:03:21 -06002661 }
David Ahern2c9e45f72011-03-17 10:03:21 -06002662 }
2663
2664 if (type >= 0) {
2665 if (output[type].fields == 0) {
2666 pr_debug("No fields requested for %s type. "
2667 "Events will not be displayed.\n", event_type(type));
David Ahern745f43e2011-03-09 22:23:26 -07002668 }
David Ahern1424dc92011-03-09 22:23:28 -07002669 }
Andi Kleen36ce5652017-06-02 08:48:10 -07002670 goto out;
David Ahern745f43e2011-03-09 22:23:26 -07002671
Andi Kleen36ce5652017-06-02 08:48:10 -07002672out_badmix:
2673 fprintf(stderr, "Cannot mix +-field with overridden fields\n");
2674 rc = -EINVAL;
David Ahern2c9e45f72011-03-17 10:03:21 -06002675out:
David Ahern745f43e2011-03-09 22:23:26 -07002676 free(str);
2677 return rc;
2678}
2679
Arnaldo Carvalho de Meloa5e8e822016-04-08 11:25:59 -03002680#define for_each_lang(scripts_path, scripts_dir, lang_dirent) \
2681 while ((lang_dirent = readdir(scripts_dir)) != NULL) \
2682 if ((lang_dirent->d_type == DT_DIR || \
2683 (lang_dirent->d_type == DT_UNKNOWN && \
2684 is_directory(scripts_path, lang_dirent))) && \
2685 (strcmp(lang_dirent->d_name, ".")) && \
2686 (strcmp(lang_dirent->d_name, "..")))
Tom Zanussi4b9c0c52009-12-15 02:53:38 -06002687
Arnaldo Carvalho de Meloa5e8e822016-04-08 11:25:59 -03002688#define for_each_script(lang_path, lang_dir, script_dirent) \
2689 while ((script_dirent = readdir(lang_dir)) != NULL) \
2690 if (script_dirent->d_type != DT_DIR && \
2691 (script_dirent->d_type != DT_UNKNOWN || \
2692 !is_directory(lang_path, script_dirent)))
Tom Zanussi4b9c0c52009-12-15 02:53:38 -06002693
2694
2695#define RECORD_SUFFIX "-record"
2696#define REPORT_SUFFIX "-report"
2697
2698struct script_desc {
2699 struct list_head node;
2700 char *name;
2701 char *half_liner;
2702 char *args;
2703};
2704
Arnaldo Carvalho de Meloeccdfe22011-01-04 16:32:52 -02002705static LIST_HEAD(script_descs);
Tom Zanussi4b9c0c52009-12-15 02:53:38 -06002706
2707static struct script_desc *script_desc__new(const char *name)
2708{
2709 struct script_desc *s = zalloc(sizeof(*s));
2710
Tom Zanussib5b87312010-11-10 08:16:51 -06002711 if (s != NULL && name)
Tom Zanussi4b9c0c52009-12-15 02:53:38 -06002712 s->name = strdup(name);
2713
2714 return s;
2715}
2716
2717static void script_desc__delete(struct script_desc *s)
2718{
Arnaldo Carvalho de Melo74cf2492013-12-27 16:55:14 -03002719 zfree(&s->name);
2720 zfree(&s->half_liner);
2721 zfree(&s->args);
Tom Zanussi4b9c0c52009-12-15 02:53:38 -06002722 free(s);
2723}
2724
2725static void script_desc__add(struct script_desc *s)
2726{
2727 list_add_tail(&s->node, &script_descs);
2728}
2729
2730static struct script_desc *script_desc__find(const char *name)
2731{
2732 struct script_desc *s;
2733
2734 list_for_each_entry(s, &script_descs, node)
2735 if (strcasecmp(s->name, name) == 0)
2736 return s;
2737 return NULL;
2738}
2739
2740static struct script_desc *script_desc__findnew(const char *name)
2741{
2742 struct script_desc *s = script_desc__find(name);
2743
2744 if (s)
2745 return s;
2746
2747 s = script_desc__new(name);
2748 if (!s)
Dan Carpenter2ec5cab62017-07-22 10:36:10 +03002749 return NULL;
Tom Zanussi4b9c0c52009-12-15 02:53:38 -06002750
2751 script_desc__add(s);
2752
2753 return s;
Tom Zanussi4b9c0c52009-12-15 02:53:38 -06002754}
2755
Stephane Eranian965bb6b2010-12-03 17:52:01 +02002756static const char *ends_with(const char *str, const char *suffix)
Tom Zanussi4b9c0c52009-12-15 02:53:38 -06002757{
2758 size_t suffix_len = strlen(suffix);
Stephane Eranian965bb6b2010-12-03 17:52:01 +02002759 const char *p = str;
Tom Zanussi4b9c0c52009-12-15 02:53:38 -06002760
2761 if (strlen(str) > suffix_len) {
2762 p = str + strlen(str) - suffix_len;
2763 if (!strncmp(p, suffix, suffix_len))
2764 return p;
2765 }
2766
2767 return NULL;
2768}
2769
Tom Zanussi4b9c0c52009-12-15 02:53:38 -06002770static int read_script_info(struct script_desc *desc, const char *filename)
2771{
2772 char line[BUFSIZ], *p;
2773 FILE *fp;
2774
2775 fp = fopen(filename, "r");
2776 if (!fp)
2777 return -1;
2778
2779 while (fgets(line, sizeof(line), fp)) {
2780 p = ltrim(line);
2781 if (strlen(p) == 0)
2782 continue;
2783 if (*p != '#')
2784 continue;
2785 p++;
2786 if (strlen(p) && *p == '!')
2787 continue;
2788
2789 p = ltrim(p);
2790 if (strlen(p) && p[strlen(p) - 1] == '\n')
2791 p[strlen(p) - 1] = '\0';
2792
2793 if (!strncmp(p, "description:", strlen("description:"))) {
2794 p += strlen("description:");
2795 desc->half_liner = strdup(ltrim(p));
2796 continue;
2797 }
2798
2799 if (!strncmp(p, "args:", strlen("args:"))) {
2800 p += strlen("args:");
2801 desc->args = strdup(ltrim(p));
2802 continue;
2803 }
2804 }
2805
2806 fclose(fp);
2807
2808 return 0;
2809}
2810
Robert Richter38efb532011-11-25 11:38:40 +01002811static char *get_script_root(struct dirent *script_dirent, const char *suffix)
2812{
2813 char *script_root, *str;
2814
2815 script_root = strdup(script_dirent->d_name);
2816 if (!script_root)
2817 return NULL;
2818
2819 str = (char *)ends_with(script_root, suffix);
2820 if (!str) {
2821 free(script_root);
2822 return NULL;
2823 }
2824
2825 *str = '\0';
2826 return script_root;
2827}
2828
Irina Tirdea1d037ca2012-09-11 01:15:03 +03002829static int list_available_scripts(const struct option *opt __maybe_unused,
2830 const char *s __maybe_unused,
2831 int unset __maybe_unused)
Tom Zanussi4b9c0c52009-12-15 02:53:38 -06002832{
Arnaldo Carvalho de Meloa5e8e822016-04-08 11:25:59 -03002833 struct dirent *script_dirent, *lang_dirent;
Tom Zanussi4b9c0c52009-12-15 02:53:38 -06002834 char scripts_path[MAXPATHLEN];
2835 DIR *scripts_dir, *lang_dir;
2836 char script_path[MAXPATHLEN];
2837 char lang_path[MAXPATHLEN];
2838 struct script_desc *desc;
2839 char first_half[BUFSIZ];
2840 char *script_root;
Tom Zanussi4b9c0c52009-12-15 02:53:38 -06002841
Josh Poimboeuf46113a52015-12-15 09:39:37 -06002842 snprintf(scripts_path, MAXPATHLEN, "%s/scripts", get_argv_exec_path());
Tom Zanussi4b9c0c52009-12-15 02:53:38 -06002843
2844 scripts_dir = opendir(scripts_path);
He Kuang88ded4d2016-08-04 11:25:42 +00002845 if (!scripts_dir) {
2846 fprintf(stdout,
2847 "open(%s) failed.\n"
2848 "Check \"PERF_EXEC_PATH\" env to set scripts dir.\n",
2849 scripts_path);
2850 exit(-1);
2851 }
Tom Zanussi4b9c0c52009-12-15 02:53:38 -06002852
Arnaldo Carvalho de Meloa5e8e822016-04-08 11:25:59 -03002853 for_each_lang(scripts_path, scripts_dir, lang_dirent) {
Jiri Olsa77f18152018-03-19 09:29:01 +01002854 scnprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path,
2855 lang_dirent->d_name);
Tom Zanussi4b9c0c52009-12-15 02:53:38 -06002856 lang_dir = opendir(lang_path);
2857 if (!lang_dir)
2858 continue;
2859
Arnaldo Carvalho de Meloa5e8e822016-04-08 11:25:59 -03002860 for_each_script(lang_path, lang_dir, script_dirent) {
2861 script_root = get_script_root(script_dirent, REPORT_SUFFIX);
Robert Richter38efb532011-11-25 11:38:40 +01002862 if (script_root) {
Tom Zanussi4b9c0c52009-12-15 02:53:38 -06002863 desc = script_desc__findnew(script_root);
Jiri Olsa77f18152018-03-19 09:29:01 +01002864 scnprintf(script_path, MAXPATHLEN, "%s/%s",
2865 lang_path, script_dirent->d_name);
Tom Zanussi4b9c0c52009-12-15 02:53:38 -06002866 read_script_info(desc, script_path);
Robert Richter38efb532011-11-25 11:38:40 +01002867 free(script_root);
Tom Zanussi4b9c0c52009-12-15 02:53:38 -06002868 }
Tom Zanussi4b9c0c52009-12-15 02:53:38 -06002869 }
2870 }
2871
2872 fprintf(stdout, "List of available trace scripts:\n");
2873 list_for_each_entry(desc, &script_descs, node) {
2874 sprintf(first_half, "%s %s", desc->name,
2875 desc->args ? desc->args : "");
2876 fprintf(stdout, " %-36s %s\n", first_half,
2877 desc->half_liner ? desc->half_liner : "");
2878 }
2879
2880 exit(0);
2881}
2882
Feng Tange5f37052012-09-07 16:42:26 +08002883/*
Feng Tang49e639e2012-10-30 11:56:03 +08002884 * Some scripts specify the required events in their "xxx-record" file,
2885 * this function will check if the events in perf.data match those
2886 * mentioned in the "xxx-record".
2887 *
2888 * Fixme: All existing "xxx-record" are all in good formats "-e event ",
2889 * which is covered well now. And new parsing code should be added to
2890 * cover the future complexing formats like event groups etc.
2891 */
2892static int check_ev_match(char *dir_name, char *scriptname,
2893 struct perf_session *session)
2894{
2895 char filename[MAXPATHLEN], evname[128];
2896 char line[BUFSIZ], *p;
2897 struct perf_evsel *pos;
2898 int match, len;
2899 FILE *fp;
2900
Jiri Olsa77f18152018-03-19 09:29:01 +01002901 scnprintf(filename, MAXPATHLEN, "%s/bin/%s-record", dir_name, scriptname);
Feng Tang49e639e2012-10-30 11:56:03 +08002902
2903 fp = fopen(filename, "r");
2904 if (!fp)
2905 return -1;
2906
2907 while (fgets(line, sizeof(line), fp)) {
2908 p = ltrim(line);
2909 if (*p == '#')
2910 continue;
2911
2912 while (strlen(p)) {
2913 p = strstr(p, "-e");
2914 if (!p)
2915 break;
2916
2917 p += 2;
2918 p = ltrim(p);
2919 len = strcspn(p, " \t");
2920 if (!len)
2921 break;
2922
2923 snprintf(evname, len + 1, "%s", p);
2924
2925 match = 0;
Arnaldo Carvalho de Meloe5cadb92016-06-23 11:26:15 -03002926 evlist__for_each_entry(session->evlist, pos) {
Feng Tang49e639e2012-10-30 11:56:03 +08002927 if (!strcmp(perf_evsel__name(pos), evname)) {
2928 match = 1;
2929 break;
2930 }
2931 }
2932
2933 if (!match) {
2934 fclose(fp);
2935 return -1;
2936 }
2937 }
2938 }
2939
2940 fclose(fp);
2941 return 0;
2942}
2943
2944/*
Feng Tange5f37052012-09-07 16:42:26 +08002945 * Return -1 if none is found, otherwise the actual scripts number.
2946 *
2947 * Currently the only user of this function is the script browser, which
2948 * will list all statically runnable scripts, select one, execute it and
2949 * show the output in a perf browser.
2950 */
2951int find_scripts(char **scripts_array, char **scripts_path_array)
2952{
Arnaldo Carvalho de Meloa5e8e822016-04-08 11:25:59 -03002953 struct dirent *script_dirent, *lang_dirent;
Feng Tang49e639e2012-10-30 11:56:03 +08002954 char scripts_path[MAXPATHLEN], lang_path[MAXPATHLEN];
Feng Tange5f37052012-09-07 16:42:26 +08002955 DIR *scripts_dir, *lang_dir;
Feng Tang49e639e2012-10-30 11:56:03 +08002956 struct perf_session *session;
Jiri Olsa8ceb41d2017-01-23 22:07:59 +01002957 struct perf_data data = {
Jiri Olsa2d4f2792019-02-21 10:41:30 +01002958 .path = input_name,
2959 .mode = PERF_DATA_MODE_READ,
Jiri Olsaf5fc14122013-10-15 16:27:32 +02002960 };
Feng Tange5f37052012-09-07 16:42:26 +08002961 char *temp;
2962 int i = 0;
2963
Jiri Olsa8ceb41d2017-01-23 22:07:59 +01002964 session = perf_session__new(&data, false, NULL);
Feng Tang49e639e2012-10-30 11:56:03 +08002965 if (!session)
2966 return -1;
2967
Josh Poimboeuf46113a52015-12-15 09:39:37 -06002968 snprintf(scripts_path, MAXPATHLEN, "%s/scripts", get_argv_exec_path());
Feng Tange5f37052012-09-07 16:42:26 +08002969
2970 scripts_dir = opendir(scripts_path);
Feng Tang49e639e2012-10-30 11:56:03 +08002971 if (!scripts_dir) {
2972 perf_session__delete(session);
Feng Tange5f37052012-09-07 16:42:26 +08002973 return -1;
Feng Tang49e639e2012-10-30 11:56:03 +08002974 }
Feng Tange5f37052012-09-07 16:42:26 +08002975
Arnaldo Carvalho de Meloa5e8e822016-04-08 11:25:59 -03002976 for_each_lang(scripts_path, scripts_dir, lang_dirent) {
Jiri Olsa77f18152018-03-19 09:29:01 +01002977 scnprintf(lang_path, MAXPATHLEN, "%s/%s", scripts_path,
2978 lang_dirent->d_name);
Jin Yao90ce61b2018-04-09 18:26:47 +08002979#ifndef HAVE_LIBPERL_SUPPORT
Feng Tange5f37052012-09-07 16:42:26 +08002980 if (strstr(lang_path, "perl"))
2981 continue;
2982#endif
Jin Yao90ce61b2018-04-09 18:26:47 +08002983#ifndef HAVE_LIBPYTHON_SUPPORT
Feng Tange5f37052012-09-07 16:42:26 +08002984 if (strstr(lang_path, "python"))
2985 continue;
2986#endif
2987
2988 lang_dir = opendir(lang_path);
2989 if (!lang_dir)
2990 continue;
2991
Arnaldo Carvalho de Meloa5e8e822016-04-08 11:25:59 -03002992 for_each_script(lang_path, lang_dir, script_dirent) {
Feng Tange5f37052012-09-07 16:42:26 +08002993 /* Skip those real time scripts: xxxtop.p[yl] */
Arnaldo Carvalho de Meloa5e8e822016-04-08 11:25:59 -03002994 if (strstr(script_dirent->d_name, "top."))
Feng Tange5f37052012-09-07 16:42:26 +08002995 continue;
2996 sprintf(scripts_path_array[i], "%s/%s", lang_path,
Arnaldo Carvalho de Meloa5e8e822016-04-08 11:25:59 -03002997 script_dirent->d_name);
2998 temp = strchr(script_dirent->d_name, '.');
Feng Tange5f37052012-09-07 16:42:26 +08002999 snprintf(scripts_array[i],
Arnaldo Carvalho de Meloa5e8e822016-04-08 11:25:59 -03003000 (temp - script_dirent->d_name) + 1,
3001 "%s", script_dirent->d_name);
Feng Tang49e639e2012-10-30 11:56:03 +08003002
3003 if (check_ev_match(lang_path,
3004 scripts_array[i], session))
3005 continue;
3006
Feng Tange5f37052012-09-07 16:42:26 +08003007 i++;
3008 }
Feng Tang49e639e2012-10-30 11:56:03 +08003009 closedir(lang_dir);
Feng Tange5f37052012-09-07 16:42:26 +08003010 }
3011
Feng Tang49e639e2012-10-30 11:56:03 +08003012 closedir(scripts_dir);
3013 perf_session__delete(session);
Feng Tange5f37052012-09-07 16:42:26 +08003014 return i;
3015}
3016
Tom Zanussi38752942009-12-15 02:53:39 -06003017static char *get_script_path(const char *script_root, const char *suffix)
3018{
Arnaldo Carvalho de Meloa5e8e822016-04-08 11:25:59 -03003019 struct dirent *script_dirent, *lang_dirent;
Tom Zanussi38752942009-12-15 02:53:39 -06003020 char scripts_path[MAXPATHLEN];
3021 char script_path[MAXPATHLEN];
3022 DIR *scripts_dir, *lang_dir;
3023 char lang_path[MAXPATHLEN];
Robert Richter38efb532011-11-25 11:38:40 +01003024 char *__script_root;
Tom Zanussi38752942009-12-15 02:53:39 -06003025
Josh Poimboeuf46113a52015-12-15 09:39:37 -06003026 snprintf(scripts_path, MAXPATHLEN, "%s/scripts", get_argv_exec_path());
Tom Zanussi38752942009-12-15 02:53:39 -06003027
3028 scripts_dir = opendir(scripts_path);
3029 if (!scripts_dir)
3030 return NULL;
3031
Arnaldo Carvalho de Meloa5e8e822016-04-08 11:25:59 -03003032 for_each_lang(scripts_path, scripts_dir, lang_dirent) {
Jiri Olsa77f18152018-03-19 09:29:01 +01003033 scnprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path,
3034 lang_dirent->d_name);
Tom Zanussi38752942009-12-15 02:53:39 -06003035 lang_dir = opendir(lang_path);
3036 if (!lang_dir)
3037 continue;
3038
Arnaldo Carvalho de Meloa5e8e822016-04-08 11:25:59 -03003039 for_each_script(lang_path, lang_dir, script_dirent) {
3040 __script_root = get_script_root(script_dirent, suffix);
Robert Richter38efb532011-11-25 11:38:40 +01003041 if (__script_root && !strcmp(script_root, __script_root)) {
3042 free(__script_root);
Namhyung Kim946ef2a2012-01-08 02:25:25 +09003043 closedir(lang_dir);
3044 closedir(scripts_dir);
Jiri Olsa77f18152018-03-19 09:29:01 +01003045 scnprintf(script_path, MAXPATHLEN, "%s/%s",
3046 lang_path, script_dirent->d_name);
Robert Richter38efb532011-11-25 11:38:40 +01003047 return strdup(script_path);
Tom Zanussi38752942009-12-15 02:53:39 -06003048 }
3049 free(__script_root);
3050 }
Namhyung Kim946ef2a2012-01-08 02:25:25 +09003051 closedir(lang_dir);
Tom Zanussi38752942009-12-15 02:53:39 -06003052 }
Namhyung Kim946ef2a2012-01-08 02:25:25 +09003053 closedir(scripts_dir);
Tom Zanussi38752942009-12-15 02:53:39 -06003054
Robert Richter38efb532011-11-25 11:38:40 +01003055 return NULL;
Tom Zanussi38752942009-12-15 02:53:39 -06003056}
3057
Tom Zanussib5b87312010-11-10 08:16:51 -06003058static bool is_top_script(const char *script_path)
3059{
Stephane Eranian965bb6b2010-12-03 17:52:01 +02003060 return ends_with(script_path, "top") == NULL ? false : true;
Tom Zanussib5b87312010-11-10 08:16:51 -06003061}
3062
3063static int has_required_arg(char *script_path)
3064{
3065 struct script_desc *desc;
3066 int n_args = 0;
3067 char *p;
3068
3069 desc = script_desc__new(NULL);
3070
3071 if (read_script_info(desc, script_path))
3072 goto out;
3073
3074 if (!desc->args)
3075 goto out;
3076
3077 for (p = desc->args; *p; p++)
3078 if (*p == '<')
3079 n_args++;
3080out:
3081 script_desc__delete(desc);
3082
3083 return n_args;
3084}
3085
David Ahernd54b1a92012-08-26 12:24:46 -06003086static int have_cmd(int argc, const char **argv)
Tom Zanussi34c86ea2010-11-10 08:15:43 -06003087{
3088 char **__argv = malloc(sizeof(const char *) * argc);
3089
David Ahernd54b1a92012-08-26 12:24:46 -06003090 if (!__argv) {
3091 pr_err("malloc failed\n");
3092 return -1;
3093 }
3094
Tom Zanussi34c86ea2010-11-10 08:15:43 -06003095 memcpy(__argv, argv, sizeof(const char *) * argc);
3096 argc = parse_options(argc, (const char **)__argv, record_options,
3097 NULL, PARSE_OPT_STOP_AT_NON_OPTION);
3098 free(__argv);
3099
David Ahernd54b1a92012-08-26 12:24:46 -06003100 system_wide = (argc == 0);
3101
3102 return 0;
Tom Zanussi34c86ea2010-11-10 08:15:43 -06003103}
3104
Jiri Olsa7322d6c2015-08-13 09:17:24 +02003105static void script__setup_sample_type(struct perf_script *script)
3106{
3107 struct perf_session *session = script->session;
3108 u64 sample_type = perf_evlist__combined_sample_type(session->evlist);
3109
3110 if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain) {
3111 if ((sample_type & PERF_SAMPLE_REGS_USER) &&
Arnaldo Carvalho de Meloeabad8c2018-01-15 16:48:46 -03003112 (sample_type & PERF_SAMPLE_STACK_USER)) {
Jiri Olsa7322d6c2015-08-13 09:17:24 +02003113 callchain_param.record_mode = CALLCHAIN_DWARF;
Arnaldo Carvalho de Meloeabad8c2018-01-15 16:48:46 -03003114 dwarf_callchain_users = true;
3115 } else if (sample_type & PERF_SAMPLE_BRANCH_STACK)
Jiri Olsa7322d6c2015-08-13 09:17:24 +02003116 callchain_param.record_mode = CALLCHAIN_LBR;
3117 else
3118 callchain_param.record_mode = CALLCHAIN_FP;
3119 }
3120}
3121
Jiri Olsa89f16882018-09-13 14:54:03 +02003122static int process_stat_round_event(struct perf_session *session,
3123 union perf_event *event)
Jiri Olsae099eba2016-01-05 22:09:09 +01003124{
3125 struct stat_round_event *round = &event->stat_round;
3126 struct perf_evsel *counter;
3127
Arnaldo Carvalho de Meloe5cadb92016-06-23 11:26:15 -03003128 evlist__for_each_entry(session->evlist, counter) {
Jiri Olsae099eba2016-01-05 22:09:09 +01003129 perf_stat_process_counter(&stat_config, counter);
3130 process_stat(counter, round->time);
3131 }
3132
3133 process_stat_interval(round->time);
3134 return 0;
3135}
3136
Jiri Olsa89f16882018-09-13 14:54:03 +02003137static int process_stat_config_event(struct perf_session *session __maybe_unused,
3138 union perf_event *event)
Jiri Olsa91a2c3d2016-01-05 22:09:07 +01003139{
3140 perf_event__read_stat_config(&stat_config, &event->stat_config);
3141 return 0;
3142}
3143
Jiri Olsacfc88742016-01-05 22:09:06 +01003144static int set_maps(struct perf_script *script)
3145{
3146 struct perf_evlist *evlist = script->session->evlist;
3147
3148 if (!script->cpus || !script->threads)
3149 return 0;
3150
3151 if (WARN_ONCE(script->allocated, "stats double allocation\n"))
3152 return -EINVAL;
3153
3154 perf_evlist__set_maps(evlist, script->cpus, script->threads);
3155
3156 if (perf_evlist__alloc_stats(evlist, true))
3157 return -ENOMEM;
3158
3159 script->allocated = true;
3160 return 0;
3161}
3162
3163static
Jiri Olsa89f16882018-09-13 14:54:03 +02003164int process_thread_map_event(struct perf_session *session,
3165 union perf_event *event)
Jiri Olsacfc88742016-01-05 22:09:06 +01003166{
Jiri Olsa89f16882018-09-13 14:54:03 +02003167 struct perf_tool *tool = session->tool;
Jiri Olsacfc88742016-01-05 22:09:06 +01003168 struct perf_script *script = container_of(tool, struct perf_script, tool);
3169
3170 if (script->threads) {
3171 pr_warning("Extra thread map event, ignoring.\n");
3172 return 0;
3173 }
3174
3175 script->threads = thread_map__new_event(&event->thread_map);
3176 if (!script->threads)
3177 return -ENOMEM;
3178
3179 return set_maps(script);
3180}
3181
3182static
Jiri Olsa89f16882018-09-13 14:54:03 +02003183int process_cpu_map_event(struct perf_session *session,
3184 union perf_event *event)
Jiri Olsacfc88742016-01-05 22:09:06 +01003185{
Jiri Olsa89f16882018-09-13 14:54:03 +02003186 struct perf_tool *tool = session->tool;
Jiri Olsacfc88742016-01-05 22:09:06 +01003187 struct perf_script *script = container_of(tool, struct perf_script, tool);
3188
3189 if (script->cpus) {
3190 pr_warning("Extra cpu map event, ignoring.\n");
3191 return 0;
3192 }
3193
3194 script->cpus = cpu_map__new_data(&event->cpu_map.data);
3195 if (!script->cpus)
3196 return -ENOMEM;
3197
3198 return set_maps(script);
3199}
3200
Jiri Olsa89f16882018-09-13 14:54:03 +02003201static int process_feature_event(struct perf_session *session,
3202 union perf_event *event)
Ravi Bangoria92ead7e2018-06-25 18:12:20 +05303203{
3204 if (event->feat.feat_id < HEADER_LAST_FEATURE)
Jiri Olsa89f16882018-09-13 14:54:03 +02003205 return perf_event__process_feature(session, event);
Ravi Bangoria92ead7e2018-06-25 18:12:20 +05303206 return 0;
3207}
3208
Arnaldo Carvalho de Melofa48c892017-11-09 16:04:26 -03003209#ifdef HAVE_AUXTRACE_SUPPORT
Jiri Olsa89f16882018-09-13 14:54:03 +02003210static int perf_script__process_auxtrace_info(struct perf_session *session,
3211 union perf_event *event)
Arnaldo Carvalho de Melofa48c892017-11-09 16:04:26 -03003212{
Jiri Olsa89f16882018-09-13 14:54:03 +02003213 struct perf_tool *tool = session->tool;
3214
3215 int ret = perf_event__process_auxtrace_info(session, event);
Arnaldo Carvalho de Melofa48c892017-11-09 16:04:26 -03003216
3217 if (ret == 0) {
3218 struct perf_script *script = container_of(tool, struct perf_script, tool);
3219
3220 ret = perf_script__setup_per_event_dump(script);
3221 }
3222
3223 return ret;
3224}
3225#else
3226#define perf_script__process_auxtrace_info 0
3227#endif
3228
Andi Kleenb585ebd2018-09-20 11:05:36 -07003229static int parse_insn_trace(const struct option *opt __maybe_unused,
3230 const char *str __maybe_unused,
3231 int unset __maybe_unused)
3232{
3233 parse_output_fields(NULL, "+insn,-event,-period", 0);
3234 itrace_parse_synth_opts(opt, "i0ns", 0);
3235 nanosecs = true;
3236 return 0;
3237}
3238
3239static int parse_xed(const struct option *opt __maybe_unused,
3240 const char *str __maybe_unused,
3241 int unset __maybe_unused)
3242{
3243 force_pager("xed -F insn: -A -64 | less");
3244 return 0;
3245}
3246
Andi Kleend1b15522018-09-20 11:05:38 -07003247static int parse_call_trace(const struct option *opt __maybe_unused,
3248 const char *str __maybe_unused,
3249 int unset __maybe_unused)
3250{
3251 parse_output_fields(NULL, "-ip,-addr,-event,-period,+callindent", 0);
3252 itrace_parse_synth_opts(opt, "cewp", 0);
3253 nanosecs = true;
3254 return 0;
3255}
3256
3257static int parse_callret_trace(const struct option *opt __maybe_unused,
3258 const char *str __maybe_unused,
3259 int unset __maybe_unused)
3260{
3261 parse_output_fields(NULL, "-ip,-addr,-event,-period,+callindent,+flags", 0);
3262 itrace_parse_synth_opts(opt, "crewp", 0);
3263 nanosecs = true;
3264 return 0;
3265}
3266
Arnaldo Carvalho de Melob0ad8ea2017-03-27 11:47:20 -03003267int cmd_script(int argc, const char **argv)
Frederic Weisbecker5f9c39d2009-08-17 16:18:08 +02003268{
Arnaldo Carvalho de Melo69b64702012-10-01 15:20:58 -03003269 bool show_full_info = false;
Jiri Olsae90debd2013-12-09 11:02:50 +01003270 bool header = false;
3271 bool header_only = false;
Namhyung Kim6cc870f2014-08-12 15:40:33 +09003272 bool script_started = false;
Tom Zanussib5b87312010-11-10 08:16:51 -06003273 char *rec_script_path = NULL;
3274 char *rep_script_path = NULL;
Arnaldo Carvalho de Melod8f66242009-12-13 19:50:24 -02003275 struct perf_session *session;
Andi Kleen4eb06812018-09-20 11:05:37 -07003276 struct itrace_synth_opts itrace_synth_opts = {
3277 .set = false,
3278 .default_no_sample = true,
3279 };
Tom Zanussib5b87312010-11-10 08:16:51 -06003280 char *script_path = NULL;
Tom Zanussi38752942009-12-15 02:53:39 -06003281 const char **__argv;
Namhyung Kim6cc870f2014-08-12 15:40:33 +09003282 int i, j, err = 0;
Adrian Hunter6f3e5ed2013-10-22 10:34:07 +03003283 struct perf_script script = {
3284 .tool = {
3285 .sample = process_sample_event,
3286 .mmap = perf_event__process_mmap,
3287 .mmap2 = perf_event__process_mmap2,
3288 .comm = perf_event__process_comm,
Hari Bathinif3b36142017-03-08 02:11:43 +05303289 .namespaces = perf_event__process_namespaces,
Adrian Hunter6f3e5ed2013-10-22 10:34:07 +03003290 .exit = perf_event__process_exit,
3291 .fork = perf_event__process_fork,
Adrian Hunter7ea95722013-11-01 15:51:30 +02003292 .attr = process_attr,
Jiri Olsa91daee32016-04-07 09:11:13 +02003293 .event_update = perf_event__process_event_update,
Adrian Hunter6f3e5ed2013-10-22 10:34:07 +03003294 .tracing_data = perf_event__process_tracing_data,
Ravi Bangoria92ead7e2018-06-25 18:12:20 +05303295 .feature = process_feature_event,
Adrian Hunter6f3e5ed2013-10-22 10:34:07 +03003296 .build_id = perf_event__process_build_id,
Adrian Hunter7a680eb2015-04-09 18:53:56 +03003297 .id_index = perf_event__process_id_index,
Arnaldo Carvalho de Melofa48c892017-11-09 16:04:26 -03003298 .auxtrace_info = perf_script__process_auxtrace_info,
Adrian Hunter7a680eb2015-04-09 18:53:56 +03003299 .auxtrace = perf_event__process_auxtrace,
3300 .auxtrace_error = perf_event__process_auxtrace_error,
Jiri Olsae099eba2016-01-05 22:09:09 +01003301 .stat = perf_event__process_stat_event,
3302 .stat_round = process_stat_round_event,
Jiri Olsa91a2c3d2016-01-05 22:09:07 +01003303 .stat_config = process_stat_config_event,
Jiri Olsacfc88742016-01-05 22:09:06 +01003304 .thread_map = process_thread_map_event,
3305 .cpu_map = process_cpu_map_event,
Jiri Olsa0a8cb852014-07-06 14:18:21 +02003306 .ordered_events = true,
Adrian Hunter6f3e5ed2013-10-22 10:34:07 +03003307 .ordering_requires_timestamps = true,
3308 },
3309 };
Jiri Olsa8ceb41d2017-01-23 22:07:59 +01003310 struct perf_data data = {
Yunlong Song06af0f22015-04-02 21:47:16 +08003311 .mode = PERF_DATA_MODE_READ,
3312 };
Arnaldo Carvalho de Melo69b64702012-10-01 15:20:58 -03003313 const struct option options[] = {
3314 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
3315 "dump raw trace in ASCII"),
3316 OPT_INCR('v', "verbose", &verbose,
3317 "be more verbose (show symbol address, etc)"),
3318 OPT_BOOLEAN('L', "Latency", &latency_format,
3319 "show latency attributes (irqs/preemption disabled, etc)"),
3320 OPT_CALLBACK_NOOPT('l', "list", NULL, NULL, "list available scripts",
3321 list_available_scripts),
3322 OPT_CALLBACK('s', "script", NULL, "name",
3323 "script file name (lang:script name, script name, or *)",
3324 parse_scriptname),
3325 OPT_STRING('g', "gen-script", &generate_script_lang, "lang",
3326 "generate perf-script.xx script in specified language"),
3327 OPT_STRING('i', "input", &input_name, "file", "input file name"),
3328 OPT_BOOLEAN('d', "debug-mode", &debug_mode,
3329 "do various checks like samples ordering and lost events"),
Jiri Olsae90debd2013-12-09 11:02:50 +01003330 OPT_BOOLEAN(0, "header", &header, "Show data header."),
3331 OPT_BOOLEAN(0, "header-only", &header_only, "Show only data header."),
Arnaldo Carvalho de Melo69b64702012-10-01 15:20:58 -03003332 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
3333 "file", "vmlinux pathname"),
3334 OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name,
3335 "file", "kallsyms pathname"),
3336 OPT_BOOLEAN('G', "hide-call-graph", &no_callchain,
3337 "When printing symbols do not display call chain"),
He Kuanga7066702016-05-19 11:47:37 +00003338 OPT_CALLBACK(0, "symfs", NULL, "directory",
3339 "Look for files with symbols relative to this directory",
3340 symbol__config_symfs),
Yunlong Song06af0f22015-04-02 21:47:16 +08003341 OPT_CALLBACK('F', "fields", NULL, "str",
Arnaldo Carvalho de Melo69b64702012-10-01 15:20:58 -03003342 "comma separated output fields prepend with 'type:'. "
Andi Kleen36ce5652017-06-02 08:48:10 -07003343 "+field to add and -field to remove."
Adrian Hunter14057202017-06-21 13:17:19 +03003344 "Valid types: hw,sw,trace,raw,synth. "
Arnaldo Carvalho de Melo69b64702012-10-01 15:20:58 -03003345 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,"
Ravi Bangoria10e9cec2018-06-25 18:12:18 +05303346 "addr,symoff,srcline,period,iregs,uregs,brstack,"
3347 "brstacksym,flags,bpf-output,brstackinsn,brstackoff,"
3348 "callindent,insn,insnlen,synth,phys_addr,metric,misc",
Andi Kleen48d02a12017-02-23 15:46:34 -08003349 parse_output_fields),
Arnaldo Carvalho de Melo69b64702012-10-01 15:20:58 -03003350 OPT_BOOLEAN('a', "all-cpus", &system_wide,
3351 "system-wide collection from all CPUs"),
3352 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
3353 "only consider these symbols"),
Andi Kleenb585ebd2018-09-20 11:05:36 -07003354 OPT_CALLBACK_OPTARG(0, "insn-trace", &itrace_synth_opts, NULL, NULL,
3355 "Decode instructions from itrace", parse_insn_trace),
3356 OPT_CALLBACK_OPTARG(0, "xed", NULL, NULL, NULL,
3357 "Run xed disassembler on output", parse_xed),
Andi Kleend1b15522018-09-20 11:05:38 -07003358 OPT_CALLBACK_OPTARG(0, "call-trace", &itrace_synth_opts, NULL, NULL,
3359 "Decode calls from from itrace", parse_call_trace),
3360 OPT_CALLBACK_OPTARG(0, "call-ret-trace", &itrace_synth_opts, NULL, NULL,
3361 "Decode calls and returns from itrace", parse_callret_trace),
Andi Kleen99f753f2018-09-20 11:05:39 -07003362 OPT_STRING(0, "graph-function", &symbol_conf.graph_function, "symbol[,symbol...]",
3363 "Only print symbols and callees with --call-trace/--call-ret-trace"),
David Ahern64eff7d2016-11-25 13:00:21 -07003364 OPT_STRING(0, "stop-bt", &symbol_conf.bt_stop_list_str, "symbol[,symbol...]",
3365 "Stop display of callgraph at these symbols"),
Arnaldo Carvalho de Melo69b64702012-10-01 15:20:58 -03003366 OPT_STRING('C', "cpu", &cpu_list, "cpu", "list of cpus to profile"),
3367 OPT_STRING('c', "comms", &symbol_conf.comm_list_str, "comm[,comm...]",
3368 "only display events for these comms"),
David Aherne03eaa42015-03-24 09:52:41 -06003369 OPT_STRING(0, "pid", &symbol_conf.pid_list_str, "pid[,pid...]",
3370 "only consider symbols in these pids"),
3371 OPT_STRING(0, "tid", &symbol_conf.tid_list_str, "tid[,tid...]",
3372 "only consider symbols in these tids"),
Arnaldo Carvalho de Melo6125cc82016-04-14 18:15:18 -03003373 OPT_UINTEGER(0, "max-stack", &scripting_max_stack,
3374 "Set the maximum stack depth when parsing the callchain, "
3375 "anything beyond the specified depth will be ignored. "
Arnaldo Carvalho de Melo4cb93442016-04-27 10:16:24 -03003376 "Default: kernel.perf_event_max_stack or " __stringify(PERF_MAX_STACK_DEPTH)),
Arnaldo Carvalho de Melo69b64702012-10-01 15:20:58 -03003377 OPT_BOOLEAN('I', "show-info", &show_full_info,
3378 "display extended information from perf.data file"),
3379 OPT_BOOLEAN('\0', "show-kernel-path", &symbol_conf.show_kernel_path,
3380 "Show the path of [kernel.kallsyms]"),
Namhyung Kimad7ebb92013-11-26 17:51:12 +09003381 OPT_BOOLEAN('\0', "show-task-events", &script.show_task_events,
3382 "Show the fork/comm/exit events"),
Namhyung Kimba1ddf42013-11-26 17:54:26 +09003383 OPT_BOOLEAN('\0', "show-mmap-events", &script.show_mmap_events,
3384 "Show the mmap events"),
Adrian Hunter7c148982015-07-21 12:44:06 +03003385 OPT_BOOLEAN('\0', "show-switch-events", &script.show_switch_events,
3386 "Show context switch events (if recorded)"),
Hari Bathini96a44bb2017-03-08 02:12:06 +05303387 OPT_BOOLEAN('\0', "show-namespace-events", &script.show_namespace_events,
3388 "Show namespace events (if recorded)"),
Jiri Olsa3d7c27b2018-01-07 17:03:53 +01003389 OPT_BOOLEAN('\0', "show-lost-events", &script.show_lost_events,
3390 "Show lost events (if recorded)"),
Jiri Olsa3233b372018-02-06 19:17:59 +01003391 OPT_BOOLEAN('\0', "show-round-events", &script.show_round_events,
3392 "Show round events (if recorded)"),
Arnaldo Carvalho de Meloa14390f2017-10-26 10:30:20 -03003393 OPT_BOOLEAN('\0', "per-event-dump", &script.per_event_dump,
3394 "Dump trace output to files named by the monitored events"),
Yannick Brosseaube3d4662017-01-13 13:25:27 -05003395 OPT_BOOLEAN('f', "force", &symbol_conf.force, "don't complain, do it"),
Andi Kleen48d02a12017-02-23 15:46:34 -08003396 OPT_INTEGER(0, "max-blocks", &max_blocks,
3397 "Maximum number of code blocks to dump with brstackinsn"),
Adrian Hunter83e19862015-09-25 16:15:36 +03003398 OPT_BOOLEAN(0, "ns", &nanosecs,
3399 "Use 9 decimal places when displaying time"),
Adrian Hunter7a680eb2015-04-09 18:53:56 +03003400 OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts",
Andi Kleenc12e0392018-09-13 20:10:31 -07003401 "Instruction Tracing options\n" ITRACE_HELP,
Adrian Hunter7a680eb2015-04-09 18:53:56 +03003402 itrace_parse_synth_opts),
Andi Kleena9710ba2015-08-07 15:24:05 -07003403 OPT_BOOLEAN(0, "full-source-path", &srcline_full_filename,
3404 "Show full source file name path for source lines"),
Mark Drayton77e00702015-08-26 12:18:15 -07003405 OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle,
3406 "Enable symbol demangling"),
3407 OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel,
3408 "Enable kernel symbol demangling"),
David Aherna91f4c42016-11-29 10:15:43 -07003409 OPT_STRING(0, "time", &script.time_str, "str",
3410 "Time span of interest (start,stop)"),
Namhyung Kim325fbff2017-05-24 15:21:26 +09003411 OPT_BOOLEAN(0, "inline", &symbol_conf.inline_name,
3412 "Show inline function"),
Arnaldo Carvalho de Melo69b64702012-10-01 15:20:58 -03003413 OPT_END()
3414 };
Yunlong Song40cae2b2015-03-18 21:35:54 +08003415 const char * const script_subcommands[] = { "record", "report", NULL };
3416 const char *script_usage[] = {
Arnaldo Carvalho de Melo69b64702012-10-01 15:20:58 -03003417 "perf script [<options>]",
3418 "perf script [<options>] record <script> [<record-options>] <command>",
3419 "perf script [<options>] report <script> [script-args]",
3420 "perf script [<options>] <script> [<record-options>] <command>",
3421 "perf script [<options>] <top-script> [script-args]",
3422 NULL
3423 };
Tom Zanussi38752942009-12-15 02:53:39 -06003424
Arnaldo Carvalho de Melo0a7c74e2017-04-04 13:15:04 -03003425 perf_set_singlethreaded();
3426
Tom Zanussib5b87312010-11-10 08:16:51 -06003427 setup_scripting();
3428
Yunlong Song40cae2b2015-03-18 21:35:54 +08003429 argc = parse_options_subcommand(argc, argv, options, script_subcommands, script_usage,
Tom Zanussib5b87312010-11-10 08:16:51 -06003430 PARSE_OPT_STOP_AT_NON_OPTION);
3431
Jiri Olsa2d4f2792019-02-21 10:41:30 +01003432 data.path = input_name;
3433 data.force = symbol_conf.force;
Jiri Olsaf5fc14122013-10-15 16:27:32 +02003434
Tom Zanussib5b87312010-11-10 08:16:51 -06003435 if (argc > 1 && !strncmp(argv[0], "rec", strlen("rec"))) {
3436 rec_script_path = get_script_path(argv[1], RECORD_SUFFIX);
3437 if (!rec_script_path)
Arnaldo Carvalho de Melob0ad8ea2017-03-27 11:47:20 -03003438 return cmd_record(argc, argv);
Tom Zanussi38752942009-12-15 02:53:39 -06003439 }
3440
Tom Zanussib5b87312010-11-10 08:16:51 -06003441 if (argc > 1 && !strncmp(argv[0], "rep", strlen("rep"))) {
3442 rep_script_path = get_script_path(argv[1], REPORT_SUFFIX);
3443 if (!rep_script_path) {
Tom Zanussi38752942009-12-15 02:53:39 -06003444 fprintf(stderr,
Tom Zanussib5b87312010-11-10 08:16:51 -06003445 "Please specify a valid report script"
Ingo Molnar133dc4c2010-11-16 18:45:39 +01003446 "(see 'perf script -l' for listing)\n");
Tom Zanussi38752942009-12-15 02:53:39 -06003447 return -1;
3448 }
Tom Zanussi38752942009-12-15 02:53:39 -06003449 }
3450
Adrian Hunter3c5b6452015-09-25 16:15:51 +03003451 if (itrace_synth_opts.callchain &&
3452 itrace_synth_opts.callchain_sz > scripting_max_stack)
3453 scripting_max_stack = itrace_synth_opts.callchain_sz;
3454
Ben Hutchings44e668c2010-10-10 16:10:03 +01003455 /* make sure PERF_EXEC_PATH is set for scripts */
Josh Poimboeuf46113a52015-12-15 09:39:37 -06003456 set_argv_exec_path(get_argv_exec_path());
Ben Hutchings44e668c2010-10-10 16:10:03 +01003457
Tom Zanussib5b87312010-11-10 08:16:51 -06003458 if (argc && !script_name && !rec_script_path && !rep_script_path) {
Tom Zanussia0cccc22010-04-01 23:59:25 -05003459 int live_pipe[2];
Tom Zanussib5b87312010-11-10 08:16:51 -06003460 int rep_args;
Tom Zanussia0cccc22010-04-01 23:59:25 -05003461 pid_t pid;
3462
Tom Zanussib5b87312010-11-10 08:16:51 -06003463 rec_script_path = get_script_path(argv[0], RECORD_SUFFIX);
3464 rep_script_path = get_script_path(argv[0], REPORT_SUFFIX);
3465
3466 if (!rec_script_path && !rep_script_path) {
Namhyung Kimc7118362015-10-25 00:49:27 +09003467 usage_with_options_msg(script_usage, options,
3468 "Couldn't find script `%s'\n\n See perf"
Ingo Molnar133dc4c2010-11-16 18:45:39 +01003469 " script -l for available scripts.\n", argv[0]);
Tom Zanussia0cccc22010-04-01 23:59:25 -05003470 }
3471
Tom Zanussib5b87312010-11-10 08:16:51 -06003472 if (is_top_script(argv[0])) {
3473 rep_args = argc - 1;
3474 } else {
3475 int rec_args;
3476
3477 rep_args = has_required_arg(rep_script_path);
3478 rec_args = (argc - 1) - rep_args;
3479 if (rec_args < 0) {
Namhyung Kimc7118362015-10-25 00:49:27 +09003480 usage_with_options_msg(script_usage, options,
3481 "`%s' script requires options."
Ingo Molnar133dc4c2010-11-16 18:45:39 +01003482 "\n\n See perf script -l for available "
Tom Zanussib5b87312010-11-10 08:16:51 -06003483 "scripts and options.\n", argv[0]);
Tom Zanussib5b87312010-11-10 08:16:51 -06003484 }
Tom Zanussia0cccc22010-04-01 23:59:25 -05003485 }
3486
3487 if (pipe(live_pipe) < 0) {
3488 perror("failed to create pipe");
David Ahernd54b1a92012-08-26 12:24:46 -06003489 return -1;
Tom Zanussia0cccc22010-04-01 23:59:25 -05003490 }
3491
3492 pid = fork();
3493 if (pid < 0) {
3494 perror("failed to fork");
David Ahernd54b1a92012-08-26 12:24:46 -06003495 return -1;
Tom Zanussia0cccc22010-04-01 23:59:25 -05003496 }
3497
3498 if (!pid) {
Tom Zanussib5b87312010-11-10 08:16:51 -06003499 j = 0;
3500
Tom Zanussia0cccc22010-04-01 23:59:25 -05003501 dup2(live_pipe[1], 1);
3502 close(live_pipe[0]);
3503
Robert Richter317df652011-11-25 15:05:25 +01003504 if (is_top_script(argv[0])) {
3505 system_wide = true;
3506 } else if (!system_wide) {
David Ahernd54b1a92012-08-26 12:24:46 -06003507 if (have_cmd(argc - rep_args, &argv[rep_args]) != 0) {
3508 err = -1;
3509 goto out;
3510 }
Robert Richter317df652011-11-25 15:05:25 +01003511 }
Tom Zanussib5b87312010-11-10 08:16:51 -06003512
3513 __argv = malloc((argc + 6) * sizeof(const char *));
David Ahernd54b1a92012-08-26 12:24:46 -06003514 if (!__argv) {
3515 pr_err("malloc failed\n");
3516 err = -ENOMEM;
3517 goto out;
3518 }
Tom Zanussie8719ad2010-11-10 07:52:32 -06003519
Tom Zanussib5b87312010-11-10 08:16:51 -06003520 __argv[j++] = "/bin/sh";
3521 __argv[j++] = rec_script_path;
3522 if (system_wide)
3523 __argv[j++] = "-a";
3524 __argv[j++] = "-q";
3525 __argv[j++] = "-o";
3526 __argv[j++] = "-";
3527 for (i = rep_args + 1; i < argc; i++)
3528 __argv[j++] = argv[i];
3529 __argv[j++] = NULL;
Tom Zanussia0cccc22010-04-01 23:59:25 -05003530
3531 execvp("/bin/sh", (char **)__argv);
Tom Zanussie8719ad2010-11-10 07:52:32 -06003532 free(__argv);
Tom Zanussia0cccc22010-04-01 23:59:25 -05003533 exit(-1);
3534 }
3535
3536 dup2(live_pipe[0], 0);
3537 close(live_pipe[1]);
3538
Tom Zanussib5b87312010-11-10 08:16:51 -06003539 __argv = malloc((argc + 4) * sizeof(const char *));
David Ahernd54b1a92012-08-26 12:24:46 -06003540 if (!__argv) {
3541 pr_err("malloc failed\n");
3542 err = -ENOMEM;
3543 goto out;
3544 }
3545
Tom Zanussib5b87312010-11-10 08:16:51 -06003546 j = 0;
Tom Zanussi34c86ea2010-11-10 08:15:43 -06003547 __argv[j++] = "/bin/sh";
Tom Zanussib5b87312010-11-10 08:16:51 -06003548 __argv[j++] = rep_script_path;
3549 for (i = 1; i < rep_args + 1; i++)
Tom Zanussi34c86ea2010-11-10 08:15:43 -06003550 __argv[j++] = argv[i];
Tom Zanussib5b87312010-11-10 08:16:51 -06003551 __argv[j++] = "-i";
3552 __argv[j++] = "-";
Tom Zanussi34c86ea2010-11-10 08:15:43 -06003553 __argv[j++] = NULL;
Tom Zanussi38752942009-12-15 02:53:39 -06003554
3555 execvp("/bin/sh", (char **)__argv);
Tom Zanussie8719ad2010-11-10 07:52:32 -06003556 free(__argv);
Tom Zanussi38752942009-12-15 02:53:39 -06003557 exit(-1);
3558 }
Tom Zanussi956ffd02009-11-25 01:15:46 -06003559
Tom Zanussib5b87312010-11-10 08:16:51 -06003560 if (rec_script_path)
3561 script_path = rec_script_path;
3562 if (rep_script_path)
3563 script_path = rep_script_path;
Tom Zanussi956ffd02009-11-25 01:15:46 -06003564
Tom Zanussib5b87312010-11-10 08:16:51 -06003565 if (script_path) {
Tom Zanussib5b87312010-11-10 08:16:51 -06003566 j = 0;
3567
Robert Richter317df652011-11-25 15:05:25 +01003568 if (!rec_script_path)
3569 system_wide = false;
David Ahernd54b1a92012-08-26 12:24:46 -06003570 else if (!system_wide) {
3571 if (have_cmd(argc - 1, &argv[1]) != 0) {
3572 err = -1;
3573 goto out;
3574 }
3575 }
Tom Zanussib5b87312010-11-10 08:16:51 -06003576
3577 __argv = malloc((argc + 2) * sizeof(const char *));
David Ahernd54b1a92012-08-26 12:24:46 -06003578 if (!__argv) {
3579 pr_err("malloc failed\n");
3580 err = -ENOMEM;
3581 goto out;
3582 }
3583
Tom Zanussib5b87312010-11-10 08:16:51 -06003584 __argv[j++] = "/bin/sh";
3585 __argv[j++] = script_path;
3586 if (system_wide)
3587 __argv[j++] = "-a";
3588 for (i = 2; i < argc; i++)
3589 __argv[j++] = argv[i];
3590 __argv[j++] = NULL;
3591
3592 execvp("/bin/sh", (char **)__argv);
3593 free(__argv);
3594 exit(-1);
3595 }
Frederic Weisbecker5f9c39d2009-08-17 16:18:08 +02003596
Milian Wolffc1c9b962018-10-21 21:14:23 +02003597 if (!script_name) {
Tom Zanussicf4fee52010-03-03 01:04:33 -06003598 setup_pager();
Milian Wolffc1c9b962018-10-21 21:14:23 +02003599 use_browser = 0;
3600 }
Frederic Weisbecker5f9c39d2009-08-17 16:18:08 +02003601
Jiri Olsa8ceb41d2017-01-23 22:07:59 +01003602 session = perf_session__new(&data, false, &script.tool);
Arnaldo Carvalho de Melod8f66242009-12-13 19:50:24 -02003603 if (session == NULL)
Taeung Song52e028342014-09-24 10:33:37 +09003604 return -1;
Arnaldo Carvalho de Melod8f66242009-12-13 19:50:24 -02003605
Jiri Olsae90debd2013-12-09 11:02:50 +01003606 if (header || header_only) {
David Carrillo-Cisneros114f7092017-07-17 21:25:47 -07003607 script.tool.show_feat_hdr = SHOW_FEAT_HEADER;
Jiri Olsae90debd2013-12-09 11:02:50 +01003608 perf_session__fprintf_info(session, stdout, show_full_info);
3609 if (header_only)
Namhyung Kim6cc870f2014-08-12 15:40:33 +09003610 goto out_delete;
Jiri Olsae90debd2013-12-09 11:02:50 +01003611 }
David Carrillo-Cisneros114f7092017-07-17 21:25:47 -07003612 if (show_full_info)
3613 script.tool.show_feat_hdr = SHOW_FEAT_HEADER_FULL_INFO;
Jiri Olsae90debd2013-12-09 11:02:50 +01003614
Namhyung Kim0a7e6d12014-08-12 15:40:45 +09003615 if (symbol__init(&session->header.env) < 0)
Namhyung Kim38520dc2014-08-12 15:40:42 +09003616 goto out_delete;
3617
Adrian Hunter6f3e5ed2013-10-22 10:34:07 +03003618 script.session = session;
Jiri Olsa7322d6c2015-08-13 09:17:24 +02003619 script__setup_sample_type(&script);
Adrian Hunter6f3e5ed2013-10-22 10:34:07 +03003620
Andi Kleen99f753f2018-09-20 11:05:39 -07003621 if ((output[PERF_TYPE_HARDWARE].fields & PERF_OUTPUT_CALLINDENT) ||
3622 symbol_conf.graph_function)
Adrian Huntere2167082016-06-23 16:40:58 +03003623 itrace_synth_opts.thread_stack = true;
3624
Adrian Hunter7a680eb2015-04-09 18:53:56 +03003625 session->itrace_synth_opts = &itrace_synth_opts;
3626
Anton Blanchard5d67be92011-07-04 21:57:50 +10003627 if (cpu_list) {
Namhyung Kim6cc870f2014-08-12 15:40:33 +09003628 err = perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap);
3629 if (err < 0)
3630 goto out_delete;
Adrian Hunter644e0842017-05-26 11:17:38 +03003631 itrace_synth_opts.cpu_bitmap = cpu_bitmap;
Anton Blanchard5d67be92011-07-04 21:57:50 +10003632 }
3633
David Ahern1424dc92011-03-09 22:23:28 -07003634 if (!no_callchain)
David Ahernc0230b22011-03-09 22:23:27 -07003635 symbol_conf.use_callchain = true;
3636 else
3637 symbol_conf.use_callchain = false;
3638
Arnaldo Carvalho de Melo9ee67422015-08-03 16:27:40 -03003639 if (session->tevent.pevent &&
Tzvetomir Stoyanov (VMware)ece2a4f2018-08-08 14:02:55 -04003640 tep_set_function_resolver(session->tevent.pevent,
3641 machine__resolve_kernel_addr,
3642 &session->machines.host) < 0) {
Arnaldo Carvalho de Meloccb3a822015-07-22 16:43:37 -03003643 pr_err("%s: failed to set libtraceevent function resolver\n", __func__);
Christophe JAILLETdb49bc12017-09-16 08:25:37 +02003644 err = -1;
3645 goto out_delete;
Arnaldo Carvalho de Meloccb3a822015-07-22 16:43:37 -03003646 }
3647
Tom Zanussi956ffd02009-11-25 01:15:46 -06003648 if (generate_script_lang) {
3649 struct stat perf_stat;
David Ahern745f43e2011-03-09 22:23:26 -07003650 int input;
Tom Zanussi956ffd02009-11-25 01:15:46 -06003651
David Ahern2c9e45f72011-03-17 10:03:21 -06003652 if (output_set_by_user()) {
David Ahern745f43e2011-03-09 22:23:26 -07003653 fprintf(stderr,
3654 "custom fields not supported for generated scripts");
Namhyung Kim6cc870f2014-08-12 15:40:33 +09003655 err = -EINVAL;
3656 goto out_delete;
David Ahern745f43e2011-03-09 22:23:26 -07003657 }
3658
Jiri Olsa2d4f2792019-02-21 10:41:30 +01003659 input = open(data.path, O_RDONLY); /* input_name */
Tom Zanussi956ffd02009-11-25 01:15:46 -06003660 if (input < 0) {
Namhyung Kim6cc870f2014-08-12 15:40:33 +09003661 err = -errno;
Tom Zanussi956ffd02009-11-25 01:15:46 -06003662 perror("failed to open file");
Namhyung Kim6cc870f2014-08-12 15:40:33 +09003663 goto out_delete;
Tom Zanussi956ffd02009-11-25 01:15:46 -06003664 }
3665
3666 err = fstat(input, &perf_stat);
3667 if (err < 0) {
3668 perror("failed to stat file");
Namhyung Kim6cc870f2014-08-12 15:40:33 +09003669 goto out_delete;
Tom Zanussi956ffd02009-11-25 01:15:46 -06003670 }
3671
3672 if (!perf_stat.st_size) {
3673 fprintf(stderr, "zero-sized file, nothing to do!\n");
Namhyung Kim6cc870f2014-08-12 15:40:33 +09003674 goto out_delete;
Tom Zanussi956ffd02009-11-25 01:15:46 -06003675 }
3676
3677 scripting_ops = script_spec__lookup(generate_script_lang);
3678 if (!scripting_ops) {
3679 fprintf(stderr, "invalid language specifier");
Namhyung Kim6cc870f2014-08-12 15:40:33 +09003680 err = -ENOENT;
3681 goto out_delete;
Tom Zanussi956ffd02009-11-25 01:15:46 -06003682 }
3683
Jiri Olsa29f5ffd2013-12-03 14:09:23 +01003684 err = scripting_ops->generate_script(session->tevent.pevent,
Arnaldo Carvalho de Meloda378962012-06-27 13:08:42 -03003685 "perf-script");
Namhyung Kim6cc870f2014-08-12 15:40:33 +09003686 goto out_delete;
Tom Zanussi956ffd02009-11-25 01:15:46 -06003687 }
3688
3689 if (script_name) {
Tom Zanussi586bc5c2009-12-15 02:53:35 -06003690 err = scripting_ops->start_script(script_name, argc, argv);
Tom Zanussi956ffd02009-11-25 01:15:46 -06003691 if (err)
Namhyung Kim6cc870f2014-08-12 15:40:33 +09003692 goto out_delete;
Ingo Molnar133dc4c2010-11-16 18:45:39 +01003693 pr_debug("perf script started with script %s\n\n", script_name);
Namhyung Kim6cc870f2014-08-12 15:40:33 +09003694 script_started = true;
Tom Zanussi956ffd02009-11-25 01:15:46 -06003695 }
3696
David Ahern9cbdb702011-04-06 21:54:20 -06003697
3698 err = perf_session__check_output_opt(session);
3699 if (err < 0)
Namhyung Kim6cc870f2014-08-12 15:40:33 +09003700 goto out_delete;
David Ahern9cbdb702011-04-06 21:54:20 -06003701
Jin Yaocc2ef582018-01-10 23:00:33 +08003702 script.ptime_range = perf_time__range_alloc(script.time_str,
3703 &script.range_size);
3704 if (!script.ptime_range) {
3705 err = -ENOMEM;
3706 goto out_delete;
3707 }
3708
David Aherna91f4c42016-11-29 10:15:43 -07003709 /* needs to be parsed after looking up reference time */
Jin Yao2ab046c2017-12-08 21:13:46 +08003710 if (perf_time__parse_str(script.ptime_range, script.time_str) != 0) {
3711 if (session->evlist->first_sample_time == 0 &&
3712 session->evlist->last_sample_time == 0) {
Jin Yao1e2778e2018-01-10 23:00:27 +08003713 pr_err("HINT: no first/last sample time found in perf data.\n"
3714 "Please use latest perf binary to execute 'perf record'\n"
3715 "(if '--buildid-all' is enabled, please set '--timestamp-boundary').\n");
Jin Yao2ab046c2017-12-08 21:13:46 +08003716 err = -EINVAL;
3717 goto out_delete;
3718 }
3719
3720 script.range_num = perf_time__percent_parse_str(
Jin Yaocc2ef582018-01-10 23:00:33 +08003721 script.ptime_range, script.range_size,
Jin Yao2ab046c2017-12-08 21:13:46 +08003722 script.time_str,
3723 session->evlist->first_sample_time,
3724 session->evlist->last_sample_time);
3725
3726 if (script.range_num < 0) {
3727 pr_err("Invalid time string\n");
3728 err = -EINVAL;
3729 goto out_delete;
3730 }
3731 } else {
3732 script.range_num = 1;
David Aherna91f4c42016-11-29 10:15:43 -07003733 }
3734
Adrian Hunter6f3e5ed2013-10-22 10:34:07 +03003735 err = __cmd_script(&script);
Tom Zanussi956ffd02009-11-25 01:15:46 -06003736
Adrian Hunterd445dd22014-08-15 22:08:37 +03003737 flush_scripting();
3738
Namhyung Kim6cc870f2014-08-12 15:40:33 +09003739out_delete:
Jin Yaocc2ef582018-01-10 23:00:33 +08003740 zfree(&script.ptime_range);
3741
Jiri Olsacfc88742016-01-05 22:09:06 +01003742 perf_evlist__free_stats(session->evlist);
Arnaldo Carvalho de Melod8f66242009-12-13 19:50:24 -02003743 perf_session__delete(session);
Namhyung Kim6cc870f2014-08-12 15:40:33 +09003744
3745 if (script_started)
3746 cleanup_scripting();
Tom Zanussi956ffd02009-11-25 01:15:46 -06003747out:
3748 return err;
Frederic Weisbecker5f9c39d2009-08-17 16:18:08 +02003749}