4519 lines · c
1// SPDX-License-Identifier: GPL-2.02#include "builtin.h"3 4#include "util/counts.h"5#include "util/debug.h"6#include "util/dso.h"7#include <subcmd/exec-cmd.h>8#include "util/header.h"9#include <subcmd/parse-options.h>10#include "util/perf_regs.h"11#include "util/session.h"12#include "util/tool.h"13#include "util/map.h"14#include "util/srcline.h"15#include "util/symbol.h"16#include "util/thread.h"17#include "util/trace-event.h"18#include "util/env.h"19#include "util/evlist.h"20#include "util/evsel.h"21#include "util/evsel_fprintf.h"22#include "util/evswitch.h"23#include "util/sort.h"24#include "util/data.h"25#include "util/auxtrace.h"26#include "util/cpumap.h"27#include "util/thread_map.h"28#include "util/stat.h"29#include "util/color.h"30#include "util/string2.h"31#include "util/thread-stack.h"32#include "util/time-utils.h"33#include "util/path.h"34#include "util/event.h"35#include "util/mem-info.h"36#include "ui/ui.h"37#include "print_binary.h"38#include "print_insn.h"39#include "archinsn.h"40#include <linux/bitmap.h>41#include <linux/kernel.h>42#include <linux/stringify.h>43#include <linux/time64.h>44#include <linux/zalloc.h>45#include <sys/utsname.h>46#include "asm/bug.h"47#include "util/mem-events.h"48#include "util/dump-insn.h"49#include <dirent.h>50#include <errno.h>51#include <inttypes.h>52#include <signal.h>53#include <sys/param.h>54#include <sys/types.h>55#include <sys/stat.h>56#include <fcntl.h>57#include <unistd.h>58#include <subcmd/pager.h>59#include <perf/evlist.h>60#include <linux/err.h>61#include "util/dlfilter.h"62#include "util/record.h"63#include "util/util.h"64#include "util/cgroup.h"65#include "util/annotate.h"66#include "perf.h"67 68#include <linux/ctype.h>69#ifdef HAVE_LIBTRACEEVENT70#include <traceevent/event-parse.h>71#endif72 73static char const *script_name;74static char const *generate_script_lang;75static bool reltime;76static bool deltatime;77static u64 initial_time;78static u64 previous_time;79static bool debug_mode;80static u64 last_timestamp;81static u64 nr_unordered;82static bool no_callchain;83static bool latency_format;84static bool system_wide;85static bool print_flags;86static const char *cpu_list;87static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);88static struct perf_stat_config stat_config;89static int max_blocks;90static bool native_arch;91static struct dlfilter *dlfilter;92static int dlargc;93static char **dlargv;94 95unsigned int scripting_max_stack = PERF_MAX_STACK_DEPTH;96 97enum perf_output_field {98 PERF_OUTPUT_COMM = 1ULL << 0,99 PERF_OUTPUT_TID = 1ULL << 1,100 PERF_OUTPUT_PID = 1ULL << 2,101 PERF_OUTPUT_TIME = 1ULL << 3,102 PERF_OUTPUT_CPU = 1ULL << 4,103 PERF_OUTPUT_EVNAME = 1ULL << 5,104 PERF_OUTPUT_TRACE = 1ULL << 6,105 PERF_OUTPUT_IP = 1ULL << 7,106 PERF_OUTPUT_SYM = 1ULL << 8,107 PERF_OUTPUT_DSO = 1ULL << 9,108 PERF_OUTPUT_ADDR = 1ULL << 10,109 PERF_OUTPUT_SYMOFFSET = 1ULL << 11,110 PERF_OUTPUT_SRCLINE = 1ULL << 12,111 PERF_OUTPUT_PERIOD = 1ULL << 13,112 PERF_OUTPUT_IREGS = 1ULL << 14,113 PERF_OUTPUT_BRSTACK = 1ULL << 15,114 PERF_OUTPUT_BRSTACKSYM = 1ULL << 16,115 PERF_OUTPUT_DATA_SRC = 1ULL << 17,116 PERF_OUTPUT_WEIGHT = 1ULL << 18,117 PERF_OUTPUT_BPF_OUTPUT = 1ULL << 19,118 PERF_OUTPUT_CALLINDENT = 1ULL << 20,119 PERF_OUTPUT_INSN = 1ULL << 21,120 PERF_OUTPUT_INSNLEN = 1ULL << 22,121 PERF_OUTPUT_BRSTACKINSN = 1ULL << 23,122 PERF_OUTPUT_BRSTACKOFF = 1ULL << 24,123 PERF_OUTPUT_SYNTH = 1ULL << 25,124 PERF_OUTPUT_PHYS_ADDR = 1ULL << 26,125 PERF_OUTPUT_UREGS = 1ULL << 27,126 PERF_OUTPUT_METRIC = 1ULL << 28,127 PERF_OUTPUT_MISC = 1ULL << 29,128 PERF_OUTPUT_SRCCODE = 1ULL << 30,129 PERF_OUTPUT_IPC = 1ULL << 31,130 PERF_OUTPUT_TOD = 1ULL << 32,131 PERF_OUTPUT_DATA_PAGE_SIZE = 1ULL << 33,132 PERF_OUTPUT_CODE_PAGE_SIZE = 1ULL << 34,133 PERF_OUTPUT_INS_LAT = 1ULL << 35,134 PERF_OUTPUT_BRSTACKINSNLEN = 1ULL << 36,135 PERF_OUTPUT_MACHINE_PID = 1ULL << 37,136 PERF_OUTPUT_VCPU = 1ULL << 38,137 PERF_OUTPUT_CGROUP = 1ULL << 39,138 PERF_OUTPUT_RETIRE_LAT = 1ULL << 40,139 PERF_OUTPUT_DSOFF = 1ULL << 41,140 PERF_OUTPUT_DISASM = 1ULL << 42,141 PERF_OUTPUT_BRSTACKDISASM = 1ULL << 43,142 PERF_OUTPUT_BRCNTR = 1ULL << 44,143};144 145struct perf_script {146 struct perf_tool tool;147 struct perf_session *session;148 bool show_task_events;149 bool show_mmap_events;150 bool show_switch_events;151 bool show_namespace_events;152 bool show_lost_events;153 bool show_round_events;154 bool show_bpf_events;155 bool show_cgroup_events;156 bool show_text_poke_events;157 bool allocated;158 bool per_event_dump;159 bool stitch_lbr;160 struct evswitch evswitch;161 struct perf_cpu_map *cpus;162 struct perf_thread_map *threads;163 int name_width;164 const char *time_str;165 struct perf_time_interval *ptime_range;166 int range_size;167 int range_num;168};169 170struct output_option {171 const char *str;172 enum perf_output_field field;173} all_output_options[] = {174 {.str = "comm", .field = PERF_OUTPUT_COMM},175 {.str = "tid", .field = PERF_OUTPUT_TID},176 {.str = "pid", .field = PERF_OUTPUT_PID},177 {.str = "time", .field = PERF_OUTPUT_TIME},178 {.str = "cpu", .field = PERF_OUTPUT_CPU},179 {.str = "event", .field = PERF_OUTPUT_EVNAME},180 {.str = "trace", .field = PERF_OUTPUT_TRACE},181 {.str = "ip", .field = PERF_OUTPUT_IP},182 {.str = "sym", .field = PERF_OUTPUT_SYM},183 {.str = "dso", .field = PERF_OUTPUT_DSO},184 {.str = "dsoff", .field = PERF_OUTPUT_DSOFF},185 {.str = "addr", .field = PERF_OUTPUT_ADDR},186 {.str = "symoff", .field = PERF_OUTPUT_SYMOFFSET},187 {.str = "srcline", .field = PERF_OUTPUT_SRCLINE},188 {.str = "period", .field = PERF_OUTPUT_PERIOD},189 {.str = "iregs", .field = PERF_OUTPUT_IREGS},190 {.str = "uregs", .field = PERF_OUTPUT_UREGS},191 {.str = "brstack", .field = PERF_OUTPUT_BRSTACK},192 {.str = "brstacksym", .field = PERF_OUTPUT_BRSTACKSYM},193 {.str = "data_src", .field = PERF_OUTPUT_DATA_SRC},194 {.str = "weight", .field = PERF_OUTPUT_WEIGHT},195 {.str = "bpf-output", .field = PERF_OUTPUT_BPF_OUTPUT},196 {.str = "callindent", .field = PERF_OUTPUT_CALLINDENT},197 {.str = "insn", .field = PERF_OUTPUT_INSN},198 {.str = "disasm", .field = PERF_OUTPUT_DISASM},199 {.str = "insnlen", .field = PERF_OUTPUT_INSNLEN},200 {.str = "brstackinsn", .field = PERF_OUTPUT_BRSTACKINSN},201 {.str = "brstackoff", .field = PERF_OUTPUT_BRSTACKOFF},202 {.str = "synth", .field = PERF_OUTPUT_SYNTH},203 {.str = "phys_addr", .field = PERF_OUTPUT_PHYS_ADDR},204 {.str = "metric", .field = PERF_OUTPUT_METRIC},205 {.str = "misc", .field = PERF_OUTPUT_MISC},206 {.str = "srccode", .field = PERF_OUTPUT_SRCCODE},207 {.str = "ipc", .field = PERF_OUTPUT_IPC},208 {.str = "tod", .field = PERF_OUTPUT_TOD},209 {.str = "data_page_size", .field = PERF_OUTPUT_DATA_PAGE_SIZE},210 {.str = "code_page_size", .field = PERF_OUTPUT_CODE_PAGE_SIZE},211 {.str = "ins_lat", .field = PERF_OUTPUT_INS_LAT},212 {.str = "brstackinsnlen", .field = PERF_OUTPUT_BRSTACKINSNLEN},213 {.str = "machine_pid", .field = PERF_OUTPUT_MACHINE_PID},214 {.str = "vcpu", .field = PERF_OUTPUT_VCPU},215 {.str = "cgroup", .field = PERF_OUTPUT_CGROUP},216 {.str = "retire_lat", .field = PERF_OUTPUT_RETIRE_LAT},217 {.str = "brstackdisasm", .field = PERF_OUTPUT_BRSTACKDISASM},218 {.str = "brcntr", .field = PERF_OUTPUT_BRCNTR},219};220 221enum {222 OUTPUT_TYPE_SYNTH = PERF_TYPE_MAX,223 OUTPUT_TYPE_OTHER,224 OUTPUT_TYPE_MAX225};226 227/* default set to maintain compatibility with current format */228static struct {229 bool user_set;230 bool wildcard_set;231 unsigned int print_ip_opts;232 u64 fields;233 u64 invalid_fields;234 u64 user_set_fields;235 u64 user_unset_fields;236} output[OUTPUT_TYPE_MAX] = {237 238 [PERF_TYPE_HARDWARE] = {239 .user_set = false,240 241 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |242 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |243 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |244 PERF_OUTPUT_SYM | PERF_OUTPUT_SYMOFFSET |245 PERF_OUTPUT_DSO | PERF_OUTPUT_PERIOD,246 247 .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT,248 },249 250 [PERF_TYPE_SOFTWARE] = {251 .user_set = false,252 253 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |254 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |255 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |256 PERF_OUTPUT_SYM | PERF_OUTPUT_SYMOFFSET |257 PERF_OUTPUT_DSO | PERF_OUTPUT_PERIOD |258 PERF_OUTPUT_BPF_OUTPUT,259 260 .invalid_fields = PERF_OUTPUT_TRACE,261 },262 263 [PERF_TYPE_TRACEPOINT] = {264 .user_set = false,265 266 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |267 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |268 PERF_OUTPUT_EVNAME | PERF_OUTPUT_TRACE269 },270 271 [PERF_TYPE_HW_CACHE] = {272 .user_set = false,273 274 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |275 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |276 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |277 PERF_OUTPUT_SYM | PERF_OUTPUT_SYMOFFSET |278 PERF_OUTPUT_DSO | PERF_OUTPUT_PERIOD,279 280 .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT,281 },282 283 [PERF_TYPE_RAW] = {284 .user_set = false,285 286 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |287 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |288 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |289 PERF_OUTPUT_SYM | PERF_OUTPUT_SYMOFFSET |290 PERF_OUTPUT_DSO | PERF_OUTPUT_PERIOD |291 PERF_OUTPUT_ADDR | PERF_OUTPUT_DATA_SRC |292 PERF_OUTPUT_WEIGHT | PERF_OUTPUT_PHYS_ADDR |293 PERF_OUTPUT_DATA_PAGE_SIZE | PERF_OUTPUT_CODE_PAGE_SIZE |294 PERF_OUTPUT_INS_LAT | PERF_OUTPUT_RETIRE_LAT,295 296 .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT,297 },298 299 [PERF_TYPE_BREAKPOINT] = {300 .user_set = false,301 302 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |303 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |304 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |305 PERF_OUTPUT_SYM | PERF_OUTPUT_SYMOFFSET |306 PERF_OUTPUT_DSO | PERF_OUTPUT_PERIOD,307 308 .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT,309 },310 311 [OUTPUT_TYPE_SYNTH] = {312 .user_set = false,313 314 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |315 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |316 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |317 PERF_OUTPUT_SYM | PERF_OUTPUT_SYMOFFSET |318 PERF_OUTPUT_DSO | PERF_OUTPUT_SYNTH,319 320 .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT,321 },322 323 [OUTPUT_TYPE_OTHER] = {324 .user_set = false,325 326 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |327 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |328 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |329 PERF_OUTPUT_SYM | PERF_OUTPUT_SYMOFFSET |330 PERF_OUTPUT_DSO | PERF_OUTPUT_PERIOD,331 332 .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT,333 },334};335 336struct evsel_script {337 char *filename;338 FILE *fp;339 u64 samples;340 /* For metric output */341 u64 val;342 int gnum;343};344 345static inline struct evsel_script *evsel_script(struct evsel *evsel)346{347 return (struct evsel_script *)evsel->priv;348}349 350static struct evsel_script *evsel_script__new(struct evsel *evsel, struct perf_data *data)351{352 struct evsel_script *es = zalloc(sizeof(*es));353 354 if (es != NULL) {355 if (asprintf(&es->filename, "%s.%s.dump", data->file.path, evsel__name(evsel)) < 0)356 goto out_free;357 es->fp = fopen(es->filename, "w");358 if (es->fp == NULL)359 goto out_free_filename;360 }361 362 return es;363out_free_filename:364 zfree(&es->filename);365out_free:366 free(es);367 return NULL;368}369 370static void evsel_script__delete(struct evsel_script *es)371{372 zfree(&es->filename);373 fclose(es->fp);374 es->fp = NULL;375 free(es);376}377 378static int evsel_script__fprintf(struct evsel_script *es, FILE *fp)379{380 struct stat st;381 382 fstat(fileno(es->fp), &st);383 return fprintf(fp, "[ perf script: Wrote %.3f MB %s (%" PRIu64 " samples) ]\n",384 st.st_size / 1024.0 / 1024.0, es->filename, es->samples);385}386 387static inline int output_type(unsigned int type)388{389 switch (type) {390 case PERF_TYPE_SYNTH:391 return OUTPUT_TYPE_SYNTH;392 default:393 if (type < PERF_TYPE_MAX)394 return type;395 }396 397 return OUTPUT_TYPE_OTHER;398}399 400static bool output_set_by_user(void)401{402 int j;403 for (j = 0; j < OUTPUT_TYPE_MAX; ++j) {404 if (output[j].user_set)405 return true;406 }407 return false;408}409 410static const char *output_field2str(enum perf_output_field field)411{412 int i, imax = ARRAY_SIZE(all_output_options);413 const char *str = "";414 415 for (i = 0; i < imax; ++i) {416 if (all_output_options[i].field == field) {417 str = all_output_options[i].str;418 break;419 }420 }421 return str;422}423 424#define PRINT_FIELD(x) (output[output_type(attr->type)].fields & PERF_OUTPUT_##x)425 426static int evsel__do_check_stype(struct evsel *evsel, u64 sample_type, const char *sample_msg,427 enum perf_output_field field, bool allow_user_set)428{429 struct perf_event_attr *attr = &evsel->core.attr;430 int type = output_type(attr->type);431 const char *evname;432 433 if (attr->sample_type & sample_type)434 return 0;435 436 if (output[type].user_set_fields & field) {437 if (allow_user_set)438 return 0;439 evname = evsel__name(evsel);440 pr_err("Samples for '%s' event do not have %s attribute set. "441 "Cannot print '%s' field.\n",442 evname, sample_msg, output_field2str(field));443 return -1;444 }445 446 /* user did not ask for it explicitly so remove from the default list */447 output[type].fields &= ~field;448 evname = evsel__name(evsel);449 pr_debug("Samples for '%s' event do not have %s attribute set. "450 "Skipping '%s' field.\n",451 evname, sample_msg, output_field2str(field));452 453 return 0;454}455 456static int evsel__check_stype(struct evsel *evsel, u64 sample_type, const char *sample_msg,457 enum perf_output_field field)458{459 return evsel__do_check_stype(evsel, sample_type, sample_msg, field, false);460}461 462static int evsel__check_attr(struct evsel *evsel, struct perf_session *session)463{464 struct perf_event_attr *attr = &evsel->core.attr;465 bool allow_user_set;466 467 if (evsel__is_dummy_event(evsel))468 return 0;469 470 if (perf_header__has_feat(&session->header, HEADER_STAT))471 return 0;472 473 allow_user_set = perf_header__has_feat(&session->header,474 HEADER_AUXTRACE);475 476 if (PRINT_FIELD(TRACE) &&477 !perf_session__has_traces(session, "record -R"))478 return -EINVAL;479 480 if (PRINT_FIELD(IP)) {481 if (evsel__check_stype(evsel, PERF_SAMPLE_IP, "IP", PERF_OUTPUT_IP))482 return -EINVAL;483 }484 485 if (PRINT_FIELD(ADDR) &&486 evsel__do_check_stype(evsel, PERF_SAMPLE_ADDR, "ADDR", PERF_OUTPUT_ADDR, allow_user_set))487 return -EINVAL;488 489 if (PRINT_FIELD(DATA_SRC) &&490 evsel__do_check_stype(evsel, PERF_SAMPLE_DATA_SRC, "DATA_SRC", PERF_OUTPUT_DATA_SRC, allow_user_set))491 return -EINVAL;492 493 if (PRINT_FIELD(WEIGHT) &&494 evsel__do_check_stype(evsel, PERF_SAMPLE_WEIGHT_TYPE, "WEIGHT", PERF_OUTPUT_WEIGHT, allow_user_set))495 return -EINVAL;496 497 if (PRINT_FIELD(SYM) &&498 !(evsel->core.attr.sample_type & (PERF_SAMPLE_IP|PERF_SAMPLE_ADDR))) {499 pr_err("Display of symbols requested but neither sample IP nor "500 "sample address\navailable. Hence, no addresses to convert "501 "to symbols.\n");502 return -EINVAL;503 }504 if (PRINT_FIELD(SYMOFFSET) && !PRINT_FIELD(SYM)) {505 pr_err("Display of offsets requested but symbol is not"506 "selected.\n");507 return -EINVAL;508 }509 if (PRINT_FIELD(DSO) &&510 !(evsel->core.attr.sample_type & (PERF_SAMPLE_IP|PERF_SAMPLE_ADDR))) {511 pr_err("Display of DSO requested but no address to convert.\n");512 return -EINVAL;513 }514 if ((PRINT_FIELD(SRCLINE) || PRINT_FIELD(SRCCODE)) && !PRINT_FIELD(IP)) {515 pr_err("Display of source line number requested but sample IP is not\n"516 "selected. Hence, no address to lookup the source line number.\n");517 return -EINVAL;518 }519 if ((PRINT_FIELD(BRSTACKINSN) || PRINT_FIELD(BRSTACKINSNLEN) || PRINT_FIELD(BRSTACKDISASM))520 && !allow_user_set &&521 !(evlist__combined_branch_type(session->evlist) & PERF_SAMPLE_BRANCH_ANY)) {522 pr_err("Display of branch stack assembler requested, but non all-branch filter set\n"523 "Hint: run 'perf record -b ...'\n");524 return -EINVAL;525 }526 if (PRINT_FIELD(BRCNTR) &&527 !(evlist__combined_branch_type(session->evlist) & PERF_SAMPLE_BRANCH_COUNTERS)) {528 pr_err("Display of branch counter requested but it's not enabled\n"529 "Hint: run 'perf record -j any,counter ...'\n");530 return -EINVAL;531 }532 if ((PRINT_FIELD(PID) || PRINT_FIELD(TID)) &&533 evsel__check_stype(evsel, PERF_SAMPLE_TID, "TID", PERF_OUTPUT_TID|PERF_OUTPUT_PID))534 return -EINVAL;535 536 if (PRINT_FIELD(TIME) &&537 evsel__check_stype(evsel, PERF_SAMPLE_TIME, "TIME", PERF_OUTPUT_TIME))538 return -EINVAL;539 540 if (PRINT_FIELD(CPU) &&541 evsel__do_check_stype(evsel, PERF_SAMPLE_CPU, "CPU", PERF_OUTPUT_CPU, allow_user_set))542 return -EINVAL;543 544 if (PRINT_FIELD(IREGS) &&545 evsel__do_check_stype(evsel, PERF_SAMPLE_REGS_INTR, "IREGS", PERF_OUTPUT_IREGS, allow_user_set))546 return -EINVAL;547 548 if (PRINT_FIELD(UREGS) &&549 evsel__check_stype(evsel, PERF_SAMPLE_REGS_USER, "UREGS", PERF_OUTPUT_UREGS))550 return -EINVAL;551 552 if (PRINT_FIELD(PHYS_ADDR) &&553 evsel__do_check_stype(evsel, PERF_SAMPLE_PHYS_ADDR, "PHYS_ADDR", PERF_OUTPUT_PHYS_ADDR, allow_user_set))554 return -EINVAL;555 556 if (PRINT_FIELD(DATA_PAGE_SIZE) &&557 evsel__check_stype(evsel, PERF_SAMPLE_DATA_PAGE_SIZE, "DATA_PAGE_SIZE", PERF_OUTPUT_DATA_PAGE_SIZE))558 return -EINVAL;559 560 if (PRINT_FIELD(CODE_PAGE_SIZE) &&561 evsel__check_stype(evsel, PERF_SAMPLE_CODE_PAGE_SIZE, "CODE_PAGE_SIZE", PERF_OUTPUT_CODE_PAGE_SIZE))562 return -EINVAL;563 564 if (PRINT_FIELD(INS_LAT) &&565 evsel__check_stype(evsel, PERF_SAMPLE_WEIGHT_STRUCT, "WEIGHT_STRUCT", PERF_OUTPUT_INS_LAT))566 return -EINVAL;567 568 if (PRINT_FIELD(CGROUP) &&569 evsel__check_stype(evsel, PERF_SAMPLE_CGROUP, "CGROUP", PERF_OUTPUT_CGROUP)) {570 pr_err("Hint: run 'perf record --all-cgroups ...'\n");571 return -EINVAL;572 }573 574 if (PRINT_FIELD(RETIRE_LAT) &&575 evsel__check_stype(evsel, PERF_SAMPLE_WEIGHT_STRUCT, "WEIGHT_STRUCT", PERF_OUTPUT_RETIRE_LAT))576 return -EINVAL;577 578 return 0;579}580 581static void set_print_ip_opts(struct perf_event_attr *attr)582{583 unsigned int type = output_type(attr->type);584 585 output[type].print_ip_opts = 0;586 if (PRINT_FIELD(IP))587 output[type].print_ip_opts |= EVSEL__PRINT_IP;588 589 if (PRINT_FIELD(SYM))590 output[type].print_ip_opts |= EVSEL__PRINT_SYM;591 592 if (PRINT_FIELD(DSO))593 output[type].print_ip_opts |= EVSEL__PRINT_DSO;594 595 if (PRINT_FIELD(DSOFF))596 output[type].print_ip_opts |= EVSEL__PRINT_DSOFF;597 598 if (PRINT_FIELD(SYMOFFSET))599 output[type].print_ip_opts |= EVSEL__PRINT_SYMOFFSET;600 601 if (PRINT_FIELD(SRCLINE))602 output[type].print_ip_opts |= EVSEL__PRINT_SRCLINE;603}604 605static struct evsel *find_first_output_type(struct evlist *evlist,606 unsigned int type)607{608 struct evsel *evsel;609 610 evlist__for_each_entry(evlist, evsel) {611 if (evsel__is_dummy_event(evsel))612 continue;613 if (output_type(evsel->core.attr.type) == (int)type)614 return evsel;615 }616 return NULL;617}618 619/*620 * verify all user requested events exist and the samples621 * have the expected data622 */623static int perf_session__check_output_opt(struct perf_session *session)624{625 bool tod = false;626 unsigned int j;627 struct evsel *evsel;628 629 for (j = 0; j < OUTPUT_TYPE_MAX; ++j) {630 evsel = find_first_output_type(session->evlist, j);631 632 /*633 * even if fields is set to 0 (ie., show nothing) event must634 * exist if user explicitly includes it on the command line635 */636 if (!evsel && output[j].user_set && !output[j].wildcard_set &&637 j != OUTPUT_TYPE_SYNTH) {638 pr_err("%s events do not exist. "639 "Remove corresponding -F option to proceed.\n",640 event_type(j));641 return -1;642 }643 644 if (evsel && output[j].fields &&645 evsel__check_attr(evsel, session))646 return -1;647 648 if (evsel == NULL)649 continue;650 651 /* 'dsoff' implys 'dso' field */652 if (output[j].fields & PERF_OUTPUT_DSOFF)653 output[j].fields |= PERF_OUTPUT_DSO;654 655 set_print_ip_opts(&evsel->core.attr);656 tod |= output[j].fields & PERF_OUTPUT_TOD;657 }658 659 if (!no_callchain) {660 bool use_callchain = false;661 bool not_pipe = false;662 663 evlist__for_each_entry(session->evlist, evsel) {664 not_pipe = true;665 if (evsel__has_callchain(evsel)) {666 use_callchain = true;667 break;668 }669 }670 if (not_pipe && !use_callchain)671 symbol_conf.use_callchain = false;672 }673 674 /*675 * set default for tracepoints to print symbols only676 * if callchains are present677 */678 if (symbol_conf.use_callchain &&679 !output[PERF_TYPE_TRACEPOINT].user_set) {680 j = PERF_TYPE_TRACEPOINT;681 682 evlist__for_each_entry(session->evlist, evsel) {683 if (evsel->core.attr.type != j)684 continue;685 686 if (evsel__has_callchain(evsel)) {687 output[j].fields |= PERF_OUTPUT_IP;688 output[j].fields |= PERF_OUTPUT_SYM;689 output[j].fields |= PERF_OUTPUT_SYMOFFSET;690 output[j].fields |= PERF_OUTPUT_DSO;691 set_print_ip_opts(&evsel->core.attr);692 goto out;693 }694 }695 }696 697 if (tod && !session->header.env.clock.enabled) {698 pr_err("Can't provide 'tod' time, missing clock data. "699 "Please record with -k/--clockid option.\n");700 return -1;701 }702out:703 return 0;704}705 706static int perf_sample__fprintf_regs(struct regs_dump *regs, uint64_t mask, const char *arch,707 FILE *fp)708{709 unsigned i = 0, r;710 int printed = 0;711 712 if (!regs || !regs->regs)713 return 0;714 715 printed += fprintf(fp, " ABI:%" PRIu64 " ", regs->abi);716 717 for_each_set_bit(r, (unsigned long *) &mask, sizeof(mask) * 8) {718 u64 val = regs->regs[i++];719 printed += fprintf(fp, "%5s:0x%"PRIx64" ", perf_reg_name(r, arch), val);720 }721 722 return printed;723}724 725#define DEFAULT_TOD_FMT "%F %H:%M:%S"726 727static char*728tod_scnprintf(struct perf_script *script, char *buf, int buflen,729 u64 timestamp)730{731 u64 tod_ns, clockid_ns;732 struct perf_env *env;733 unsigned long nsec;734 struct tm ltime;735 char date[64];736 time_t sec;737 738 buf[0] = '\0';739 if (buflen < 64 || !script)740 return buf;741 742 env = &script->session->header.env;743 if (!env->clock.enabled) {744 scnprintf(buf, buflen, "disabled");745 return buf;746 }747 748 clockid_ns = env->clock.clockid_ns;749 tod_ns = env->clock.tod_ns;750 751 if (timestamp > clockid_ns)752 tod_ns += timestamp - clockid_ns;753 else754 tod_ns -= clockid_ns - timestamp;755 756 sec = (time_t) (tod_ns / NSEC_PER_SEC);757 nsec = tod_ns - sec * NSEC_PER_SEC;758 759 if (localtime_r(&sec, <ime) == NULL) {760 scnprintf(buf, buflen, "failed");761 } else {762 strftime(date, sizeof(date), DEFAULT_TOD_FMT, <ime);763 764 if (symbol_conf.nanosecs) {765 snprintf(buf, buflen, "%s.%09lu", date, nsec);766 } else {767 snprintf(buf, buflen, "%s.%06lu",768 date, nsec / NSEC_PER_USEC);769 }770 }771 772 return buf;773}774 775static int perf_sample__fprintf_iregs(struct perf_sample *sample,776 struct perf_event_attr *attr, const char *arch, FILE *fp)777{778 return perf_sample__fprintf_regs(&sample->intr_regs,779 attr->sample_regs_intr, arch, fp);780}781 782static int perf_sample__fprintf_uregs(struct perf_sample *sample,783 struct perf_event_attr *attr, const char *arch, FILE *fp)784{785 return perf_sample__fprintf_regs(&sample->user_regs,786 attr->sample_regs_user, arch, fp);787}788 789static int perf_sample__fprintf_start(struct perf_script *script,790 struct perf_sample *sample,791 struct thread *thread,792 struct evsel *evsel,793 u32 type, FILE *fp)794{795 struct perf_event_attr *attr = &evsel->core.attr;796 unsigned long secs;797 unsigned long long nsecs;798 int printed = 0;799 char tstr[128];800 801 /*802 * Print the branch counter's abbreviation list,803 * if the branch counter is available.804 */805 if (PRINT_FIELD(BRCNTR) && !verbose) {806 char *buf;807 808 if (!annotation_br_cntr_abbr_list(&buf, evsel, true)) {809 printed += fprintf(stdout, "%s", buf);810 free(buf);811 }812 }813 814 if (PRINT_FIELD(MACHINE_PID) && sample->machine_pid)815 printed += fprintf(fp, "VM:%5d ", sample->machine_pid);816 817 /* Print VCPU only for guest events i.e. with machine_pid */818 if (PRINT_FIELD(VCPU) && sample->machine_pid)819 printed += fprintf(fp, "VCPU:%03d ", sample->vcpu);820 821 if (PRINT_FIELD(COMM)) {822 const char *comm = thread ? thread__comm_str(thread) : ":-1";823 824 if (latency_format)825 printed += fprintf(fp, "%8.8s ", comm);826 else if (PRINT_FIELD(IP) && evsel__has_callchain(evsel) && symbol_conf.use_callchain)827 printed += fprintf(fp, "%s ", comm);828 else829 printed += fprintf(fp, "%16s ", comm);830 }831 832 if (PRINT_FIELD(PID) && PRINT_FIELD(TID))833 printed += fprintf(fp, "%7d/%-7d ", sample->pid, sample->tid);834 else if (PRINT_FIELD(PID))835 printed += fprintf(fp, "%7d ", sample->pid);836 else if (PRINT_FIELD(TID))837 printed += fprintf(fp, "%7d ", sample->tid);838 839 if (PRINT_FIELD(CPU)) {840 if (latency_format)841 printed += fprintf(fp, "%3d ", sample->cpu);842 else843 printed += fprintf(fp, "[%03d] ", sample->cpu);844 }845 846 if (PRINT_FIELD(MISC)) {847 int ret = 0;848 849 #define has(m) \850 (sample->misc & PERF_RECORD_MISC_##m) == PERF_RECORD_MISC_##m851 852 if (has(KERNEL))853 ret += fprintf(fp, "K");854 if (has(USER))855 ret += fprintf(fp, "U");856 if (has(HYPERVISOR))857 ret += fprintf(fp, "H");858 if (has(GUEST_KERNEL))859 ret += fprintf(fp, "G");860 if (has(GUEST_USER))861 ret += fprintf(fp, "g");862 863 switch (type) {864 case PERF_RECORD_MMAP:865 case PERF_RECORD_MMAP2:866 if (has(MMAP_DATA))867 ret += fprintf(fp, "M");868 break;869 case PERF_RECORD_COMM:870 if (has(COMM_EXEC))871 ret += fprintf(fp, "E");872 break;873 case PERF_RECORD_SWITCH:874 case PERF_RECORD_SWITCH_CPU_WIDE:875 if (has(SWITCH_OUT)) {876 ret += fprintf(fp, "S");877 if (sample->misc & PERF_RECORD_MISC_SWITCH_OUT_PREEMPT)878 ret += fprintf(fp, "p");879 }880 default:881 break;882 }883 884 #undef has885 886 ret += fprintf(fp, "%*s", 6 - ret, " ");887 printed += ret;888 }889 890 if (PRINT_FIELD(TOD)) {891 tod_scnprintf(script, tstr, sizeof(tstr), sample->time);892 printed += fprintf(fp, "%s ", tstr);893 }894 895 if (PRINT_FIELD(TIME)) {896 u64 t = sample->time;897 if (reltime) {898 if (!initial_time)899 initial_time = sample->time;900 t = sample->time - initial_time;901 } else if (deltatime) {902 if (previous_time)903 t = sample->time - previous_time;904 else {905 t = 0;906 }907 previous_time = sample->time;908 }909 nsecs = t;910 secs = nsecs / NSEC_PER_SEC;911 nsecs -= secs * NSEC_PER_SEC;912 913 if (symbol_conf.nanosecs)914 printed += fprintf(fp, "%5lu.%09llu: ", secs, nsecs);915 else {916 char sample_time[32];917 timestamp__scnprintf_usec(t, sample_time, sizeof(sample_time));918 printed += fprintf(fp, "%12s: ", sample_time);919 }920 }921 922 return printed;923}924 925static inline char926mispred_str(struct branch_entry *br)927{928 if (!(br->flags.mispred || br->flags.predicted))929 return '-';930 931 return br->flags.predicted ? 'P' : 'M';932}933 934static int print_bstack_flags(FILE *fp, struct branch_entry *br)935{936 return fprintf(fp, "/%c/%c/%c/%d/%s/%s ",937 mispred_str(br),938 br->flags.in_tx ? 'X' : '-',939 br->flags.abort ? 'A' : '-',940 br->flags.cycles,941 get_branch_type(br),942 br->flags.spec ? branch_spec_desc(br->flags.spec) : "-");943}944 945static int perf_sample__fprintf_brstack(struct perf_sample *sample,946 struct thread *thread,947 struct perf_event_attr *attr, FILE *fp)948{949 struct branch_stack *br = sample->branch_stack;950 struct branch_entry *entries = perf_sample__branch_entries(sample);951 u64 i, from, to;952 int printed = 0;953 954 if (!(br && br->nr))955 return 0;956 957 for (i = 0; i < br->nr; i++) {958 from = entries[i].from;959 to = entries[i].to;960 961 printed += fprintf(fp, " 0x%"PRIx64, from);962 if (PRINT_FIELD(DSO)) {963 struct addr_location alf, alt;964 965 addr_location__init(&alf);966 addr_location__init(&alt);967 thread__find_map_fb(thread, sample->cpumode, from, &alf);968 thread__find_map_fb(thread, sample->cpumode, to, &alt);969 970 printed += map__fprintf_dsoname_dsoff(alf.map, PRINT_FIELD(DSOFF), alf.addr, fp);971 printed += fprintf(fp, "/0x%"PRIx64, to);972 printed += map__fprintf_dsoname_dsoff(alt.map, PRINT_FIELD(DSOFF), alt.addr, fp);973 addr_location__exit(&alt);974 addr_location__exit(&alf);975 } else976 printed += fprintf(fp, "/0x%"PRIx64, to);977 978 printed += print_bstack_flags(fp, entries + i);979 }980 981 return printed;982}983 984static int perf_sample__fprintf_brstacksym(struct perf_sample *sample,985 struct thread *thread,986 struct perf_event_attr *attr, FILE *fp)987{988 struct branch_stack *br = sample->branch_stack;989 struct branch_entry *entries = perf_sample__branch_entries(sample);990 u64 i, from, to;991 int printed = 0;992 993 if (!(br && br->nr))994 return 0;995 996 for (i = 0; i < br->nr; i++) {997 struct addr_location alf, alt;998 999 addr_location__init(&alf);1000 addr_location__init(&alt);1001 from = entries[i].from;1002 to = entries[i].to;1003 1004 thread__find_symbol_fb(thread, sample->cpumode, from, &alf);1005 thread__find_symbol_fb(thread, sample->cpumode, to, &alt);1006 1007 printed += symbol__fprintf_symname_offs(alf.sym, &alf, fp);1008 if (PRINT_FIELD(DSO))1009 printed += map__fprintf_dsoname_dsoff(alf.map, PRINT_FIELD(DSOFF), alf.addr, fp);1010 printed += fprintf(fp, "%c", '/');1011 printed += symbol__fprintf_symname_offs(alt.sym, &alt, fp);1012 if (PRINT_FIELD(DSO))1013 printed += map__fprintf_dsoname_dsoff(alt.map, PRINT_FIELD(DSOFF), alt.addr, fp);1014 printed += print_bstack_flags(fp, entries + i);1015 addr_location__exit(&alt);1016 addr_location__exit(&alf);1017 }1018 1019 return printed;1020}1021 1022static int perf_sample__fprintf_brstackoff(struct perf_sample *sample,1023 struct thread *thread,1024 struct perf_event_attr *attr, FILE *fp)1025{1026 struct branch_stack *br = sample->branch_stack;1027 struct branch_entry *entries = perf_sample__branch_entries(sample);1028 u64 i, from, to;1029 int printed = 0;1030 1031 if (!(br && br->nr))1032 return 0;1033 1034 for (i = 0; i < br->nr; i++) {1035 struct addr_location alf, alt;1036 1037 addr_location__init(&alf);1038 addr_location__init(&alt);1039 from = entries[i].from;1040 to = entries[i].to;1041 1042 if (thread__find_map_fb(thread, sample->cpumode, from, &alf) &&1043 !dso__adjust_symbols(map__dso(alf.map)))1044 from = map__dso_map_ip(alf.map, from);1045 1046 if (thread__find_map_fb(thread, sample->cpumode, to, &alt) &&1047 !dso__adjust_symbols(map__dso(alt.map)))1048 to = map__dso_map_ip(alt.map, to);1049 1050 printed += fprintf(fp, " 0x%"PRIx64, from);1051 if (PRINT_FIELD(DSO))1052 printed += map__fprintf_dsoname_dsoff(alf.map, PRINT_FIELD(DSOFF), alf.addr, fp);1053 printed += fprintf(fp, "/0x%"PRIx64, to);1054 if (PRINT_FIELD(DSO))1055 printed += map__fprintf_dsoname_dsoff(alt.map, PRINT_FIELD(DSOFF), alt.addr, fp);1056 printed += print_bstack_flags(fp, entries + i);1057 addr_location__exit(&alt);1058 addr_location__exit(&alf);1059 }1060 1061 return printed;1062}1063#define MAXBB 16384UL1064 1065static int grab_bb(u8 *buffer, u64 start, u64 end,1066 struct machine *machine, struct thread *thread,1067 bool *is64bit, u8 *cpumode, bool last)1068{1069 long offset, len;1070 struct addr_location al;1071 bool kernel;1072 struct dso *dso;1073 int ret = 0;1074 1075 if (!start || !end)1076 return 0;1077 1078 kernel = machine__kernel_ip(machine, start);1079 if (kernel)1080 *cpumode = PERF_RECORD_MISC_KERNEL;1081 else1082 *cpumode = PERF_RECORD_MISC_USER;1083 1084 /*1085 * Block overlaps between kernel and user.1086 * This can happen due to ring filtering1087 * On Intel CPUs the entry into the kernel is filtered,1088 * but the exit is not. Let the caller patch it up.1089 */1090 if (kernel != machine__kernel_ip(machine, end)) {1091 pr_debug("\tblock %" PRIx64 "-%" PRIx64 " transfers between kernel and user\n", start, end);1092 return -ENXIO;1093 }1094 1095 if (end - start > MAXBB - MAXINSN) {1096 if (last)1097 pr_debug("\tbrstack does not reach to final jump (%" PRIx64 "-%" PRIx64 ")\n", start, end);1098 else1099 pr_debug("\tblock %" PRIx64 "-%" PRIx64 " (%" PRIu64 ") too long to dump\n", start, end, end - start);1100 return 0;1101 }1102 1103 addr_location__init(&al);1104 if (!thread__find_map(thread, *cpumode, start, &al) || (dso = map__dso(al.map)) == NULL) {1105 pr_debug("\tcannot resolve %" PRIx64 "-%" PRIx64 "\n", start, end);1106 goto out;1107 }1108 if (dso__data(dso)->status == DSO_DATA_STATUS_ERROR) {1109 pr_debug("\tcannot resolve %" PRIx64 "-%" PRIx64 "\n", start, end);1110 goto out;1111 }1112 1113 /* Load maps to ensure dso->is_64_bit has been updated */1114 map__load(al.map);1115 1116 offset = map__map_ip(al.map, start);1117 len = dso__data_read_offset(dso, machine, offset, (u8 *)buffer,1118 end - start + MAXINSN);1119 1120 *is64bit = dso__is_64_bit(dso);1121 if (len <= 0)1122 pr_debug("\tcannot fetch code for block at %" PRIx64 "-%" PRIx64 "\n",1123 start, end);1124 ret = len;1125out:1126 addr_location__exit(&al);1127 return ret;1128}1129 1130static int map__fprintf_srccode(struct map *map, u64 addr, FILE *fp, struct srccode_state *state)1131{1132 char *srcfile;1133 int ret = 0;1134 unsigned line;1135 int len;1136 char *srccode;1137 struct dso *dso;1138 1139 if (!map || (dso = map__dso(map)) == NULL)1140 return 0;1141 srcfile = get_srcline_split(dso,1142 map__rip_2objdump(map, addr),1143 &line);1144 if (!srcfile)1145 return 0;1146 1147 /* Avoid redundant printing */1148 if (state &&1149 state->srcfile &&1150 !strcmp(state->srcfile, srcfile) &&1151 state->line == line) {1152 free(srcfile);1153 return 0;1154 }1155 1156 srccode = find_sourceline(srcfile, line, &len);1157 if (!srccode)1158 goto out_free_line;1159 1160 ret = fprintf(fp, "|%-8d %.*s", line, len, srccode);1161 1162 if (state) {1163 state->srcfile = srcfile;1164 state->line = line;1165 }1166 return ret;1167 1168out_free_line:1169 free(srcfile);1170 return ret;1171}1172 1173static int print_srccode(struct thread *thread, u8 cpumode, uint64_t addr)1174{1175 struct addr_location al;1176 int ret = 0;1177 1178 addr_location__init(&al);1179 thread__find_map(thread, cpumode, addr, &al);1180 if (!al.map)1181 goto out;1182 ret = map__fprintf_srccode(al.map, al.addr, stdout,1183 thread__srccode_state(thread));1184 if (ret)1185 ret += printf("\n");1186out:1187 addr_location__exit(&al);1188 return ret;1189}1190 1191static int any_dump_insn(struct perf_event_attr *attr __maybe_unused,1192 struct perf_insn *x, uint64_t ip,1193 u8 *inbuf, int inlen, int *lenp,1194 FILE *fp)1195{1196#ifdef HAVE_LIBCAPSTONE_SUPPORT1197 if (PRINT_FIELD(BRSTACKDISASM)) {1198 int printed = fprintf_insn_asm(x->machine, x->thread, x->cpumode, x->is64bit,1199 (uint8_t *)inbuf, inlen, ip, lenp,1200 PRINT_INSN_IMM_HEX, fp);1201 1202 if (printed > 0)1203 return printed;1204 }1205#endif1206 return fprintf(fp, "%s", dump_insn(x, ip, inbuf, inlen, lenp));1207}1208 1209static int add_padding(FILE *fp, int printed, int padding)1210{1211 if (printed >= 0 && printed < padding)1212 printed += fprintf(fp, "%*s", padding - printed, "");1213 return printed;1214}1215 1216static int ip__fprintf_jump(uint64_t ip, struct branch_entry *en,1217 struct perf_insn *x, u8 *inbuf, int len,1218 int insn, FILE *fp, int *total_cycles,1219 struct perf_event_attr *attr,1220 struct thread *thread,1221 struct evsel *evsel,1222 u64 br_cntr)1223{1224 int ilen = 0;1225 int printed = fprintf(fp, "\t%016" PRIx64 "\t", ip);1226 1227 printed += add_padding(fp, any_dump_insn(attr, x, ip, inbuf, len, &ilen, fp), 30);1228 printed += fprintf(fp, "\t");1229 1230 if (PRINT_FIELD(BRSTACKINSNLEN))1231 printed += fprintf(fp, "ilen: %d\t", ilen);1232 1233 if (PRINT_FIELD(SRCLINE)) {1234 struct addr_location al;1235 1236 addr_location__init(&al);1237 thread__find_map(thread, x->cpumode, ip, &al);1238 printed += map__fprintf_srcline(al.map, al.addr, " srcline: ", fp);1239 printed += fprintf(fp, "\t");1240 addr_location__exit(&al);1241 }1242 1243 if (PRINT_FIELD(BRCNTR)) {1244 struct evsel *pos = evsel__leader(evsel);1245 unsigned int i = 0, j, num, mask, width;1246 1247 perf_env__find_br_cntr_info(evsel__env(evsel), NULL, &width);1248 mask = (1L << width) - 1;1249 printed += fprintf(fp, "br_cntr: ");1250 evlist__for_each_entry_from(evsel->evlist, pos) {1251 if (!(pos->core.attr.branch_sample_type & PERF_SAMPLE_BRANCH_COUNTERS))1252 continue;1253 if (evsel__leader(pos) != evsel__leader(evsel))1254 break;1255 1256 num = (br_cntr >> (i++ * width)) & mask;1257 if (!verbose) {1258 for (j = 0; j < num; j++)1259 printed += fprintf(fp, "%s", pos->abbr_name);1260 } else1261 printed += fprintf(fp, "%s %d ", pos->name, num);1262 }1263 printed += fprintf(fp, "\t");1264 }1265 1266 printed += fprintf(fp, "#%s%s%s%s",1267 en->flags.predicted ? " PRED" : "",1268 en->flags.mispred ? " MISPRED" : "",1269 en->flags.in_tx ? " INTX" : "",1270 en->flags.abort ? " ABORT" : "");1271 if (en->flags.cycles) {1272 *total_cycles += en->flags.cycles;1273 printed += fprintf(fp, " %d cycles [%d]", en->flags.cycles, *total_cycles);1274 if (insn)1275 printed += fprintf(fp, " %.2f IPC", (float)insn / en->flags.cycles);1276 }1277 1278 return printed + fprintf(fp, "\n");1279}1280 1281static int ip__fprintf_sym(uint64_t addr, struct thread *thread,1282 u8 cpumode, int cpu, struct symbol **lastsym,1283 struct perf_event_attr *attr, FILE *fp)1284{1285 struct addr_location al;1286 int off, printed = 0, ret = 0;1287 1288 addr_location__init(&al);1289 thread__find_map(thread, cpumode, addr, &al);1290 1291 if ((*lastsym) && al.addr >= (*lastsym)->start && al.addr < (*lastsym)->end)1292 goto out;1293 1294 al.cpu = cpu;1295 al.sym = NULL;1296 if (al.map)1297 al.sym = map__find_symbol(al.map, al.addr);1298 1299 if (!al.sym)1300 goto out;1301 1302 if (al.addr < al.sym->end)1303 off = al.addr - al.sym->start;1304 else1305 off = al.addr - map__start(al.map) - al.sym->start;1306 printed += fprintf(fp, "\t%s", al.sym->name);1307 if (off)1308 printed += fprintf(fp, "%+d", off);1309 printed += fprintf(fp, ":");1310 if (PRINT_FIELD(SRCLINE))1311 printed += map__fprintf_srcline(al.map, al.addr, "\t", fp);1312 printed += fprintf(fp, "\n");1313 *lastsym = al.sym;1314 1315 ret = printed;1316out:1317 addr_location__exit(&al);1318 return ret;1319}1320 1321static int perf_sample__fprintf_brstackinsn(struct perf_sample *sample,1322 struct evsel *evsel,1323 struct thread *thread,1324 struct perf_event_attr *attr,1325 struct machine *machine, FILE *fp)1326{1327 struct branch_stack *br = sample->branch_stack;1328 struct branch_entry *entries = perf_sample__branch_entries(sample);1329 u64 start, end;1330 int i, insn, len, nr, ilen, printed = 0;1331 struct perf_insn x;1332 u8 buffer[MAXBB];1333 unsigned off;1334 struct symbol *lastsym = NULL;1335 int total_cycles = 0;1336 u64 br_cntr = 0;1337 1338 if (!(br && br->nr))1339 return 0;1340 nr = br->nr;1341 if (max_blocks && nr > max_blocks + 1)1342 nr = max_blocks + 1;1343 1344 x.thread = thread;1345 x.machine = machine;1346 x.cpu = sample->cpu;1347 1348 if (PRINT_FIELD(BRCNTR) && sample->branch_stack_cntr)1349 br_cntr = sample->branch_stack_cntr[nr - 1];1350 1351 printed += fprintf(fp, "%c", '\n');1352 1353 /* Handle first from jump, of which we don't know the entry. */1354 len = grab_bb(buffer, entries[nr-1].from,1355 entries[nr-1].from,1356 machine, thread, &x.is64bit, &x.cpumode, false);1357 if (len > 0) {1358 printed += ip__fprintf_sym(entries[nr - 1].from, thread,1359 x.cpumode, x.cpu, &lastsym, attr, fp);1360 printed += ip__fprintf_jump(entries[nr - 1].from, &entries[nr - 1],1361 &x, buffer, len, 0, fp, &total_cycles,1362 attr, thread, evsel, br_cntr);1363 if (PRINT_FIELD(SRCCODE))1364 printed += print_srccode(thread, x.cpumode, entries[nr - 1].from);1365 }1366 1367 /* Print all blocks */1368 for (i = nr - 2; i >= 0; i--) {1369 if (entries[i].from || entries[i].to)1370 pr_debug("%d: %" PRIx64 "-%" PRIx64 "\n", i,1371 entries[i].from,1372 entries[i].to);1373 start = entries[i + 1].to;1374 end = entries[i].from;1375 1376 len = grab_bb(buffer, start, end, machine, thread, &x.is64bit, &x.cpumode, false);1377 /* Patch up missing kernel transfers due to ring filters */1378 if (len == -ENXIO && i > 0) {1379 end = entries[--i].from;1380 pr_debug("\tpatching up to %" PRIx64 "-%" PRIx64 "\n", start, end);1381 len = grab_bb(buffer, start, end, machine, thread, &x.is64bit, &x.cpumode, false);1382 }1383 if (len <= 0)1384 continue;1385 1386 insn = 0;1387 for (off = 0; off < (unsigned)len; off += ilen) {1388 uint64_t ip = start + off;1389 1390 printed += ip__fprintf_sym(ip, thread, x.cpumode, x.cpu, &lastsym, attr, fp);1391 if (ip == end) {1392 if (PRINT_FIELD(BRCNTR) && sample->branch_stack_cntr)1393 br_cntr = sample->branch_stack_cntr[i];1394 printed += ip__fprintf_jump(ip, &entries[i], &x, buffer + off, len - off, ++insn, fp,1395 &total_cycles, attr, thread, evsel, br_cntr);1396 if (PRINT_FIELD(SRCCODE))1397 printed += print_srccode(thread, x.cpumode, ip);1398 break;1399 } else {1400 ilen = 0;1401 printed += fprintf(fp, "\t%016" PRIx64 "\t", ip);1402 printed += any_dump_insn(attr, &x, ip, buffer + off, len - off, &ilen, fp);1403 if (PRINT_FIELD(BRSTACKINSNLEN))1404 printed += fprintf(fp, "\tilen: %d", ilen);1405 printed += fprintf(fp, "\n");1406 if (ilen == 0)1407 break;1408 if (PRINT_FIELD(SRCCODE))1409 print_srccode(thread, x.cpumode, ip);1410 insn++;1411 }1412 }1413 if (off != end - start)1414 printed += fprintf(fp, "\tmismatch of LBR data and executable\n");1415 }1416 1417 /*1418 * Hit the branch? In this case we are already done, and the target1419 * has not been executed yet.1420 */1421 if (entries[0].from == sample->ip)1422 goto out;1423 if (entries[0].flags.abort)1424 goto out;1425 1426 /*1427 * Print final block up to sample1428 *1429 * Due to pipeline delays the LBRs might be missing a branch1430 * or two, which can result in very large or negative blocks1431 * between final branch and sample. When this happens just1432 * continue walking after the last TO.1433 */1434 start = entries[0].to;1435 end = sample->ip;1436 if (end < start) {1437 /* Missing jump. Scan 128 bytes for the next branch */1438 end = start + 128;1439 }1440 len = grab_bb(buffer, start, end, machine, thread, &x.is64bit, &x.cpumode, true);1441 printed += ip__fprintf_sym(start, thread, x.cpumode, x.cpu, &lastsym, attr, fp);1442 if (len <= 0) {1443 /* Print at least last IP if basic block did not work */1444 len = grab_bb(buffer, sample->ip, sample->ip,1445 machine, thread, &x.is64bit, &x.cpumode, false);1446 if (len <= 0)1447 goto out;1448 ilen = 0;1449 printed += fprintf(fp, "\t%016" PRIx64 "\t", sample->ip);1450 printed += any_dump_insn(attr, &x, sample->ip, buffer, len, &ilen, fp);1451 if (PRINT_FIELD(BRSTACKINSNLEN))1452 printed += fprintf(fp, "\tilen: %d", ilen);1453 printed += fprintf(fp, "\n");1454 if (PRINT_FIELD(SRCCODE))1455 print_srccode(thread, x.cpumode, sample->ip);1456 goto out;1457 }1458 for (off = 0; off <= end - start; off += ilen) {1459 ilen = 0;1460 printed += fprintf(fp, "\t%016" PRIx64 "\t", start + off);1461 printed += any_dump_insn(attr, &x, start + off, buffer + off, len - off, &ilen, fp);1462 if (PRINT_FIELD(BRSTACKINSNLEN))1463 printed += fprintf(fp, "\tilen: %d", ilen);1464 printed += fprintf(fp, "\n");1465 if (ilen == 0)1466 break;1467 if ((attr->branch_sample_type == 0 || attr->branch_sample_type & PERF_SAMPLE_BRANCH_ANY)1468 && arch_is_uncond_branch(buffer + off, len - off, x.is64bit)1469 && start + off != sample->ip) {1470 /*1471 * Hit a missing branch. Just stop.1472 */1473 printed += fprintf(fp, "\t... not reaching sample ...\n");1474 break;1475 }1476 if (PRINT_FIELD(SRCCODE))1477 print_srccode(thread, x.cpumode, start + off);1478 }1479out:1480 return printed;1481}1482 1483static int perf_sample__fprintf_addr(struct perf_sample *sample,1484 struct thread *thread,1485 struct perf_event_attr *attr, FILE *fp)1486{1487 struct addr_location al;1488 int printed = fprintf(fp, "%16" PRIx64, sample->addr);1489 1490 addr_location__init(&al);1491 if (!sample_addr_correlates_sym(attr))1492 goto out;1493 1494 thread__resolve(thread, &al, sample);1495 1496 if (PRINT_FIELD(SYM)) {1497 printed += fprintf(fp, " ");1498 if (PRINT_FIELD(SYMOFFSET))1499 printed += symbol__fprintf_symname_offs(al.sym, &al, fp);1500 else1501 printed += symbol__fprintf_symname(al.sym, fp);1502 }1503 1504 if (PRINT_FIELD(DSO))1505 printed += map__fprintf_dsoname_dsoff(al.map, PRINT_FIELD(DSOFF), al.addr, fp);1506out:1507 addr_location__exit(&al);1508 return printed;1509}1510 1511static const char *resolve_branch_sym(struct perf_sample *sample,1512 struct evsel *evsel,1513 struct thread *thread,1514 struct addr_location *al,1515 struct addr_location *addr_al,1516 u64 *ip)1517{1518 struct perf_event_attr *attr = &evsel->core.attr;1519 const char *name = NULL;1520 1521 if (sample->flags & (PERF_IP_FLAG_CALL | PERF_IP_FLAG_TRACE_BEGIN)) {1522 if (sample_addr_correlates_sym(attr)) {1523 if (!addr_al->thread)1524 thread__resolve(thread, addr_al, sample);1525 if (addr_al->sym)1526 name = addr_al->sym->name;1527 else1528 *ip = sample->addr;1529 } else {1530 *ip = sample->addr;1531 }1532 } else if (sample->flags & (PERF_IP_FLAG_RETURN | PERF_IP_FLAG_TRACE_END)) {1533 if (al->sym)1534 name = al->sym->name;1535 else1536 *ip = sample->ip;1537 }1538 return name;1539}1540 1541static int perf_sample__fprintf_callindent(struct perf_sample *sample,1542 struct evsel *evsel,1543 struct thread *thread,1544 struct addr_location *al,1545 struct addr_location *addr_al,1546 FILE *fp)1547{1548 struct perf_event_attr *attr = &evsel->core.attr;1549 size_t depth = thread_stack__depth(thread, sample->cpu);1550 const char *name = NULL;1551 static int spacing;1552 int len = 0;1553 int dlen = 0;1554 u64 ip = 0;1555 1556 /*1557 * The 'return' has already been popped off the stack so the depth has1558 * to be adjusted to match the 'call'.1559 */1560 if (thread__ts(thread) && sample->flags & PERF_IP_FLAG_RETURN)1561 depth += 1;1562 1563 name = resolve_branch_sym(sample, evsel, thread, al, addr_al, &ip);1564 1565 if (PRINT_FIELD(DSO) && !(PRINT_FIELD(IP) || PRINT_FIELD(ADDR))) {1566 dlen += fprintf(fp, "(");1567 dlen += map__fprintf_dsoname(al->map, fp);1568 dlen += fprintf(fp, ")\t");1569 }1570 1571 if (name)1572 len = fprintf(fp, "%*s%s", (int)depth * 4, "", name);1573 else if (ip)1574 len = fprintf(fp, "%*s%16" PRIx64, (int)depth * 4, "", ip);1575 1576 if (len < 0)1577 return len;1578 1579 /*1580 * Try to keep the output length from changing frequently so that the1581 * output lines up more nicely.1582 */1583 if (len > spacing || (len && len < spacing - 52))1584 spacing = round_up(len + 4, 32);1585 1586 if (len < spacing)1587 len += fprintf(fp, "%*s", spacing - len, "");1588 1589 return len + dlen;1590}1591 1592__weak void arch_fetch_insn(struct perf_sample *sample __maybe_unused,1593 struct thread *thread __maybe_unused,1594 struct machine *machine __maybe_unused)1595{1596}1597 1598void script_fetch_insn(struct perf_sample *sample, struct thread *thread,1599 struct machine *machine)1600{1601 if (sample->insn_len == 0 && native_arch)1602 arch_fetch_insn(sample, thread, machine);1603}1604 1605static int perf_sample__fprintf_insn(struct perf_sample *sample,1606 struct evsel *evsel,1607 struct perf_event_attr *attr,1608 struct thread *thread,1609 struct machine *machine, FILE *fp,1610 struct addr_location *al)1611{1612 int printed = 0;1613 1614 script_fetch_insn(sample, thread, machine);1615 1616 if (PRINT_FIELD(INSNLEN))1617 printed += fprintf(fp, " ilen: %d", sample->insn_len);1618 if (PRINT_FIELD(INSN) && sample->insn_len) {1619 printed += fprintf(fp, " insn: ");1620 printed += sample__fprintf_insn_raw(sample, fp);1621 }1622 if (PRINT_FIELD(DISASM) && sample->insn_len) {1623 printed += fprintf(fp, "\t\t");1624 printed += sample__fprintf_insn_asm(sample, thread, machine, fp, al);1625 }1626 if (PRINT_FIELD(BRSTACKINSN) || PRINT_FIELD(BRSTACKINSNLEN) || PRINT_FIELD(BRSTACKDISASM))1627 printed += perf_sample__fprintf_brstackinsn(sample, evsel, thread, attr, machine, fp);1628 1629 return printed;1630}1631 1632static int perf_sample__fprintf_ipc(struct perf_sample *sample,1633 struct perf_event_attr *attr, FILE *fp)1634{1635 unsigned int ipc;1636 1637 if (!PRINT_FIELD(IPC) || !sample->cyc_cnt || !sample->insn_cnt)1638 return 0;1639 1640 ipc = (sample->insn_cnt * 100) / sample->cyc_cnt;1641 1642 return fprintf(fp, " \t IPC: %u.%02u (%" PRIu64 "/%" PRIu64 ") ",1643 ipc / 100, ipc % 100, sample->insn_cnt, sample->cyc_cnt);1644}1645 1646static int perf_sample__fprintf_bts(struct perf_sample *sample,1647 struct evsel *evsel,1648 struct thread *thread,1649 struct addr_location *al,1650 struct addr_location *addr_al,1651 struct machine *machine, FILE *fp)1652{1653 struct perf_event_attr *attr = &evsel->core.attr;1654 unsigned int type = output_type(attr->type);1655 bool print_srcline_last = false;1656 int printed = 0;1657 1658 if (PRINT_FIELD(CALLINDENT))1659 printed += perf_sample__fprintf_callindent(sample, evsel, thread, al, addr_al, fp);1660 1661 /* print branch_from information */1662 if (PRINT_FIELD(IP)) {1663 unsigned int print_opts = output[type].print_ip_opts;1664 struct callchain_cursor *cursor = NULL;1665 1666 if (symbol_conf.use_callchain && sample->callchain) {1667 cursor = get_tls_callchain_cursor();1668 if (thread__resolve_callchain(al->thread, cursor, evsel,1669 sample, NULL, NULL,1670 scripting_max_stack))1671 cursor = NULL;1672 }1673 if (cursor == NULL) {1674 printed += fprintf(fp, " ");1675 if (print_opts & EVSEL__PRINT_SRCLINE) {1676 print_srcline_last = true;1677 print_opts &= ~EVSEL__PRINT_SRCLINE;1678 }1679 } else1680 printed += fprintf(fp, "\n");1681 1682 printed += sample__fprintf_sym(sample, al, 0, print_opts, cursor,1683 symbol_conf.bt_stop_list, fp);1684 }1685 1686 /* print branch_to information */1687 if (PRINT_FIELD(ADDR) ||1688 ((evsel->core.attr.sample_type & PERF_SAMPLE_ADDR) &&1689 !output[type].user_set)) {1690 printed += fprintf(fp, " => ");1691 printed += perf_sample__fprintf_addr(sample, thread, attr, fp);1692 }1693 1694 printed += perf_sample__fprintf_ipc(sample, attr, fp);1695 1696 if (print_srcline_last)1697 printed += map__fprintf_srcline(al->map, al->addr, "\n ", fp);1698 1699 printed += perf_sample__fprintf_insn(sample, evsel, attr, thread, machine, fp, al);1700 printed += fprintf(fp, "\n");1701 if (PRINT_FIELD(SRCCODE)) {1702 int ret = map__fprintf_srccode(al->map, al->addr, stdout,1703 thread__srccode_state(thread));1704 if (ret) {1705 printed += ret;1706 printed += printf("\n");1707 }1708 }1709 return printed;1710}1711 1712static struct {1713 u32 flags;1714 const char *name;1715} sample_flags[] = {1716 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL, "call"},1717 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN, "return"},1718 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CONDITIONAL, "jcc"},1719 {PERF_IP_FLAG_BRANCH, "jmp"},1720 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_INTERRUPT, "int"},1721 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN | PERF_IP_FLAG_INTERRUPT, "iret"},1722 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_SYSCALLRET, "syscall"},1723 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN | PERF_IP_FLAG_SYSCALLRET, "sysret"},1724 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_ASYNC, "async"},1725 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_ASYNC | PERF_IP_FLAG_INTERRUPT, "hw int"},1726 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TX_ABORT, "tx abrt"},1727 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TRACE_BEGIN, "tr strt"},1728 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TRACE_END, "tr end"},1729 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_VMENTRY, "vmentry"},1730 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_VMEXIT, "vmexit"},1731 {0, NULL}1732};1733 1734static const char *sample_flags_to_name(u32 flags)1735{1736 int i;1737 1738 for (i = 0; sample_flags[i].name ; i++) {1739 if (sample_flags[i].flags == flags)1740 return sample_flags[i].name;1741 }1742 1743 return NULL;1744}1745 1746int perf_sample__sprintf_flags(u32 flags, char *str, size_t sz)1747{1748 u32 xf = PERF_IP_FLAG_IN_TX | PERF_IP_FLAG_INTR_DISABLE |1749 PERF_IP_FLAG_INTR_TOGGLE;1750 const char *chars = PERF_IP_FLAG_CHARS;1751 const size_t n = strlen(PERF_IP_FLAG_CHARS);1752 const char *name = NULL;1753 size_t i, pos = 0;1754 char xs[16] = {0};1755 1756 if (flags & xf)1757 snprintf(xs, sizeof(xs), "(%s%s%s)",1758 flags & PERF_IP_FLAG_IN_TX ? "x" : "",1759 flags & PERF_IP_FLAG_INTR_DISABLE ? "D" : "",1760 flags & PERF_IP_FLAG_INTR_TOGGLE ? "t" : "");1761 1762 name = sample_flags_to_name(flags & ~xf);1763 if (name)1764 return snprintf(str, sz, "%-15s%6s", name, xs);1765 1766 if (flags & PERF_IP_FLAG_TRACE_BEGIN) {1767 name = sample_flags_to_name(flags & ~(xf | PERF_IP_FLAG_TRACE_BEGIN));1768 if (name)1769 return snprintf(str, sz, "tr strt %-7s%6s", name, xs);1770 }1771 1772 if (flags & PERF_IP_FLAG_TRACE_END) {1773 name = sample_flags_to_name(flags & ~(xf | PERF_IP_FLAG_TRACE_END));1774 if (name)1775 return snprintf(str, sz, "tr end %-7s%6s", name, xs);1776 }1777 1778 for (i = 0; i < n; i++, flags >>= 1) {1779 if ((flags & 1) && pos < sz)1780 str[pos++] = chars[i];1781 }1782 for (; i < 32; i++, flags >>= 1) {1783 if ((flags & 1) && pos < sz)1784 str[pos++] = '?';1785 }1786 if (pos < sz)1787 str[pos] = 0;1788 1789 return pos;1790}1791 1792static int perf_sample__fprintf_flags(u32 flags, FILE *fp)1793{1794 char str[SAMPLE_FLAGS_BUF_SIZE];1795 1796 perf_sample__sprintf_flags(flags, str, sizeof(str));1797 return fprintf(fp, " %-21s ", str);1798}1799 1800struct printer_data {1801 int line_no;1802 bool hit_nul;1803 bool is_printable;1804};1805 1806static int sample__fprintf_bpf_output(enum binary_printer_ops op,1807 unsigned int val,1808 void *extra, FILE *fp)1809{1810 unsigned char ch = (unsigned char)val;1811 struct printer_data *printer_data = extra;1812 int printed = 0;1813 1814 switch (op) {1815 case BINARY_PRINT_DATA_BEGIN:1816 printed += fprintf(fp, "\n");1817 break;1818 case BINARY_PRINT_LINE_BEGIN:1819 printed += fprintf(fp, "%17s", !printer_data->line_no ? "BPF output:" :1820 " ");1821 break;1822 case BINARY_PRINT_ADDR:1823 printed += fprintf(fp, " %04x:", val);1824 break;1825 case BINARY_PRINT_NUM_DATA:1826 printed += fprintf(fp, " %02x", val);1827 break;1828 case BINARY_PRINT_NUM_PAD:1829 printed += fprintf(fp, " ");1830 break;1831 case BINARY_PRINT_SEP:1832 printed += fprintf(fp, " ");1833 break;1834 case BINARY_PRINT_CHAR_DATA:1835 if (printer_data->hit_nul && ch)1836 printer_data->is_printable = false;1837 1838 if (!isprint(ch)) {1839 printed += fprintf(fp, "%c", '.');1840 1841 if (!printer_data->is_printable)1842 break;1843 1844 if (ch == '\0')1845 printer_data->hit_nul = true;1846 else1847 printer_data->is_printable = false;1848 } else {1849 printed += fprintf(fp, "%c", ch);1850 }1851 break;1852 case BINARY_PRINT_CHAR_PAD:1853 printed += fprintf(fp, " ");1854 break;1855 case BINARY_PRINT_LINE_END:1856 printed += fprintf(fp, "\n");1857 printer_data->line_no++;1858 break;1859 case BINARY_PRINT_DATA_END:1860 default:1861 break;1862 }1863 1864 return printed;1865}1866 1867static int perf_sample__fprintf_bpf_output(struct perf_sample *sample, FILE *fp)1868{1869 unsigned int nr_bytes = sample->raw_size;1870 struct printer_data printer_data = {0, false, true};1871 int printed = binary__fprintf(sample->raw_data, nr_bytes, 8,1872 sample__fprintf_bpf_output, &printer_data, fp);1873 1874 if (printer_data.is_printable && printer_data.hit_nul)1875 printed += fprintf(fp, "%17s \"%s\"\n", "BPF string:", (char *)(sample->raw_data));1876 1877 return printed;1878}1879 1880static int perf_sample__fprintf_spacing(int len, int spacing, FILE *fp)1881{1882 if (len > 0 && len < spacing)1883 return fprintf(fp, "%*s", spacing - len, "");1884 1885 return 0;1886}1887 1888static int perf_sample__fprintf_pt_spacing(int len, FILE *fp)1889{1890 return perf_sample__fprintf_spacing(len, 34, fp);1891}1892 1893/* If a value contains only printable ASCII characters padded with NULLs */1894static bool ptw_is_prt(u64 val)1895{1896 char c;1897 u32 i;1898 1899 for (i = 0; i < sizeof(val); i++) {1900 c = ((char *)&val)[i];1901 if (!c)1902 break;1903 if (!isprint(c) || !isascii(c))1904 return false;1905 }1906 for (; i < sizeof(val); i++) {1907 c = ((char *)&val)[i];1908 if (c)1909 return false;1910 }1911 return true;1912}1913 1914static int perf_sample__fprintf_synth_ptwrite(struct perf_sample *sample, FILE *fp)1915{1916 struct perf_synth_intel_ptwrite *data = perf_sample__synth_ptr(sample);1917 char str[sizeof(u64) + 1] = "";1918 int len;1919 u64 val;1920 1921 if (perf_sample__bad_synth_size(sample, *data))1922 return 0;1923 1924 val = le64_to_cpu(data->payload);1925 if (ptw_is_prt(val)) {1926 memcpy(str, &val, sizeof(val));1927 str[sizeof(val)] = 0;1928 }1929 len = fprintf(fp, " IP: %u payload: %#" PRIx64 " %s ",1930 data->ip, val, str);1931 return len + perf_sample__fprintf_pt_spacing(len, fp);1932}1933 1934static int perf_sample__fprintf_synth_mwait(struct perf_sample *sample, FILE *fp)1935{1936 struct perf_synth_intel_mwait *data = perf_sample__synth_ptr(sample);1937 int len;1938 1939 if (perf_sample__bad_synth_size(sample, *data))1940 return 0;1941 1942 len = fprintf(fp, " hints: %#x extensions: %#x ",1943 data->hints, data->extensions);1944 return len + perf_sample__fprintf_pt_spacing(len, fp);1945}1946 1947static int perf_sample__fprintf_synth_pwre(struct perf_sample *sample, FILE *fp)1948{1949 struct perf_synth_intel_pwre *data = perf_sample__synth_ptr(sample);1950 int len;1951 1952 if (perf_sample__bad_synth_size(sample, *data))1953 return 0;1954 1955 len = fprintf(fp, " hw: %u cstate: %u sub-cstate: %u ",1956 data->hw, data->cstate, data->subcstate);1957 return len + perf_sample__fprintf_pt_spacing(len, fp);1958}1959 1960static int perf_sample__fprintf_synth_exstop(struct perf_sample *sample, FILE *fp)1961{1962 struct perf_synth_intel_exstop *data = perf_sample__synth_ptr(sample);1963 int len;1964 1965 if (perf_sample__bad_synth_size(sample, *data))1966 return 0;1967 1968 len = fprintf(fp, " IP: %u ", data->ip);1969 return len + perf_sample__fprintf_pt_spacing(len, fp);1970}1971 1972static int perf_sample__fprintf_synth_pwrx(struct perf_sample *sample, FILE *fp)1973{1974 struct perf_synth_intel_pwrx *data = perf_sample__synth_ptr(sample);1975 int len;1976 1977 if (perf_sample__bad_synth_size(sample, *data))1978 return 0;1979 1980 len = fprintf(fp, " deepest cstate: %u last cstate: %u wake reason: %#x ",1981 data->deepest_cstate, data->last_cstate,1982 data->wake_reason);1983 return len + perf_sample__fprintf_pt_spacing(len, fp);1984}1985 1986static int perf_sample__fprintf_synth_cbr(struct perf_sample *sample, FILE *fp)1987{1988 struct perf_synth_intel_cbr *data = perf_sample__synth_ptr(sample);1989 unsigned int percent, freq;1990 int len;1991 1992 if (perf_sample__bad_synth_size(sample, *data))1993 return 0;1994 1995 freq = (le32_to_cpu(data->freq) + 500) / 1000;1996 len = fprintf(fp, " cbr: %2u freq: %4u MHz ", data->cbr, freq);1997 if (data->max_nonturbo) {1998 percent = (5 + (1000 * data->cbr) / data->max_nonturbo) / 10;1999 len += fprintf(fp, "(%3u%%) ", percent);2000 }2001 return len + perf_sample__fprintf_pt_spacing(len, fp);2002}2003 2004static int perf_sample__fprintf_synth_psb(struct perf_sample *sample, FILE *fp)2005{2006 struct perf_synth_intel_psb *data = perf_sample__synth_ptr(sample);2007 int len;2008 2009 if (perf_sample__bad_synth_size(sample, *data))2010 return 0;2011 2012 len = fprintf(fp, " psb offs: %#" PRIx64, data->offset);2013 return len + perf_sample__fprintf_pt_spacing(len, fp);2014}2015 2016/* Intel PT Event Trace */2017static int perf_sample__fprintf_synth_evt(struct perf_sample *sample, FILE *fp)2018{2019 struct perf_synth_intel_evt *data = perf_sample__synth_ptr(sample);2020 const char *cfe[32] = {NULL, "INTR", "IRET", "SMI", "RSM", "SIPI",2021 "INIT", "VMENTRY", "VMEXIT", "VMEXIT_INTR",2022 "SHUTDOWN", NULL, "UINTR", "UIRET"};2023 const char *evd[64] = {"PFA", "VMXQ", "VMXR"};2024 const char *s;2025 int len, i;2026 2027 if (perf_sample__bad_synth_size(sample, *data))2028 return 0;2029 2030 s = cfe[data->type];2031 if (s) {2032 len = fprintf(fp, " cfe: %s IP: %d vector: %u",2033 s, data->ip, data->vector);2034 } else {2035 len = fprintf(fp, " cfe: %u IP: %d vector: %u",2036 data->type, data->ip, data->vector);2037 }2038 for (i = 0; i < data->evd_cnt; i++) {2039 unsigned int et = data->evd[i].evd_type & 0x3f;2040 2041 s = evd[et];2042 if (s) {2043 len += fprintf(fp, " %s: %#" PRIx64,2044 s, data->evd[i].payload);2045 } else {2046 len += fprintf(fp, " EVD_%u: %#" PRIx64,2047 et, data->evd[i].payload);2048 }2049 }2050 return len + perf_sample__fprintf_pt_spacing(len, fp);2051}2052 2053static int perf_sample__fprintf_synth_iflag_chg(struct perf_sample *sample, FILE *fp)2054{2055 struct perf_synth_intel_iflag_chg *data = perf_sample__synth_ptr(sample);2056 int len;2057 2058 if (perf_sample__bad_synth_size(sample, *data))2059 return 0;2060 2061 len = fprintf(fp, " IFLAG: %d->%d %s branch", !data->iflag, data->iflag,2062 data->via_branch ? "via" : "non");2063 return len + perf_sample__fprintf_pt_spacing(len, fp);2064}2065 2066static int perf_sample__fprintf_synth(struct perf_sample *sample,2067 struct evsel *evsel, FILE *fp)2068{2069 switch (evsel->core.attr.config) {2070 case PERF_SYNTH_INTEL_PTWRITE:2071 return perf_sample__fprintf_synth_ptwrite(sample, fp);2072 case PERF_SYNTH_INTEL_MWAIT:2073 return perf_sample__fprintf_synth_mwait(sample, fp);2074 case PERF_SYNTH_INTEL_PWRE:2075 return perf_sample__fprintf_synth_pwre(sample, fp);2076 case PERF_SYNTH_INTEL_EXSTOP:2077 return perf_sample__fprintf_synth_exstop(sample, fp);2078 case PERF_SYNTH_INTEL_PWRX:2079 return perf_sample__fprintf_synth_pwrx(sample, fp);2080 case PERF_SYNTH_INTEL_CBR:2081 return perf_sample__fprintf_synth_cbr(sample, fp);2082 case PERF_SYNTH_INTEL_PSB:2083 return perf_sample__fprintf_synth_psb(sample, fp);2084 case PERF_SYNTH_INTEL_EVT:2085 return perf_sample__fprintf_synth_evt(sample, fp);2086 case PERF_SYNTH_INTEL_IFLAG_CHG:2087 return perf_sample__fprintf_synth_iflag_chg(sample, fp);2088 default:2089 break;2090 }2091 2092 return 0;2093}2094 2095static int evlist__max_name_len(struct evlist *evlist)2096{2097 struct evsel *evsel;2098 int max = 0;2099 2100 evlist__for_each_entry(evlist, evsel) {2101 int len = strlen(evsel__name(evsel));2102 2103 max = MAX(len, max);2104 }2105 2106 return max;2107}2108 2109static int data_src__fprintf(u64 data_src, FILE *fp)2110{2111 struct mem_info *mi = mem_info__new();2112 char decode[100];2113 char out[100];2114 static int maxlen;2115 int len;2116 2117 if (!mi)2118 return -ENOMEM;2119 2120 mem_info__data_src(mi)->val = data_src;2121 perf_script__meminfo_scnprintf(decode, 100, mi);2122 mem_info__put(mi);2123 2124 len = scnprintf(out, 100, "%16" PRIx64 " %s", data_src, decode);2125 if (maxlen < len)2126 maxlen = len;2127 2128 return fprintf(fp, "%-*s", maxlen, out);2129}2130 2131struct metric_ctx {2132 struct perf_sample *sample;2133 struct thread *thread;2134 struct evsel *evsel;2135 FILE *fp;2136};2137 2138static void script_print_metric(struct perf_stat_config *config __maybe_unused,2139 void *ctx, const char *color,2140 const char *fmt,2141 const char *unit, double val)2142{2143 struct metric_ctx *mctx = ctx;2144 2145 if (!fmt)2146 return;2147 perf_sample__fprintf_start(NULL, mctx->sample, mctx->thread, mctx->evsel,2148 PERF_RECORD_SAMPLE, mctx->fp);2149 fputs("\tmetric: ", mctx->fp);2150 if (color)2151 color_fprintf(mctx->fp, color, fmt, val);2152 else2153 printf(fmt, val);2154 fprintf(mctx->fp, " %s\n", unit);2155}2156 2157static void script_new_line(struct perf_stat_config *config __maybe_unused,2158 void *ctx)2159{2160 struct metric_ctx *mctx = ctx;2161 2162 perf_sample__fprintf_start(NULL, mctx->sample, mctx->thread, mctx->evsel,2163 PERF_RECORD_SAMPLE, mctx->fp);2164 fputs("\tmetric: ", mctx->fp);2165}2166 2167static void perf_sample__fprint_metric(struct perf_script *script,2168 struct thread *thread,2169 struct evsel *evsel,2170 struct perf_sample *sample,2171 FILE *fp)2172{2173 struct evsel *leader = evsel__leader(evsel);2174 struct perf_stat_output_ctx ctx = {2175 .print_metric = script_print_metric,2176 .new_line = script_new_line,2177 .ctx = &(struct metric_ctx) {2178 .sample = sample,2179 .thread = thread,2180 .evsel = evsel,2181 .fp = fp,2182 },2183 .force_header = false,2184 };2185 struct evsel *ev2;2186 u64 val;2187 2188 if (!evsel->stats)2189 evlist__alloc_stats(&stat_config, script->session->evlist, /*alloc_raw=*/false);2190 if (evsel_script(leader)->gnum++ == 0)2191 perf_stat__reset_shadow_stats();2192 val = sample->period * evsel->scale;2193 evsel_script(evsel)->val = val;2194 if (evsel_script(leader)->gnum == leader->core.nr_members) {2195 for_each_group_member (ev2, leader) {2196 perf_stat__print_shadow_stats(&stat_config, ev2,2197 evsel_script(ev2)->val,2198 sample->cpu,2199 &ctx,2200 NULL);2201 }2202 evsel_script(leader)->gnum = 0;2203 }2204}2205 2206static bool show_event(struct perf_sample *sample,2207 struct evsel *evsel,2208 struct thread *thread,2209 struct addr_location *al,2210 struct addr_location *addr_al)2211{2212 int depth = thread_stack__depth(thread, sample->cpu);2213 2214 if (!symbol_conf.graph_function)2215 return true;2216 2217 if (thread__filter(thread)) {2218 if (depth <= thread__filter_entry_depth(thread)) {2219 thread__set_filter(thread, false);2220 return false;2221 }2222 return true;2223 } else {2224 const char *s = symbol_conf.graph_function;2225 u64 ip;2226 const char *name = resolve_branch_sym(sample, evsel, thread, al, addr_al,2227 &ip);2228 unsigned nlen;2229 2230 if (!name)2231 return false;2232 nlen = strlen(name);2233 while (*s) {2234 unsigned len = strcspn(s, ",");2235 if (nlen == len && !strncmp(name, s, len)) {2236 thread__set_filter(thread, true);2237 thread__set_filter_entry_depth(thread, depth);2238 return true;2239 }2240 s += len;2241 if (*s == ',')2242 s++;2243 }2244 return false;2245 }2246}2247 2248static void process_event(struct perf_script *script,2249 struct perf_sample *sample, struct evsel *evsel,2250 struct addr_location *al,2251 struct addr_location *addr_al,2252 struct machine *machine)2253{2254 struct thread *thread = al->thread;2255 struct perf_event_attr *attr = &evsel->core.attr;2256 unsigned int type = output_type(attr->type);2257 struct evsel_script *es = evsel->priv;2258 FILE *fp = es->fp;2259 char str[PAGE_SIZE_NAME_LEN];2260 const char *arch = perf_env__arch(machine->env);2261 2262 if (output[type].fields == 0)2263 return;2264 2265 ++es->samples;2266 2267 perf_sample__fprintf_start(script, sample, thread, evsel,2268 PERF_RECORD_SAMPLE, fp);2269 2270 if (PRINT_FIELD(PERIOD))2271 fprintf(fp, "%10" PRIu64 " ", sample->period);2272 2273 if (PRINT_FIELD(EVNAME)) {2274 const char *evname = evsel__name(evsel);2275 2276 if (!script->name_width)2277 script->name_width = evlist__max_name_len(script->session->evlist);2278 2279 fprintf(fp, "%*s: ", script->name_width, evname ?: "[unknown]");2280 }2281 2282 if (print_flags)2283 perf_sample__fprintf_flags(sample->flags, fp);2284 2285 if (is_bts_event(attr)) {2286 perf_sample__fprintf_bts(sample, evsel, thread, al, addr_al, machine, fp);2287 return;2288 }2289#ifdef HAVE_LIBTRACEEVENT2290 if (PRINT_FIELD(TRACE) && sample->raw_data) {2291 event_format__fprintf(evsel->tp_format, sample->cpu,2292 sample->raw_data, sample->raw_size, fp);2293 }2294#endif2295 if (attr->type == PERF_TYPE_SYNTH && PRINT_FIELD(SYNTH))2296 perf_sample__fprintf_synth(sample, evsel, fp);2297 2298 if (PRINT_FIELD(ADDR))2299 perf_sample__fprintf_addr(sample, thread, attr, fp);2300 2301 if (PRINT_FIELD(DATA_SRC))2302 data_src__fprintf(sample->data_src, fp);2303 2304 if (PRINT_FIELD(WEIGHT))2305 fprintf(fp, "%16" PRIu64, sample->weight);2306 2307 if (PRINT_FIELD(INS_LAT))2308 fprintf(fp, "%16" PRIu16, sample->ins_lat);2309 2310 if (PRINT_FIELD(RETIRE_LAT))2311 fprintf(fp, "%16" PRIu16, sample->retire_lat);2312 2313 if (PRINT_FIELD(CGROUP)) {2314 const char *cgrp_name;2315 struct cgroup *cgrp = cgroup__find(machine->env,2316 sample->cgroup);2317 if (cgrp != NULL)2318 cgrp_name = cgrp->name;2319 else2320 cgrp_name = "unknown";2321 fprintf(fp, " %s", cgrp_name);2322 }2323 2324 if (PRINT_FIELD(IP)) {2325 struct callchain_cursor *cursor = NULL;2326 2327 if (script->stitch_lbr)2328 thread__set_lbr_stitch_enable(al->thread, true);2329 2330 if (symbol_conf.use_callchain && sample->callchain) {2331 cursor = get_tls_callchain_cursor();2332 if (thread__resolve_callchain(al->thread, cursor, evsel,2333 sample, NULL, NULL,2334 scripting_max_stack))2335 cursor = NULL;2336 }2337 fputc(cursor ? '\n' : ' ', fp);2338 sample__fprintf_sym(sample, al, 0, output[type].print_ip_opts, cursor,2339 symbol_conf.bt_stop_list, fp);2340 }2341 2342 if (PRINT_FIELD(IREGS))2343 perf_sample__fprintf_iregs(sample, attr, arch, fp);2344 2345 if (PRINT_FIELD(UREGS))2346 perf_sample__fprintf_uregs(sample, attr, arch, fp);2347 2348 if (PRINT_FIELD(BRSTACK))2349 perf_sample__fprintf_brstack(sample, thread, attr, fp);2350 else if (PRINT_FIELD(BRSTACKSYM))2351 perf_sample__fprintf_brstacksym(sample, thread, attr, fp);2352 else if (PRINT_FIELD(BRSTACKOFF))2353 perf_sample__fprintf_brstackoff(sample, thread, attr, fp);2354 2355 if (evsel__is_bpf_output(evsel) && PRINT_FIELD(BPF_OUTPUT))2356 perf_sample__fprintf_bpf_output(sample, fp);2357 perf_sample__fprintf_insn(sample, evsel, attr, thread, machine, fp, al);2358 2359 if (PRINT_FIELD(PHYS_ADDR))2360 fprintf(fp, "%16" PRIx64, sample->phys_addr);2361 2362 if (PRINT_FIELD(DATA_PAGE_SIZE))2363 fprintf(fp, " %s", get_page_size_name(sample->data_page_size, str));2364 2365 if (PRINT_FIELD(CODE_PAGE_SIZE))2366 fprintf(fp, " %s", get_page_size_name(sample->code_page_size, str));2367 2368 perf_sample__fprintf_ipc(sample, attr, fp);2369 2370 fprintf(fp, "\n");2371 2372 if (PRINT_FIELD(SRCCODE)) {2373 if (map__fprintf_srccode(al->map, al->addr, stdout,2374 thread__srccode_state(thread)))2375 printf("\n");2376 }2377 2378 if (PRINT_FIELD(METRIC))2379 perf_sample__fprint_metric(script, thread, evsel, sample, fp);2380 2381 if (verbose > 0)2382 fflush(fp);2383}2384 2385static struct scripting_ops *scripting_ops;2386 2387static void __process_stat(struct evsel *counter, u64 tstamp)2388{2389 int nthreads = perf_thread_map__nr(counter->core.threads);2390 int idx, thread;2391 struct perf_cpu cpu;2392 static int header_printed;2393 2394 if (!header_printed) {2395 printf("%3s %8s %15s %15s %15s %15s %s\n",2396 "CPU", "THREAD", "VAL", "ENA", "RUN", "TIME", "EVENT");2397 header_printed = 1;2398 }2399 2400 for (thread = 0; thread < nthreads; thread++) {2401 perf_cpu_map__for_each_cpu(cpu, idx, evsel__cpus(counter)) {2402 struct perf_counts_values *counts;2403 2404 counts = perf_counts(counter->counts, idx, thread);2405 2406 printf("%3d %8d %15" PRIu64 " %15" PRIu64 " %15" PRIu64 " %15" PRIu64 " %s\n",2407 cpu.cpu,2408 perf_thread_map__pid(counter->core.threads, thread),2409 counts->val,2410 counts->ena,2411 counts->run,2412 tstamp,2413 evsel__name(counter));2414 }2415 }2416}2417 2418static void process_stat(struct evsel *counter, u64 tstamp)2419{2420 if (scripting_ops && scripting_ops->process_stat)2421 scripting_ops->process_stat(&stat_config, counter, tstamp);2422 else2423 __process_stat(counter, tstamp);2424}2425 2426static void process_stat_interval(u64 tstamp)2427{2428 if (scripting_ops && scripting_ops->process_stat_interval)2429 scripting_ops->process_stat_interval(tstamp);2430}2431 2432static void setup_scripting(void)2433{2434#ifdef HAVE_LIBTRACEEVENT2435 setup_perl_scripting();2436#endif2437 setup_python_scripting();2438}2439 2440static int flush_scripting(void)2441{2442 return scripting_ops ? scripting_ops->flush_script() : 0;2443}2444 2445static int cleanup_scripting(void)2446{2447 pr_debug("\nperf script stopped\n");2448 2449 return scripting_ops ? scripting_ops->stop_script() : 0;2450}2451 2452static bool filter_cpu(struct perf_sample *sample)2453{2454 if (cpu_list && sample->cpu != (u32)-1)2455 return !test_bit(sample->cpu, cpu_bitmap);2456 return false;2457}2458 2459static int process_sample_event(const struct perf_tool *tool,2460 union perf_event *event,2461 struct perf_sample *sample,2462 struct evsel *evsel,2463 struct machine *machine)2464{2465 struct perf_script *scr = container_of(tool, struct perf_script, tool);2466 struct addr_location al;2467 struct addr_location addr_al;2468 int ret = 0;2469 2470 /* Set thread to NULL to indicate addr_al and al are not initialized */2471 addr_location__init(&al);2472 addr_location__init(&addr_al);2473 2474 ret = dlfilter__filter_event_early(dlfilter, event, sample, evsel, machine, &al, &addr_al);2475 if (ret) {2476 if (ret > 0)2477 ret = 0;2478 goto out_put;2479 }2480 2481 if (perf_time__ranges_skip_sample(scr->ptime_range, scr->range_num,2482 sample->time)) {2483 goto out_put;2484 }2485 2486 if (debug_mode) {2487 if (sample->time < last_timestamp) {2488 pr_err("Samples misordered, previous: %" PRIu642489 " this: %" PRIu64 "\n", last_timestamp,2490 sample->time);2491 nr_unordered++;2492 }2493 last_timestamp = sample->time;2494 goto out_put;2495 }2496 2497 if (filter_cpu(sample))2498 goto out_put;2499 2500 if (!al.thread && machine__resolve(machine, &al, sample) < 0) {2501 pr_err("problem processing %d event, skipping it.\n",2502 event->header.type);2503 ret = -1;2504 goto out_put;2505 }2506 2507 if (al.filtered)2508 goto out_put;2509 2510 if (!show_event(sample, evsel, al.thread, &al, &addr_al))2511 goto out_put;2512 2513 if (evswitch__discard(&scr->evswitch, evsel))2514 goto out_put;2515 2516 ret = dlfilter__filter_event(dlfilter, event, sample, evsel, machine, &al, &addr_al);2517 if (ret) {2518 if (ret > 0)2519 ret = 0;2520 goto out_put;2521 }2522 2523 if (scripting_ops) {2524 struct addr_location *addr_al_ptr = NULL;2525 2526 if ((evsel->core.attr.sample_type & PERF_SAMPLE_ADDR) &&2527 sample_addr_correlates_sym(&evsel->core.attr)) {2528 if (!addr_al.thread)2529 thread__resolve(al.thread, &addr_al, sample);2530 addr_al_ptr = &addr_al;2531 }2532 scripting_ops->process_event(event, sample, evsel, &al, addr_al_ptr);2533 } else {2534 process_event(scr, sample, evsel, &al, &addr_al, machine);2535 }2536 2537out_put:2538 addr_location__exit(&addr_al);2539 addr_location__exit(&al);2540 return ret;2541}2542 2543// Used when scr->per_event_dump is not set2544static struct evsel_script es_stdout;2545 2546static int process_attr(const struct perf_tool *tool, union perf_event *event,2547 struct evlist **pevlist)2548{2549 struct perf_script *scr = container_of(tool, struct perf_script, tool);2550 struct evlist *evlist;2551 struct evsel *evsel, *pos;2552 u64 sample_type;2553 int err;2554 2555 err = perf_event__process_attr(tool, event, pevlist);2556 if (err)2557 return err;2558 2559 evlist = *pevlist;2560 evsel = evlist__last(*pevlist);2561 2562 if (!evsel->priv) {2563 if (scr->per_event_dump) {2564 evsel->priv = evsel_script__new(evsel, scr->session->data);2565 if (!evsel->priv)2566 return -ENOMEM;2567 } else { // Replicate what is done in perf_script__setup_per_event_dump()2568 es_stdout.fp = stdout;2569 evsel->priv = &es_stdout;2570 }2571 }2572 2573 if (evsel->core.attr.type >= PERF_TYPE_MAX &&2574 evsel->core.attr.type != PERF_TYPE_SYNTH)2575 return 0;2576 2577 evlist__for_each_entry(evlist, pos) {2578 if (pos->core.attr.type == evsel->core.attr.type && pos != evsel)2579 return 0;2580 }2581 2582 if (evsel->core.attr.sample_type) {2583 err = evsel__check_attr(evsel, scr->session);2584 if (err)2585 return err;2586 }2587 2588 /*2589 * Check if we need to enable callchains based2590 * on events sample_type.2591 */2592 sample_type = evlist__combined_sample_type(evlist);2593 callchain_param_setup(sample_type, perf_env__arch((*pevlist)->env));2594 2595 /* Enable fields for callchain entries */2596 if (symbol_conf.use_callchain &&2597 (sample_type & PERF_SAMPLE_CALLCHAIN ||2598 sample_type & PERF_SAMPLE_BRANCH_STACK ||2599 (sample_type & PERF_SAMPLE_REGS_USER &&2600 sample_type & PERF_SAMPLE_STACK_USER))) {2601 int type = output_type(evsel->core.attr.type);2602 2603 if (!(output[type].user_unset_fields & PERF_OUTPUT_IP))2604 output[type].fields |= PERF_OUTPUT_IP;2605 if (!(output[type].user_unset_fields & PERF_OUTPUT_SYM))2606 output[type].fields |= PERF_OUTPUT_SYM;2607 }2608 set_print_ip_opts(&evsel->core.attr);2609 return 0;2610}2611 2612static int print_event_with_time(const struct perf_tool *tool,2613 union perf_event *event,2614 struct perf_sample *sample,2615 struct machine *machine,2616 pid_t pid, pid_t tid, u64 timestamp)2617{2618 struct perf_script *script = container_of(tool, struct perf_script, tool);2619 struct perf_session *session = script->session;2620 struct evsel *evsel = evlist__id2evsel(session->evlist, sample->id);2621 struct thread *thread = NULL;2622 2623 if (evsel && !evsel->core.attr.sample_id_all) {2624 sample->cpu = 0;2625 sample->time = timestamp;2626 sample->pid = pid;2627 sample->tid = tid;2628 }2629 2630 if (filter_cpu(sample))2631 return 0;2632 2633 if (tid != -1)2634 thread = machine__findnew_thread(machine, pid, tid);2635 2636 if (evsel) {2637 perf_sample__fprintf_start(script, sample, thread, evsel,2638 event->header.type, stdout);2639 }2640 2641 perf_event__fprintf(event, machine, stdout);2642 2643 thread__put(thread);2644 2645 return 0;2646}2647 2648static int print_event(const struct perf_tool *tool, union perf_event *event,2649 struct perf_sample *sample, struct machine *machine,2650 pid_t pid, pid_t tid)2651{2652 return print_event_with_time(tool, event, sample, machine, pid, tid, 0);2653}2654 2655static int process_comm_event(const struct perf_tool *tool,2656 union perf_event *event,2657 struct perf_sample *sample,2658 struct machine *machine)2659{2660 if (perf_event__process_comm(tool, event, sample, machine) < 0)2661 return -1;2662 2663 return print_event(tool, event, sample, machine, event->comm.pid,2664 event->comm.tid);2665}2666 2667static int process_namespaces_event(const struct perf_tool *tool,2668 union perf_event *event,2669 struct perf_sample *sample,2670 struct machine *machine)2671{2672 if (perf_event__process_namespaces(tool, event, sample, machine) < 0)2673 return -1;2674 2675 return print_event(tool, event, sample, machine, event->namespaces.pid,2676 event->namespaces.tid);2677}2678 2679static int process_cgroup_event(const struct perf_tool *tool,2680 union perf_event *event,2681 struct perf_sample *sample,2682 struct machine *machine)2683{2684 if (perf_event__process_cgroup(tool, event, sample, machine) < 0)2685 return -1;2686 2687 return print_event(tool, event, sample, machine, sample->pid,2688 sample->tid);2689}2690 2691static int process_fork_event(const struct perf_tool *tool,2692 union perf_event *event,2693 struct perf_sample *sample,2694 struct machine *machine)2695{2696 if (perf_event__process_fork(tool, event, sample, machine) < 0)2697 return -1;2698 2699 return print_event_with_time(tool, event, sample, machine,2700 event->fork.pid, event->fork.tid,2701 event->fork.time);2702}2703static int process_exit_event(const struct perf_tool *tool,2704 union perf_event *event,2705 struct perf_sample *sample,2706 struct machine *machine)2707{2708 /* Print before 'exit' deletes anything */2709 if (print_event_with_time(tool, event, sample, machine, event->fork.pid,2710 event->fork.tid, event->fork.time))2711 return -1;2712 2713 return perf_event__process_exit(tool, event, sample, machine);2714}2715 2716static int process_mmap_event(const struct perf_tool *tool,2717 union perf_event *event,2718 struct perf_sample *sample,2719 struct machine *machine)2720{2721 if (perf_event__process_mmap(tool, event, sample, machine) < 0)2722 return -1;2723 2724 return print_event(tool, event, sample, machine, event->mmap.pid,2725 event->mmap.tid);2726}2727 2728static int process_mmap2_event(const struct perf_tool *tool,2729 union perf_event *event,2730 struct perf_sample *sample,2731 struct machine *machine)2732{2733 if (perf_event__process_mmap2(tool, event, sample, machine) < 0)2734 return -1;2735 2736 return print_event(tool, event, sample, machine, event->mmap2.pid,2737 event->mmap2.tid);2738}2739 2740static int process_switch_event(const struct perf_tool *tool,2741 union perf_event *event,2742 struct perf_sample *sample,2743 struct machine *machine)2744{2745 struct perf_script *script = container_of(tool, struct perf_script, tool);2746 2747 if (perf_event__process_switch(tool, event, sample, machine) < 0)2748 return -1;2749 2750 if (scripting_ops && scripting_ops->process_switch && !filter_cpu(sample))2751 scripting_ops->process_switch(event, sample, machine);2752 2753 if (!script->show_switch_events)2754 return 0;2755 2756 return print_event(tool, event, sample, machine, sample->pid,2757 sample->tid);2758}2759 2760static int process_auxtrace_error(struct perf_session *session,2761 union perf_event *event)2762{2763 if (scripting_ops && scripting_ops->process_auxtrace_error) {2764 scripting_ops->process_auxtrace_error(session, event);2765 return 0;2766 }2767 2768 return perf_event__process_auxtrace_error(session, event);2769}2770 2771static int2772process_lost_event(const struct perf_tool *tool,2773 union perf_event *event,2774 struct perf_sample *sample,2775 struct machine *machine)2776{2777 return print_event(tool, event, sample, machine, sample->pid,2778 sample->tid);2779}2780 2781static int2782process_throttle_event(const struct perf_tool *tool __maybe_unused,2783 union perf_event *event,2784 struct perf_sample *sample,2785 struct machine *machine)2786{2787 if (scripting_ops && scripting_ops->process_throttle)2788 scripting_ops->process_throttle(event, sample, machine);2789 return 0;2790}2791 2792static int2793process_finished_round_event(const struct perf_tool *tool __maybe_unused,2794 union perf_event *event,2795 struct ordered_events *oe __maybe_unused)2796 2797{2798 perf_event__fprintf(event, NULL, stdout);2799 return 0;2800}2801 2802static int2803process_bpf_events(const struct perf_tool *tool __maybe_unused,2804 union perf_event *event,2805 struct perf_sample *sample,2806 struct machine *machine)2807{2808 if (machine__process_ksymbol(machine, event, sample) < 0)2809 return -1;2810 2811 return print_event(tool, event, sample, machine, sample->pid,2812 sample->tid);2813}2814 2815static int process_text_poke_events(const struct perf_tool *tool,2816 union perf_event *event,2817 struct perf_sample *sample,2818 struct machine *machine)2819{2820 if (perf_event__process_text_poke(tool, event, sample, machine) < 0)2821 return -1;2822 2823 return print_event(tool, event, sample, machine, sample->pid,2824 sample->tid);2825}2826 2827static void sig_handler(int sig __maybe_unused)2828{2829 session_done = 1;2830}2831 2832static void perf_script__fclose_per_event_dump(struct perf_script *script)2833{2834 struct evlist *evlist = script->session->evlist;2835 struct evsel *evsel;2836 2837 evlist__for_each_entry(evlist, evsel) {2838 if (!evsel->priv)2839 break;2840 evsel_script__delete(evsel->priv);2841 evsel->priv = NULL;2842 }2843}2844 2845static int perf_script__fopen_per_event_dump(struct perf_script *script)2846{2847 struct evsel *evsel;2848 2849 evlist__for_each_entry(script->session->evlist, evsel) {2850 /*2851 * Already setup? I.e. we may be called twice in cases like2852 * Intel PT, one for the intel_pt// and dummy events, then2853 * for the evsels synthesized from the auxtrace info.2854 *2855 * Ses perf_script__process_auxtrace_info.2856 */2857 if (evsel->priv != NULL)2858 continue;2859 2860 evsel->priv = evsel_script__new(evsel, script->session->data);2861 if (evsel->priv == NULL)2862 goto out_err_fclose;2863 }2864 2865 return 0;2866 2867out_err_fclose:2868 perf_script__fclose_per_event_dump(script);2869 return -1;2870}2871 2872static int perf_script__setup_per_event_dump(struct perf_script *script)2873{2874 struct evsel *evsel;2875 2876 if (script->per_event_dump)2877 return perf_script__fopen_per_event_dump(script);2878 2879 es_stdout.fp = stdout;2880 2881 evlist__for_each_entry(script->session->evlist, evsel)2882 evsel->priv = &es_stdout;2883 2884 return 0;2885}2886 2887static void perf_script__exit_per_event_dump_stats(struct perf_script *script)2888{2889 struct evsel *evsel;2890 2891 evlist__for_each_entry(script->session->evlist, evsel) {2892 struct evsel_script *es = evsel->priv;2893 2894 evsel_script__fprintf(es, stdout);2895 evsel_script__delete(es);2896 evsel->priv = NULL;2897 }2898}2899 2900static void perf_script__exit(struct perf_script *script)2901{2902 perf_thread_map__put(script->threads);2903 perf_cpu_map__put(script->cpus);2904}2905 2906static int __cmd_script(struct perf_script *script)2907{2908 int ret;2909 2910 signal(SIGINT, sig_handler);2911 2912 /* override event processing functions */2913 if (script->show_task_events) {2914 script->tool.comm = process_comm_event;2915 script->tool.fork = process_fork_event;2916 script->tool.exit = process_exit_event;2917 }2918 if (script->show_mmap_events) {2919 script->tool.mmap = process_mmap_event;2920 script->tool.mmap2 = process_mmap2_event;2921 }2922 if (script->show_switch_events || (scripting_ops && scripting_ops->process_switch))2923 script->tool.context_switch = process_switch_event;2924 if (scripting_ops && scripting_ops->process_auxtrace_error)2925 script->tool.auxtrace_error = process_auxtrace_error;2926 if (script->show_namespace_events)2927 script->tool.namespaces = process_namespaces_event;2928 if (script->show_cgroup_events)2929 script->tool.cgroup = process_cgroup_event;2930 if (script->show_lost_events)2931 script->tool.lost = process_lost_event;2932 if (script->show_round_events) {2933 script->tool.ordered_events = false;2934 script->tool.finished_round = process_finished_round_event;2935 }2936 if (script->show_bpf_events) {2937 script->tool.ksymbol = process_bpf_events;2938 script->tool.bpf = process_bpf_events;2939 }2940 if (script->show_text_poke_events) {2941 script->tool.ksymbol = process_bpf_events;2942 script->tool.text_poke = process_text_poke_events;2943 }2944 2945 if (perf_script__setup_per_event_dump(script)) {2946 pr_err("Couldn't create the per event dump files\n");2947 return -1;2948 }2949 2950 ret = perf_session__process_events(script->session);2951 2952 if (script->per_event_dump)2953 perf_script__exit_per_event_dump_stats(script);2954 2955 if (debug_mode)2956 pr_err("Misordered timestamps: %" PRIu64 "\n", nr_unordered);2957 2958 return ret;2959}2960 2961struct script_spec {2962 struct list_head node;2963 struct scripting_ops *ops;2964 char spec[];2965};2966 2967static LIST_HEAD(script_specs);2968 2969static struct script_spec *script_spec__new(const char *spec,2970 struct scripting_ops *ops)2971{2972 struct script_spec *s = malloc(sizeof(*s) + strlen(spec) + 1);2973 2974 if (s != NULL) {2975 strcpy(s->spec, spec);2976 s->ops = ops;2977 }2978 2979 return s;2980}2981 2982static void script_spec__add(struct script_spec *s)2983{2984 list_add_tail(&s->node, &script_specs);2985}2986 2987static struct script_spec *script_spec__find(const char *spec)2988{2989 struct script_spec *s;2990 2991 list_for_each_entry(s, &script_specs, node)2992 if (strcasecmp(s->spec, spec) == 0)2993 return s;2994 return NULL;2995}2996 2997int script_spec_register(const char *spec, struct scripting_ops *ops)2998{2999 struct script_spec *s;3000 3001 s = script_spec__find(spec);3002 if (s)3003 return -1;3004 3005 s = script_spec__new(spec, ops);3006 if (!s)3007 return -1;3008 else3009 script_spec__add(s);3010 3011 return 0;3012}3013 3014static struct scripting_ops *script_spec__lookup(const char *spec)3015{3016 struct script_spec *s = script_spec__find(spec);3017 if (!s)3018 return NULL;3019 3020 return s->ops;3021}3022 3023static void list_available_languages(void)3024{3025 struct script_spec *s;3026 3027 fprintf(stderr, "\n");3028 fprintf(stderr, "Scripting language extensions (used in "3029 "perf script -s [spec:]script.[spec]):\n\n");3030 3031 list_for_each_entry(s, &script_specs, node)3032 fprintf(stderr, " %-42s [%s]\n", s->spec, s->ops->name);3033 3034 fprintf(stderr, "\n");3035}3036 3037/* Find script file relative to current directory or exec path */3038static char *find_script(const char *script)3039{3040 char path[PATH_MAX];3041 3042 if (!scripting_ops) {3043 const char *ext = strrchr(script, '.');3044 3045 if (!ext)3046 return NULL;3047 3048 scripting_ops = script_spec__lookup(++ext);3049 if (!scripting_ops)3050 return NULL;3051 }3052 3053 if (access(script, R_OK)) {3054 char *exec_path = get_argv_exec_path();3055 3056 if (!exec_path)3057 return NULL;3058 snprintf(path, sizeof(path), "%s/scripts/%s/%s",3059 exec_path, scripting_ops->dirname, script);3060 free(exec_path);3061 script = path;3062 if (access(script, R_OK))3063 return NULL;3064 }3065 return strdup(script);3066}3067 3068static int parse_scriptname(const struct option *opt __maybe_unused,3069 const char *str, int unset __maybe_unused)3070{3071 char spec[PATH_MAX];3072 const char *script, *ext;3073 int len;3074 3075 if (strcmp(str, "lang") == 0) {3076 list_available_languages();3077 exit(0);3078 }3079 3080 script = strchr(str, ':');3081 if (script) {3082 len = script - str;3083 if (len >= PATH_MAX) {3084 fprintf(stderr, "invalid language specifier");3085 return -1;3086 }3087 strncpy(spec, str, len);3088 spec[len] = '\0';3089 scripting_ops = script_spec__lookup(spec);3090 if (!scripting_ops) {3091 fprintf(stderr, "invalid language specifier");3092 return -1;3093 }3094 script++;3095 } else {3096 script = str;3097 ext = strrchr(script, '.');3098 if (!ext) {3099 fprintf(stderr, "invalid script extension");3100 return -1;3101 }3102 scripting_ops = script_spec__lookup(++ext);3103 if (!scripting_ops) {3104 fprintf(stderr, "invalid script extension");3105 return -1;3106 }3107 }3108 3109 script_name = find_script(script);3110 if (!script_name)3111 script_name = strdup(script);3112 3113 return 0;3114}3115 3116static int parse_output_fields(const struct option *opt __maybe_unused,3117 const char *arg, int unset __maybe_unused)3118{3119 char *tok, *strtok_saveptr = NULL;3120 int i, imax = ARRAY_SIZE(all_output_options);3121 int j;3122 int rc = 0;3123 char *str = strdup(arg);3124 int type = -1;3125 enum { DEFAULT, SET, ADD, REMOVE } change = DEFAULT;3126 3127 if (!str)3128 return -ENOMEM;3129 3130 /* first word can state for which event type the user is specifying3131 * the fields. If no type exists, the specified fields apply to all3132 * event types found in the file minus the invalid fields for a type.3133 */3134 tok = strchr(str, ':');3135 if (tok) {3136 *tok = '\0';3137 tok++;3138 if (!strcmp(str, "hw"))3139 type = PERF_TYPE_HARDWARE;3140 else if (!strcmp(str, "sw"))3141 type = PERF_TYPE_SOFTWARE;3142 else if (!strcmp(str, "trace"))3143 type = PERF_TYPE_TRACEPOINT;3144 else if (!strcmp(str, "raw"))3145 type = PERF_TYPE_RAW;3146 else if (!strcmp(str, "break"))3147 type = PERF_TYPE_BREAKPOINT;3148 else if (!strcmp(str, "synth"))3149 type = OUTPUT_TYPE_SYNTH;3150 else {3151 fprintf(stderr, "Invalid event type in field string.\n");3152 rc = -EINVAL;3153 goto out;3154 }3155 3156 if (output[type].user_set)3157 pr_warning("Overriding previous field request for %s events.\n",3158 event_type(type));3159 3160 /* Don't override defaults for +- */3161 if (strchr(tok, '+') || strchr(tok, '-'))3162 goto parse;3163 3164 output[type].fields = 0;3165 output[type].user_set = true;3166 output[type].wildcard_set = false;3167 3168 } else {3169 tok = str;3170 if (strlen(str) == 0) {3171 fprintf(stderr,3172 "Cannot set fields to 'none' for all event types.\n");3173 rc = -EINVAL;3174 goto out;3175 }3176 3177 /* Don't override defaults for +- */3178 if (strchr(str, '+') || strchr(str, '-'))3179 goto parse;3180 3181 if (output_set_by_user())3182 pr_warning("Overriding previous field request for all events.\n");3183 3184 for (j = 0; j < OUTPUT_TYPE_MAX; ++j) {3185 output[j].fields = 0;3186 output[j].user_set = true;3187 output[j].wildcard_set = true;3188 }3189 }3190 3191parse:3192 for (tok = strtok_r(tok, ",", &strtok_saveptr); tok; tok = strtok_r(NULL, ",", &strtok_saveptr)) {3193 if (*tok == '+') {3194 if (change == SET)3195 goto out_badmix;3196 change = ADD;3197 tok++;3198 } else if (*tok == '-') {3199 if (change == SET)3200 goto out_badmix;3201 change = REMOVE;3202 tok++;3203 } else {3204 if (change != SET && change != DEFAULT)3205 goto out_badmix;3206 change = SET;3207 }3208 3209 for (i = 0; i < imax; ++i) {3210 if (strcmp(tok, all_output_options[i].str) == 0)3211 break;3212 }3213 if (i == imax && strcmp(tok, "flags") == 0) {3214 print_flags = change != REMOVE;3215 continue;3216 }3217 if (i == imax) {3218 fprintf(stderr, "Invalid field requested.\n");3219 rc = -EINVAL;3220 goto out;3221 }3222#ifndef HAVE_LIBCAPSTONE_SUPPORT3223 if (change != REMOVE && strcmp(tok, "disasm") == 0) {3224 fprintf(stderr, "Field \"disasm\" requires perf to be built with libcapstone support.\n");3225 rc = -EINVAL;3226 goto out;3227 }3228#endif3229 3230 if (type == -1) {3231 /* add user option to all events types for3232 * which it is valid3233 */3234 for (j = 0; j < OUTPUT_TYPE_MAX; ++j) {3235 if (output[j].invalid_fields & all_output_options[i].field) {3236 pr_warning("\'%s\' not valid for %s events. Ignoring.\n",3237 all_output_options[i].str, event_type(j));3238 } else {3239 if (change == REMOVE) {3240 output[j].fields &= ~all_output_options[i].field;3241 output[j].user_set_fields &= ~all_output_options[i].field;3242 output[j].user_unset_fields |= all_output_options[i].field;3243 } else {3244 output[j].fields |= all_output_options[i].field;3245 output[j].user_set_fields |= all_output_options[i].field;3246 output[j].user_unset_fields &= ~all_output_options[i].field;3247 }3248 output[j].user_set = true;3249 output[j].wildcard_set = true;3250 }3251 }3252 } else {3253 if (output[type].invalid_fields & all_output_options[i].field) {3254 fprintf(stderr, "\'%s\' not valid for %s events.\n",3255 all_output_options[i].str, event_type(type));3256 3257 rc = -EINVAL;3258 goto out;3259 }3260 if (change == REMOVE)3261 output[type].fields &= ~all_output_options[i].field;3262 else3263 output[type].fields |= all_output_options[i].field;3264 output[type].user_set = true;3265 output[type].wildcard_set = true;3266 }3267 }3268 3269 if (type >= 0) {3270 if (output[type].fields == 0) {3271 pr_debug("No fields requested for %s type. "3272 "Events will not be displayed.\n", event_type(type));3273 }3274 }3275 goto out;3276 3277out_badmix:3278 fprintf(stderr, "Cannot mix +-field with overridden fields\n");3279 rc = -EINVAL;3280out:3281 free(str);3282 return rc;3283}3284 3285#define for_each_lang(scripts_path, scripts_dir, lang_dirent) \3286 while ((lang_dirent = readdir(scripts_dir)) != NULL) \3287 if ((lang_dirent->d_type == DT_DIR || \3288 (lang_dirent->d_type == DT_UNKNOWN && \3289 is_directory(scripts_path, lang_dirent))) && \3290 (strcmp(lang_dirent->d_name, ".")) && \3291 (strcmp(lang_dirent->d_name, "..")))3292 3293#define for_each_script(lang_path, lang_dir, script_dirent) \3294 while ((script_dirent = readdir(lang_dir)) != NULL) \3295 if (script_dirent->d_type != DT_DIR && \3296 (script_dirent->d_type != DT_UNKNOWN || \3297 !is_directory(lang_path, script_dirent)))3298 3299 3300#define RECORD_SUFFIX "-record"3301#define REPORT_SUFFIX "-report"3302 3303struct script_desc {3304 struct list_head node;3305 char *name;3306 char *half_liner;3307 char *args;3308};3309 3310static LIST_HEAD(script_descs);3311 3312static struct script_desc *script_desc__new(const char *name)3313{3314 struct script_desc *s = zalloc(sizeof(*s));3315 3316 if (s != NULL && name)3317 s->name = strdup(name);3318 3319 return s;3320}3321 3322static void script_desc__delete(struct script_desc *s)3323{3324 zfree(&s->name);3325 zfree(&s->half_liner);3326 zfree(&s->args);3327 free(s);3328}3329 3330static void script_desc__add(struct script_desc *s)3331{3332 list_add_tail(&s->node, &script_descs);3333}3334 3335static struct script_desc *script_desc__find(const char *name)3336{3337 struct script_desc *s;3338 3339 list_for_each_entry(s, &script_descs, node)3340 if (strcasecmp(s->name, name) == 0)3341 return s;3342 return NULL;3343}3344 3345static struct script_desc *script_desc__findnew(const char *name)3346{3347 struct script_desc *s = script_desc__find(name);3348 3349 if (s)3350 return s;3351 3352 s = script_desc__new(name);3353 if (!s)3354 return NULL;3355 3356 script_desc__add(s);3357 3358 return s;3359}3360 3361static const char *ends_with(const char *str, const char *suffix)3362{3363 size_t suffix_len = strlen(suffix);3364 const char *p = str;3365 3366 if (strlen(str) > suffix_len) {3367 p = str + strlen(str) - suffix_len;3368 if (!strncmp(p, suffix, suffix_len))3369 return p;3370 }3371 3372 return NULL;3373}3374 3375static int read_script_info(struct script_desc *desc, const char *filename)3376{3377 char line[BUFSIZ], *p;3378 FILE *fp;3379 3380 fp = fopen(filename, "r");3381 if (!fp)3382 return -1;3383 3384 while (fgets(line, sizeof(line), fp)) {3385 p = skip_spaces(line);3386 if (strlen(p) == 0)3387 continue;3388 if (*p != '#')3389 continue;3390 p++;3391 if (strlen(p) && *p == '!')3392 continue;3393 3394 p = skip_spaces(p);3395 if (strlen(p) && p[strlen(p) - 1] == '\n')3396 p[strlen(p) - 1] = '\0';3397 3398 if (!strncmp(p, "description:", strlen("description:"))) {3399 p += strlen("description:");3400 desc->half_liner = strdup(skip_spaces(p));3401 continue;3402 }3403 3404 if (!strncmp(p, "args:", strlen("args:"))) {3405 p += strlen("args:");3406 desc->args = strdup(skip_spaces(p));3407 continue;3408 }3409 }3410 3411 fclose(fp);3412 3413 return 0;3414}3415 3416static char *get_script_root(struct dirent *script_dirent, const char *suffix)3417{3418 char *script_root, *str;3419 3420 script_root = strdup(script_dirent->d_name);3421 if (!script_root)3422 return NULL;3423 3424 str = (char *)ends_with(script_root, suffix);3425 if (!str) {3426 free(script_root);3427 return NULL;3428 }3429 3430 *str = '\0';3431 return script_root;3432}3433 3434static int list_available_scripts(const struct option *opt __maybe_unused,3435 const char *s __maybe_unused,3436 int unset __maybe_unused)3437{3438 struct dirent *script_dirent, *lang_dirent;3439 char *buf, *scripts_path, *script_path, *lang_path, *first_half;3440 DIR *scripts_dir, *lang_dir;3441 struct script_desc *desc;3442 char *script_root;3443 3444 buf = malloc(3 * MAXPATHLEN + BUFSIZ);3445 if (!buf) {3446 pr_err("malloc failed\n");3447 exit(-1);3448 }3449 scripts_path = buf;3450 script_path = buf + MAXPATHLEN;3451 lang_path = buf + 2 * MAXPATHLEN;3452 first_half = buf + 3 * MAXPATHLEN;3453 3454 snprintf(scripts_path, MAXPATHLEN, "%s/scripts", get_argv_exec_path());3455 3456 scripts_dir = opendir(scripts_path);3457 if (!scripts_dir) {3458 fprintf(stdout,3459 "open(%s) failed.\n"3460 "Check \"PERF_EXEC_PATH\" env to set scripts dir.\n",3461 scripts_path);3462 free(buf);3463 exit(-1);3464 }3465 3466 for_each_lang(scripts_path, scripts_dir, lang_dirent) {3467 scnprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path,3468 lang_dirent->d_name);3469 lang_dir = opendir(lang_path);3470 if (!lang_dir)3471 continue;3472 3473 for_each_script(lang_path, lang_dir, script_dirent) {3474 script_root = get_script_root(script_dirent, REPORT_SUFFIX);3475 if (script_root) {3476 desc = script_desc__findnew(script_root);3477 scnprintf(script_path, MAXPATHLEN, "%s/%s",3478 lang_path, script_dirent->d_name);3479 read_script_info(desc, script_path);3480 free(script_root);3481 }3482 }3483 }3484 3485 fprintf(stdout, "List of available trace scripts:\n");3486 list_for_each_entry(desc, &script_descs, node) {3487 sprintf(first_half, "%s %s", desc->name,3488 desc->args ? desc->args : "");3489 fprintf(stdout, " %-36s %s\n", first_half,3490 desc->half_liner ? desc->half_liner : "");3491 }3492 3493 free(buf);3494 exit(0);3495}3496 3497static int add_dlarg(const struct option *opt __maybe_unused,3498 const char *s, int unset __maybe_unused)3499{3500 char *arg = strdup(s);3501 void *a;3502 3503 if (!arg)3504 return -1;3505 3506 a = realloc(dlargv, sizeof(dlargv[0]) * (dlargc + 1));3507 if (!a) {3508 free(arg);3509 return -1;3510 }3511 3512 dlargv = a;3513 dlargv[dlargc++] = arg;3514 3515 return 0;3516}3517 3518static void free_dlarg(void)3519{3520 while (dlargc--)3521 free(dlargv[dlargc]);3522 free(dlargv);3523}3524 3525/*3526 * Some scripts specify the required events in their "xxx-record" file,3527 * this function will check if the events in perf.data match those3528 * mentioned in the "xxx-record".3529 *3530 * Fixme: All existing "xxx-record" are all in good formats "-e event ",3531 * which is covered well now. And new parsing code should be added to3532 * cover the future complex formats like event groups etc.3533 */3534static int check_ev_match(char *dir_name, char *scriptname,3535 struct perf_session *session)3536{3537 char filename[MAXPATHLEN], evname[128];3538 char line[BUFSIZ], *p;3539 struct evsel *pos;3540 int match, len;3541 FILE *fp;3542 3543 scnprintf(filename, MAXPATHLEN, "%s/bin/%s-record", dir_name, scriptname);3544 3545 fp = fopen(filename, "r");3546 if (!fp)3547 return -1;3548 3549 while (fgets(line, sizeof(line), fp)) {3550 p = skip_spaces(line);3551 if (*p == '#')3552 continue;3553 3554 while (strlen(p)) {3555 p = strstr(p, "-e");3556 if (!p)3557 break;3558 3559 p += 2;3560 p = skip_spaces(p);3561 len = strcspn(p, " \t");3562 if (!len)3563 break;3564 3565 snprintf(evname, len + 1, "%s", p);3566 3567 match = 0;3568 evlist__for_each_entry(session->evlist, pos) {3569 if (evsel__name_is(pos, evname)) {3570 match = 1;3571 break;3572 }3573 }3574 3575 if (!match) {3576 fclose(fp);3577 return -1;3578 }3579 }3580 }3581 3582 fclose(fp);3583 return 0;3584}3585 3586/*3587 * Return -1 if none is found, otherwise the actual scripts number.3588 *3589 * Currently the only user of this function is the script browser, which3590 * will list all statically runnable scripts, select one, execute it and3591 * show the output in a perf browser.3592 */3593int find_scripts(char **scripts_array, char **scripts_path_array, int num,3594 int pathlen)3595{3596 struct dirent *script_dirent, *lang_dirent;3597 char scripts_path[MAXPATHLEN], lang_path[MAXPATHLEN];3598 DIR *scripts_dir, *lang_dir;3599 struct perf_session *session;3600 struct perf_data data = {3601 .path = input_name,3602 .mode = PERF_DATA_MODE_READ,3603 };3604 char *temp;3605 int i = 0;3606 3607 session = perf_session__new(&data, NULL);3608 if (IS_ERR(session))3609 return PTR_ERR(session);3610 3611 snprintf(scripts_path, MAXPATHLEN, "%s/scripts", get_argv_exec_path());3612 3613 scripts_dir = opendir(scripts_path);3614 if (!scripts_dir) {3615 perf_session__delete(session);3616 return -1;3617 }3618 3619 for_each_lang(scripts_path, scripts_dir, lang_dirent) {3620 scnprintf(lang_path, MAXPATHLEN, "%s/%s", scripts_path,3621 lang_dirent->d_name);3622#ifndef HAVE_LIBPERL_SUPPORT3623 if (strstr(lang_path, "perl"))3624 continue;3625#endif3626#ifndef HAVE_LIBPYTHON_SUPPORT3627 if (strstr(lang_path, "python"))3628 continue;3629#endif3630 3631 lang_dir = opendir(lang_path);3632 if (!lang_dir)3633 continue;3634 3635 for_each_script(lang_path, lang_dir, script_dirent) {3636 /* Skip those real time scripts: xxxtop.p[yl] */3637 if (strstr(script_dirent->d_name, "top."))3638 continue;3639 if (i >= num)3640 break;3641 snprintf(scripts_path_array[i], pathlen, "%s/%s",3642 lang_path,3643 script_dirent->d_name);3644 temp = strchr(script_dirent->d_name, '.');3645 snprintf(scripts_array[i],3646 (temp - script_dirent->d_name) + 1,3647 "%s", script_dirent->d_name);3648 3649 if (check_ev_match(lang_path,3650 scripts_array[i], session))3651 continue;3652 3653 i++;3654 }3655 closedir(lang_dir);3656 }3657 3658 closedir(scripts_dir);3659 perf_session__delete(session);3660 return i;3661}3662 3663static char *get_script_path(const char *script_root, const char *suffix)3664{3665 struct dirent *script_dirent, *lang_dirent;3666 char scripts_path[MAXPATHLEN];3667 char script_path[MAXPATHLEN];3668 DIR *scripts_dir, *lang_dir;3669 char lang_path[MAXPATHLEN];3670 char *__script_root;3671 3672 snprintf(scripts_path, MAXPATHLEN, "%s/scripts", get_argv_exec_path());3673 3674 scripts_dir = opendir(scripts_path);3675 if (!scripts_dir)3676 return NULL;3677 3678 for_each_lang(scripts_path, scripts_dir, lang_dirent) {3679 scnprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path,3680 lang_dirent->d_name);3681 lang_dir = opendir(lang_path);3682 if (!lang_dir)3683 continue;3684 3685 for_each_script(lang_path, lang_dir, script_dirent) {3686 __script_root = get_script_root(script_dirent, suffix);3687 if (__script_root && !strcmp(script_root, __script_root)) {3688 free(__script_root);3689 closedir(scripts_dir);3690 scnprintf(script_path, MAXPATHLEN, "%s/%s",3691 lang_path, script_dirent->d_name);3692 closedir(lang_dir);3693 return strdup(script_path);3694 }3695 free(__script_root);3696 }3697 closedir(lang_dir);3698 }3699 closedir(scripts_dir);3700 3701 return NULL;3702}3703 3704static bool is_top_script(const char *script_path)3705{3706 return ends_with(script_path, "top") != NULL;3707}3708 3709static int has_required_arg(char *script_path)3710{3711 struct script_desc *desc;3712 int n_args = 0;3713 char *p;3714 3715 desc = script_desc__new(NULL);3716 3717 if (read_script_info(desc, script_path))3718 goto out;3719 3720 if (!desc->args)3721 goto out;3722 3723 for (p = desc->args; *p; p++)3724 if (*p == '<')3725 n_args++;3726out:3727 script_desc__delete(desc);3728 3729 return n_args;3730}3731 3732static int have_cmd(int argc, const char **argv)3733{3734 char **__argv = malloc(sizeof(const char *) * argc);3735 3736 if (!__argv) {3737 pr_err("malloc failed\n");3738 return -1;3739 }3740 3741 memcpy(__argv, argv, sizeof(const char *) * argc);3742 argc = parse_options(argc, (const char **)__argv, record_options,3743 NULL, PARSE_OPT_STOP_AT_NON_OPTION);3744 free(__argv);3745 3746 system_wide = (argc == 0);3747 3748 return 0;3749}3750 3751static void script__setup_sample_type(struct perf_script *script)3752{3753 struct perf_session *session = script->session;3754 u64 sample_type = evlist__combined_sample_type(session->evlist);3755 3756 callchain_param_setup(sample_type, perf_env__arch(session->machines.host.env));3757 3758 if (script->stitch_lbr && (callchain_param.record_mode != CALLCHAIN_LBR)) {3759 pr_warning("Can't find LBR callchain. Switch off --stitch-lbr.\n"3760 "Please apply --call-graph lbr when recording.\n");3761 script->stitch_lbr = false;3762 }3763}3764 3765static int process_stat_round_event(struct perf_session *session,3766 union perf_event *event)3767{3768 struct perf_record_stat_round *round = &event->stat_round;3769 struct evsel *counter;3770 3771 evlist__for_each_entry(session->evlist, counter) {3772 perf_stat_process_counter(&stat_config, counter);3773 process_stat(counter, round->time);3774 }3775 3776 process_stat_interval(round->time);3777 return 0;3778}3779 3780static int process_stat_config_event(struct perf_session *session __maybe_unused,3781 union perf_event *event)3782{3783 perf_event__read_stat_config(&stat_config, &event->stat_config);3784 3785 /*3786 * Aggregation modes are not used since post-processing scripts are3787 * supposed to take care of such requirements3788 */3789 stat_config.aggr_mode = AGGR_NONE;3790 3791 return 0;3792}3793 3794static int set_maps(struct perf_script *script)3795{3796 struct evlist *evlist = script->session->evlist;3797 3798 if (!script->cpus || !script->threads)3799 return 0;3800 3801 if (WARN_ONCE(script->allocated, "stats double allocation\n"))3802 return -EINVAL;3803 3804 perf_evlist__set_maps(&evlist->core, script->cpus, script->threads);3805 3806 if (evlist__alloc_stats(&stat_config, evlist, /*alloc_raw=*/true))3807 return -ENOMEM;3808 3809 script->allocated = true;3810 return 0;3811}3812 3813static3814int process_thread_map_event(struct perf_session *session,3815 union perf_event *event)3816{3817 const struct perf_tool *tool = session->tool;3818 struct perf_script *script = container_of(tool, struct perf_script, tool);3819 3820 if (dump_trace)3821 perf_event__fprintf_thread_map(event, stdout);3822 3823 if (script->threads) {3824 pr_warning("Extra thread map event, ignoring.\n");3825 return 0;3826 }3827 3828 script->threads = thread_map__new_event(&event->thread_map);3829 if (!script->threads)3830 return -ENOMEM;3831 3832 return set_maps(script);3833}3834 3835static3836int process_cpu_map_event(struct perf_session *session,3837 union perf_event *event)3838{3839 const struct perf_tool *tool = session->tool;3840 struct perf_script *script = container_of(tool, struct perf_script, tool);3841 3842 if (dump_trace)3843 perf_event__fprintf_cpu_map(event, stdout);3844 3845 if (script->cpus) {3846 pr_warning("Extra cpu map event, ignoring.\n");3847 return 0;3848 }3849 3850 script->cpus = cpu_map__new_data(&event->cpu_map.data);3851 if (!script->cpus)3852 return -ENOMEM;3853 3854 return set_maps(script);3855}3856 3857static int process_feature_event(struct perf_session *session,3858 union perf_event *event)3859{3860 if (event->feat.feat_id < HEADER_LAST_FEATURE)3861 return perf_event__process_feature(session, event);3862 return 0;3863}3864 3865#ifdef HAVE_AUXTRACE_SUPPORT3866static int perf_script__process_auxtrace_info(struct perf_session *session,3867 union perf_event *event)3868{3869 int ret = perf_event__process_auxtrace_info(session, event);3870 3871 if (ret == 0) {3872 const struct perf_tool *tool = session->tool;3873 struct perf_script *script = container_of(tool, struct perf_script, tool);3874 3875 ret = perf_script__setup_per_event_dump(script);3876 }3877 3878 return ret;3879}3880#else3881#define perf_script__process_auxtrace_info 03882#endif3883 3884static int parse_insn_trace(const struct option *opt __maybe_unused,3885 const char *str, int unset __maybe_unused)3886{3887 const char *fields = "+insn,-event,-period";3888 int ret;3889 3890 if (str) {3891 if (strcmp(str, "disasm") == 0)3892 fields = "+disasm,-event,-period";3893 else if (strlen(str) != 0 && strcmp(str, "raw") != 0) {3894 fprintf(stderr, "Only accept raw|disasm\n");3895 return -EINVAL;3896 }3897 }3898 3899 ret = parse_output_fields(NULL, fields, 0);3900 if (ret < 0)3901 return ret;3902 3903 itrace_parse_synth_opts(opt, "i0nse", 0);3904 symbol_conf.nanosecs = true;3905 return 0;3906}3907 3908static int parse_xed(const struct option *opt __maybe_unused,3909 const char *str __maybe_unused,3910 int unset __maybe_unused)3911{3912 if (isatty(1))3913 force_pager("xed -F insn: -A -64 | less");3914 else3915 force_pager("xed -F insn: -A -64");3916 return 0;3917}3918 3919static int parse_call_trace(const struct option *opt __maybe_unused,3920 const char *str __maybe_unused,3921 int unset __maybe_unused)3922{3923 parse_output_fields(NULL, "-ip,-addr,-event,-period,+callindent", 0);3924 itrace_parse_synth_opts(opt, "cewp", 0);3925 symbol_conf.nanosecs = true;3926 symbol_conf.pad_output_len_dso = 50;3927 return 0;3928}3929 3930static int parse_callret_trace(const struct option *opt __maybe_unused,3931 const char *str __maybe_unused,3932 int unset __maybe_unused)3933{3934 parse_output_fields(NULL, "-ip,-addr,-event,-period,+callindent,+flags", 0);3935 itrace_parse_synth_opts(opt, "crewp", 0);3936 symbol_conf.nanosecs = true;3937 return 0;3938}3939 3940int cmd_script(int argc, const char **argv)3941{3942 bool show_full_info = false;3943 bool header = false;3944 bool header_only = false;3945 bool script_started = false;3946 bool unsorted_dump = false;3947 char *rec_script_path = NULL;3948 char *rep_script_path = NULL;3949 struct perf_session *session;3950 struct itrace_synth_opts itrace_synth_opts = {3951 .set = false,3952 .default_no_sample = true,3953 };3954 struct utsname uts;3955 char *script_path = NULL;3956 const char *dlfilter_file = NULL;3957 const char **__argv;3958 int i, j, err = 0;3959 struct perf_script script = {};3960 struct perf_data data = {3961 .mode = PERF_DATA_MODE_READ,3962 };3963 const struct option options[] = {3964 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,3965 "dump raw trace in ASCII"),3966 OPT_BOOLEAN(0, "dump-unsorted-raw-trace", &unsorted_dump,3967 "dump unsorted raw trace in ASCII"),3968 OPT_INCR('v', "verbose", &verbose,3969 "be more verbose (show symbol address, etc)"),3970 OPT_BOOLEAN('L', "Latency", &latency_format,3971 "show latency attributes (irqs/preemption disabled, etc)"),3972 OPT_CALLBACK_NOOPT('l', "list", NULL, NULL, "list available scripts",3973 list_available_scripts),3974 OPT_CALLBACK_NOOPT(0, "list-dlfilters", NULL, NULL, "list available dlfilters",3975 list_available_dlfilters),3976 OPT_CALLBACK('s', "script", NULL, "name",3977 "script file name (lang:script name, script name, or *)",3978 parse_scriptname),3979 OPT_STRING('g', "gen-script", &generate_script_lang, "lang",3980 "generate perf-script.xx script in specified language"),3981 OPT_STRING(0, "dlfilter", &dlfilter_file, "file", "filter .so file name"),3982 OPT_CALLBACK(0, "dlarg", NULL, "argument", "filter argument",3983 add_dlarg),3984 OPT_STRING('i', "input", &input_name, "file", "input file name"),3985 OPT_BOOLEAN('d', "debug-mode", &debug_mode,3986 "do various checks like samples ordering and lost events"),3987 OPT_BOOLEAN(0, "header", &header, "Show data header."),3988 OPT_BOOLEAN(0, "header-only", &header_only, "Show only data header."),3989 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,3990 "file", "vmlinux pathname"),3991 OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name,3992 "file", "kallsyms pathname"),3993 OPT_BOOLEAN('G', "hide-call-graph", &no_callchain,3994 "When printing symbols do not display call chain"),3995 OPT_CALLBACK(0, "symfs", NULL, "directory",3996 "Look for files with symbols relative to this directory",3997 symbol__config_symfs),3998 OPT_CALLBACK('F', "fields", NULL, "str",3999 "comma separated output fields prepend with 'type:'. "4000 "+field to add and -field to remove."4001 "Valid types: hw,sw,trace,raw,synth. "4002 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,dsoff,"4003 "addr,symoff,srcline,period,iregs,uregs,brstack,"4004 "brstacksym,flags,data_src,weight,bpf-output,brstackinsn,"4005 "brstackinsnlen,brstackdisasm,brstackoff,callindent,insn,disasm,insnlen,synth,"4006 "phys_addr,metric,misc,srccode,ipc,tod,data_page_size,"4007 "code_page_size,ins_lat,machine_pid,vcpu,cgroup,retire_lat,"4008 "brcntr",4009 parse_output_fields),4010 OPT_BOOLEAN('a', "all-cpus", &system_wide,4011 "system-wide collection from all CPUs"),4012 OPT_STRING(0, "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",4013 "only consider symbols in these DSOs"),4014 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",4015 "only consider these symbols"),4016 OPT_INTEGER(0, "addr-range", &symbol_conf.addr_range,4017 "Use with -S to list traced records within address range"),4018 OPT_CALLBACK_OPTARG(0, "insn-trace", &itrace_synth_opts, NULL, "raw|disasm",4019 "Decode instructions from itrace", parse_insn_trace),4020 OPT_CALLBACK_OPTARG(0, "xed", NULL, NULL, NULL,4021 "Run xed disassembler on output", parse_xed),4022 OPT_CALLBACK_OPTARG(0, "call-trace", &itrace_synth_opts, NULL, NULL,4023 "Decode calls from itrace", parse_call_trace),4024 OPT_CALLBACK_OPTARG(0, "call-ret-trace", &itrace_synth_opts, NULL, NULL,4025 "Decode calls and returns from itrace", parse_callret_trace),4026 OPT_STRING(0, "graph-function", &symbol_conf.graph_function, "symbol[,symbol...]",4027 "Only print symbols and callees with --call-trace/--call-ret-trace"),4028 OPT_STRING(0, "stop-bt", &symbol_conf.bt_stop_list_str, "symbol[,symbol...]",4029 "Stop display of callgraph at these symbols"),4030 OPT_STRING('C', "cpu", &cpu_list, "cpu", "list of cpus to profile"),4031 OPT_STRING('c', "comms", &symbol_conf.comm_list_str, "comm[,comm...]",4032 "only display events for these comms"),4033 OPT_STRING(0, "pid", &symbol_conf.pid_list_str, "pid[,pid...]",4034 "only consider symbols in these pids"),4035 OPT_STRING(0, "tid", &symbol_conf.tid_list_str, "tid[,tid...]",4036 "only consider symbols in these tids"),4037 OPT_UINTEGER(0, "max-stack", &scripting_max_stack,4038 "Set the maximum stack depth when parsing the callchain, "4039 "anything beyond the specified depth will be ignored. "4040 "Default: kernel.perf_event_max_stack or " __stringify(PERF_MAX_STACK_DEPTH)),4041 OPT_BOOLEAN(0, "reltime", &reltime, "Show time stamps relative to start"),4042 OPT_BOOLEAN(0, "deltatime", &deltatime, "Show time stamps relative to previous event"),4043 OPT_BOOLEAN('I', "show-info", &show_full_info,4044 "display extended information from perf.data file"),4045 OPT_BOOLEAN('\0', "show-kernel-path", &symbol_conf.show_kernel_path,4046 "Show the path of [kernel.kallsyms]"),4047 OPT_BOOLEAN('\0', "show-task-events", &script.show_task_events,4048 "Show the fork/comm/exit events"),4049 OPT_BOOLEAN('\0', "show-mmap-events", &script.show_mmap_events,4050 "Show the mmap events"),4051 OPT_BOOLEAN('\0', "show-switch-events", &script.show_switch_events,4052 "Show context switch events (if recorded)"),4053 OPT_BOOLEAN('\0', "show-namespace-events", &script.show_namespace_events,4054 "Show namespace events (if recorded)"),4055 OPT_BOOLEAN('\0', "show-cgroup-events", &script.show_cgroup_events,4056 "Show cgroup events (if recorded)"),4057 OPT_BOOLEAN('\0', "show-lost-events", &script.show_lost_events,4058 "Show lost events (if recorded)"),4059 OPT_BOOLEAN('\0', "show-round-events", &script.show_round_events,4060 "Show round events (if recorded)"),4061 OPT_BOOLEAN('\0', "show-bpf-events", &script.show_bpf_events,4062 "Show bpf related events (if recorded)"),4063 OPT_BOOLEAN('\0', "show-text-poke-events", &script.show_text_poke_events,4064 "Show text poke related events (if recorded)"),4065 OPT_BOOLEAN('\0', "per-event-dump", &script.per_event_dump,4066 "Dump trace output to files named by the monitored events"),4067 OPT_BOOLEAN('f', "force", &symbol_conf.force, "don't complain, do it"),4068 OPT_INTEGER(0, "max-blocks", &max_blocks,4069 "Maximum number of code blocks to dump with brstackinsn"),4070 OPT_BOOLEAN(0, "ns", &symbol_conf.nanosecs,4071 "Use 9 decimal places when displaying time"),4072 OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts",4073 "Instruction Tracing options\n" ITRACE_HELP,4074 itrace_parse_synth_opts),4075 OPT_BOOLEAN(0, "full-source-path", &srcline_full_filename,4076 "Show full source file name path for source lines"),4077 OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle,4078 "Enable symbol demangling"),4079 OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel,4080 "Enable kernel symbol demangling"),4081 OPT_STRING(0, "addr2line", &symbol_conf.addr2line_path, "path",4082 "addr2line binary to use for line numbers"),4083 OPT_STRING(0, "time", &script.time_str, "str",4084 "Time span of interest (start,stop)"),4085 OPT_BOOLEAN(0, "inline", &symbol_conf.inline_name,4086 "Show inline function"),4087 OPT_STRING(0, "guestmount", &symbol_conf.guestmount, "directory",4088 "guest mount directory under which every guest os"4089 " instance has a subdir"),4090 OPT_STRING(0, "guestvmlinux", &symbol_conf.default_guest_vmlinux_name,4091 "file", "file saving guest os vmlinux"),4092 OPT_STRING(0, "guestkallsyms", &symbol_conf.default_guest_kallsyms,4093 "file", "file saving guest os /proc/kallsyms"),4094 OPT_STRING(0, "guestmodules", &symbol_conf.default_guest_modules,4095 "file", "file saving guest os /proc/modules"),4096 OPT_BOOLEAN(0, "guest-code", &symbol_conf.guest_code,4097 "Guest code can be found in hypervisor process"),4098 OPT_BOOLEAN('\0', "stitch-lbr", &script.stitch_lbr,4099 "Enable LBR callgraph stitching approach"),4100 OPTS_EVSWITCH(&script.evswitch),4101 OPT_END()4102 };4103 const char * const script_subcommands[] = { "record", "report", NULL };4104 const char *script_usage[] = {4105 "perf script [<options>]",4106 "perf script [<options>] record <script> [<record-options>] <command>",4107 "perf script [<options>] report <script> [script-args]",4108 "perf script [<options>] <script> [<record-options>] <command>",4109 "perf script [<options>] <top-script> [script-args]",4110 NULL4111 };4112 4113 perf_set_singlethreaded();4114 4115 setup_scripting();4116 4117 argc = parse_options_subcommand(argc, argv, options, script_subcommands, script_usage,4118 PARSE_OPT_STOP_AT_NON_OPTION);4119 4120 if (symbol_conf.guestmount ||4121 symbol_conf.default_guest_vmlinux_name ||4122 symbol_conf.default_guest_kallsyms ||4123 symbol_conf.default_guest_modules ||4124 symbol_conf.guest_code) {4125 /*4126 * Enable guest sample processing.4127 */4128 perf_guest = true;4129 }4130 4131 data.path = input_name;4132 data.force = symbol_conf.force;4133 4134 if (unsorted_dump)4135 dump_trace = true;4136 4137 if (symbol__validate_sym_arguments())4138 return -1;4139 4140 if (argc > 1 && strlen(argv[0]) > 2 && strstarts("record", argv[0])) {4141 rec_script_path = get_script_path(argv[1], RECORD_SUFFIX);4142 if (!rec_script_path)4143 return cmd_record(argc, argv);4144 }4145 4146 if (argc > 1 && strlen(argv[0]) > 2 && strstarts("report", argv[0])) {4147 rep_script_path = get_script_path(argv[1], REPORT_SUFFIX);4148 if (!rep_script_path) {4149 fprintf(stderr,4150 "Please specify a valid report script"4151 "(see 'perf script -l' for listing)\n");4152 return -1;4153 }4154 }4155 4156 if (reltime && deltatime) {4157 fprintf(stderr,4158 "reltime and deltatime - the two don't get along well. "4159 "Please limit to --reltime or --deltatime.\n");4160 return -1;4161 }4162 4163 if ((itrace_synth_opts.callchain || itrace_synth_opts.add_callchain) &&4164 itrace_synth_opts.callchain_sz > scripting_max_stack)4165 scripting_max_stack = itrace_synth_opts.callchain_sz;4166 4167 /* make sure PERF_EXEC_PATH is set for scripts */4168 set_argv_exec_path(get_argv_exec_path());4169 4170 if (argc && !script_name && !rec_script_path && !rep_script_path) {4171 int live_pipe[2];4172 int rep_args;4173 pid_t pid;4174 4175 rec_script_path = get_script_path(argv[0], RECORD_SUFFIX);4176 rep_script_path = get_script_path(argv[0], REPORT_SUFFIX);4177 4178 if (!rec_script_path && !rep_script_path) {4179 script_name = find_script(argv[0]);4180 if (script_name) {4181 argc -= 1;4182 argv += 1;4183 goto script_found;4184 }4185 usage_with_options_msg(script_usage, options,4186 "Couldn't find script `%s'\n\n See perf"4187 " script -l for available scripts.\n", argv[0]);4188 }4189 4190 if (is_top_script(argv[0])) {4191 rep_args = argc - 1;4192 } else {4193 int rec_args;4194 4195 rep_args = has_required_arg(rep_script_path);4196 rec_args = (argc - 1) - rep_args;4197 if (rec_args < 0) {4198 usage_with_options_msg(script_usage, options,4199 "`%s' script requires options."4200 "\n\n See perf script -l for available "4201 "scripts and options.\n", argv[0]);4202 }4203 }4204 4205 if (pipe(live_pipe) < 0) {4206 perror("failed to create pipe");4207 return -1;4208 }4209 4210 pid = fork();4211 if (pid < 0) {4212 perror("failed to fork");4213 return -1;4214 }4215 4216 if (!pid) {4217 j = 0;4218 4219 dup2(live_pipe[1], 1);4220 close(live_pipe[0]);4221 4222 if (is_top_script(argv[0])) {4223 system_wide = true;4224 } else if (!system_wide) {4225 if (have_cmd(argc - rep_args, &argv[rep_args]) != 0) {4226 err = -1;4227 goto out;4228 }4229 }4230 4231 __argv = malloc((argc + 6) * sizeof(const char *));4232 if (!__argv) {4233 pr_err("malloc failed\n");4234 err = -ENOMEM;4235 goto out;4236 }4237 4238 __argv[j++] = "/bin/sh";4239 __argv[j++] = rec_script_path;4240 if (system_wide)4241 __argv[j++] = "-a";4242 __argv[j++] = "-q";4243 __argv[j++] = "-o";4244 __argv[j++] = "-";4245 for (i = rep_args + 1; i < argc; i++)4246 __argv[j++] = argv[i];4247 __argv[j++] = NULL;4248 4249 execvp("/bin/sh", (char **)__argv);4250 free(__argv);4251 exit(-1);4252 }4253 4254 dup2(live_pipe[0], 0);4255 close(live_pipe[1]);4256 4257 __argv = malloc((argc + 4) * sizeof(const char *));4258 if (!__argv) {4259 pr_err("malloc failed\n");4260 err = -ENOMEM;4261 goto out;4262 }4263 4264 j = 0;4265 __argv[j++] = "/bin/sh";4266 __argv[j++] = rep_script_path;4267 for (i = 1; i < rep_args + 1; i++)4268 __argv[j++] = argv[i];4269 __argv[j++] = "-i";4270 __argv[j++] = "-";4271 __argv[j++] = NULL;4272 4273 execvp("/bin/sh", (char **)__argv);4274 free(__argv);4275 exit(-1);4276 }4277script_found:4278 if (rec_script_path)4279 script_path = rec_script_path;4280 if (rep_script_path)4281 script_path = rep_script_path;4282 4283 if (script_path) {4284 j = 0;4285 4286 if (!rec_script_path)4287 system_wide = false;4288 else if (!system_wide) {4289 if (have_cmd(argc - 1, &argv[1]) != 0) {4290 err = -1;4291 goto out;4292 }4293 }4294 4295 __argv = malloc((argc + 2) * sizeof(const char *));4296 if (!__argv) {4297 pr_err("malloc failed\n");4298 err = -ENOMEM;4299 goto out;4300 }4301 4302 __argv[j++] = "/bin/sh";4303 __argv[j++] = script_path;4304 if (system_wide)4305 __argv[j++] = "-a";4306 for (i = 2; i < argc; i++)4307 __argv[j++] = argv[i];4308 __argv[j++] = NULL;4309 4310 execvp("/bin/sh", (char **)__argv);4311 free(__argv);4312 exit(-1);4313 }4314 4315 if (dlfilter_file) {4316 dlfilter = dlfilter__new(dlfilter_file, dlargc, dlargv);4317 if (!dlfilter)4318 return -1;4319 }4320 4321 if (!script_name) {4322 setup_pager();4323 use_browser = 0;4324 }4325 4326 perf_tool__init(&script.tool, !unsorted_dump);4327 script.tool.sample = process_sample_event;4328 script.tool.mmap = perf_event__process_mmap;4329 script.tool.mmap2 = perf_event__process_mmap2;4330 script.tool.comm = perf_event__process_comm;4331 script.tool.namespaces = perf_event__process_namespaces;4332 script.tool.cgroup = perf_event__process_cgroup;4333 script.tool.exit = perf_event__process_exit;4334 script.tool.fork = perf_event__process_fork;4335 script.tool.attr = process_attr;4336 script.tool.event_update = perf_event__process_event_update;4337#ifdef HAVE_LIBTRACEEVENT4338 script.tool.tracing_data = perf_event__process_tracing_data;4339#endif4340 script.tool.feature = process_feature_event;4341 script.tool.build_id = perf_event__process_build_id;4342 script.tool.id_index = perf_event__process_id_index;4343 script.tool.auxtrace_info = perf_script__process_auxtrace_info;4344 script.tool.auxtrace = perf_event__process_auxtrace;4345 script.tool.auxtrace_error = perf_event__process_auxtrace_error;4346 script.tool.stat = perf_event__process_stat_event;4347 script.tool.stat_round = process_stat_round_event;4348 script.tool.stat_config = process_stat_config_event;4349 script.tool.thread_map = process_thread_map_event;4350 script.tool.cpu_map = process_cpu_map_event;4351 script.tool.throttle = process_throttle_event;4352 script.tool.unthrottle = process_throttle_event;4353 script.tool.ordering_requires_timestamps = true;4354 session = perf_session__new(&data, &script.tool);4355 if (IS_ERR(session))4356 return PTR_ERR(session);4357 4358 if (header || header_only) {4359 script.tool.show_feat_hdr = SHOW_FEAT_HEADER;4360 perf_session__fprintf_info(session, stdout, show_full_info);4361 if (header_only)4362 goto out_delete;4363 }4364 if (show_full_info)4365 script.tool.show_feat_hdr = SHOW_FEAT_HEADER_FULL_INFO;4366 4367 if (symbol__init(&session->header.env) < 0)4368 goto out_delete;4369 4370 uname(&uts);4371 if (data.is_pipe) { /* Assume pipe_mode indicates native_arch */4372 native_arch = true;4373 } else if (session->header.env.arch) {4374 if (!strcmp(uts.machine, session->header.env.arch))4375 native_arch = true;4376 else if (!strcmp(uts.machine, "x86_64") &&4377 !strcmp(session->header.env.arch, "i386"))4378 native_arch = true;4379 }4380 4381 script.session = session;4382 script__setup_sample_type(&script);4383 4384 if ((output[PERF_TYPE_HARDWARE].fields & PERF_OUTPUT_CALLINDENT) ||4385 symbol_conf.graph_function)4386 itrace_synth_opts.thread_stack = true;4387 4388 session->itrace_synth_opts = &itrace_synth_opts;4389 4390 if (cpu_list) {4391 err = perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap);4392 if (err < 0)4393 goto out_delete;4394 itrace_synth_opts.cpu_bitmap = cpu_bitmap;4395 }4396 4397 if (!no_callchain)4398 symbol_conf.use_callchain = true;4399 else4400 symbol_conf.use_callchain = false;4401 4402#ifdef HAVE_LIBTRACEEVENT4403 if (session->tevent.pevent &&4404 tep_set_function_resolver(session->tevent.pevent,4405 machine__resolve_kernel_addr,4406 &session->machines.host) < 0) {4407 pr_err("%s: failed to set libtraceevent function resolver\n", __func__);4408 err = -1;4409 goto out_delete;4410 }4411#endif4412 if (generate_script_lang) {4413 struct stat perf_stat;4414 int input;4415 4416 if (output_set_by_user()) {4417 fprintf(stderr,4418 "custom fields not supported for generated scripts");4419 err = -EINVAL;4420 goto out_delete;4421 }4422 4423 input = open(data.path, O_RDONLY); /* input_name */4424 if (input < 0) {4425 err = -errno;4426 perror("failed to open file");4427 goto out_delete;4428 }4429 4430 err = fstat(input, &perf_stat);4431 if (err < 0) {4432 perror("failed to stat file");4433 goto out_delete;4434 }4435 4436 if (!perf_stat.st_size) {4437 fprintf(stderr, "zero-sized file, nothing to do!\n");4438 goto out_delete;4439 }4440 4441 scripting_ops = script_spec__lookup(generate_script_lang);4442 if (!scripting_ops) {4443 fprintf(stderr, "invalid language specifier");4444 err = -ENOENT;4445 goto out_delete;4446 }4447#ifdef HAVE_LIBTRACEEVENT4448 err = scripting_ops->generate_script(session->tevent.pevent,4449 "perf-script");4450#else4451 err = scripting_ops->generate_script(NULL, "perf-script");4452#endif4453 goto out_delete;4454 }4455 4456 err = dlfilter__start(dlfilter, session);4457 if (err)4458 goto out_delete;4459 4460 if (script_name) {4461 err = scripting_ops->start_script(script_name, argc, argv, session);4462 if (err)4463 goto out_delete;4464 pr_debug("perf script started with script %s\n\n", script_name);4465 script_started = true;4466 }4467 4468 4469 err = perf_session__check_output_opt(session);4470 if (err < 0)4471 goto out_delete;4472 4473 if (script.time_str) {4474 err = perf_time__parse_for_ranges_reltime(script.time_str, session,4475 &script.ptime_range,4476 &script.range_size,4477 &script.range_num,4478 reltime);4479 if (err < 0)4480 goto out_delete;4481 4482 itrace_synth_opts__set_time_range(&itrace_synth_opts,4483 script.ptime_range,4484 script.range_num);4485 }4486 4487 err = evswitch__init(&script.evswitch, session->evlist, stderr);4488 if (err)4489 goto out_delete;4490 4491 if (zstd_init(&(session->zstd_data), 0) < 0)4492 pr_warning("Decompression initialization failed. Reported data may be incomplete.\n");4493 4494 err = __cmd_script(&script);4495 4496 flush_scripting();4497 4498 if (verbose > 2 || debug_kmaps)4499 perf_session__dump_kmaps(session);4500 4501out_delete:4502 if (script.ptime_range) {4503 itrace_synth_opts__clear_time_range(&itrace_synth_opts);4504 zfree(&script.ptime_range);4505 }4506 4507 zstd_fini(&(session->zstd_data));4508 evlist__free_stats(session->evlist);4509 perf_session__delete(session);4510 perf_script__exit(&script);4511 4512 if (script_started)4513 cleanup_scripting();4514 dlfilter__cleanup(dlfilter);4515 free_dlarg();4516out:4517 return err;4518}4519