// SPDX-License-Identifier: GPL-2.0#include "builtin.h" #include "util/counts.h"#include "util/debug.h"#include "util/dso.h"#include <subcmd/exec-cmd.h>#include "util/header.h"#include <subcmd/parse-options.h>#include "util/perf_regs.h"#include "util/session.h"#include "util/tool.h"#include "util/map.h"#include "util/srcline.h"#include "util/symbol.h"#include "util/thread.h"#include "util/trace-event.h"#include "util/env.h"#include "util/evlist.h"#include "util/evsel.h"#include "util/evsel_fprintf.h"#include "util/evswitch.h"#include "util/sort.h"#include "util/data.h"#include "util/auxtrace.h"#include "util/cpumap.h"#include "util/thread_map.h"#include "util/stat.h"#include "util/color.h"#include "util/string2.h"#include "util/thread-stack.h"#include "util/time-utils.h"#include "util/path.h"#include "util/event.h"#include "util/mem-info.h"#include "ui/ui.h"#include "print_binary.h"#include "print_insn.h"#include "archinsn.h"#include <linux/bitmap.h>#include <linux/kernel.h>#include <linux/stringify.h>#include <linux/time64.h>#include <linux/zalloc.h>#include <sys/utsname.h>#include "asm/bug.h"#include "util/mem-events.h"#include "util/dump-insn.h"#include <dirent.h>#include <errno.h>#include <inttypes.h>#include <signal.h>#include <sys/param.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>#include <subcmd/pager.h>#include <perf/evlist.h>#include <linux/err.h>#include "util/dlfilter.h"#include "util/record.h"#include "util/util.h"#include "util/cgroup.h"#include "util/annotate.h"#include "perf.h" #include <linux/ctype.h>#ifdef HAVE_LIBTRACEEVENT#include <event-parse.h>#endif static char const *script_name;static char const *generate_script_lang;static bool reltime;static bool deltatime;static u64 initial_time;static u64 previous_time;static bool debug_mode;static u64 last_timestamp;static u64 nr_unordered;static bool no_callchain;static bool latency_format;static bool system_wide;static bool print_flags;static const char *cpu_list;static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);static struct perf_stat_config stat_config;static int max_blocks;static bool native_arch;static struct dlfilter *dlfilter;static int dlargc;static char **dlargv; unsigned int scripting_max_stack = PERF_MAX_STACK_DEPTH; enum perf_output_field { PERF_OUTPUT_COMM = 1ULL << 0, PERF_OUTPUT_TID = 1ULL << 1, PERF_OUTPUT_PID = 1ULL << 2, PERF_OUTPUT_TIME = 1ULL << 3, PERF_OUTPUT_CPU = 1ULL << 4, PERF_OUTPUT_EVNAME = 1ULL << 5, PERF_OUTPUT_TRACE = 1ULL << 6, PERF_OUTPUT_IP = 1ULL << 7, PERF_OUTPUT_SYM = 1ULL << 8, PERF_OUTPUT_DSO = 1ULL << 9, PERF_OUTPUT_ADDR = 1ULL << 10, PERF_OUTPUT_SYMOFFSET = 1ULL << 11, PERF_OUTPUT_SRCLINE = 1ULL << 12, PERF_OUTPUT_PERIOD = 1ULL << 13, PERF_OUTPUT_IREGS = 1ULL << 14, PERF_OUTPUT_BRSTACK = 1ULL << 15, PERF_OUTPUT_BRSTACKSYM = 1ULL << 16, PERF_OUTPUT_DATA_SRC = 1ULL << 17, PERF_OUTPUT_WEIGHT = 1ULL << 18, PERF_OUTPUT_BPF_OUTPUT = 1ULL << 19, PERF_OUTPUT_CALLINDENT = 1ULL << 20, PERF_OUTPUT_INSN = 1ULL << 21, PERF_OUTPUT_INSNLEN = 1ULL << 22, PERF_OUTPUT_BRSTACKINSN = 1ULL << 23, PERF_OUTPUT_BRSTACKOFF = 1ULL << 24, PERF_OUTPUT_SYNTH = 1ULL << 25, PERF_OUTPUT_PHYS_ADDR = 1ULL << 26, PERF_OUTPUT_UREGS = 1ULL << 27, PERF_OUTPUT_METRIC = 1ULL << 28, PERF_OUTPUT_MISC = 1ULL << 29, PERF_OUTPUT_SRCCODE = 1ULL << 30, PERF_OUTPUT_IPC = 1ULL << 31, PERF_OUTPUT_TOD = 1ULL << 32, PERF_OUTPUT_DATA_PAGE_SIZE = 1ULL << 33, PERF_OUTPUT_CODE_PAGE_SIZE = 1ULL << 34, PERF_OUTPUT_INS_LAT = 1ULL << 35, PERF_OUTPUT_BRSTACKINSNLEN = 1ULL << 36, PERF_OUTPUT_MACHINE_PID = 1ULL << 37, PERF_OUTPUT_VCPU = 1ULL << 38, PERF_OUTPUT_CGROUP = 1ULL << 39, PERF_OUTPUT_RETIRE_LAT = 1ULL << 40, PERF_OUTPUT_DSOFF = 1ULL << 41, PERF_OUTPUT_DISASM = 1ULL << 42, PERF_OUTPUT_BRSTACKDISASM = 1ULL << 43, PERF_OUTPUT_BRCNTR = 1ULL << 44,}; struct perf_script { struct perf_tool tool; struct perf_session *session; bool show_task_events; bool show_mmap_events; bool show_switch_events; bool show_namespace_events; bool show_lost_events; bool show_round_events; bool show_bpf_events; bool show_cgroup_events; bool show_text_poke_events; bool allocated; bool per_event_dump; bool stitch_lbr; struct evswitch evswitch; struct perf_cpu_map *cpus; struct perf_thread_map *threads; int name_width; const char *time_str; struct perf_time_interval *ptime_range; int range_size; int range_num;}; struct output_option { const char *str; enum perf_output_field field;} all_output_options[] = { {.str = "comm", .field = PERF_OUTPUT_COMM}, {.str = "tid", .field = PERF_OUTPUT_TID}, {.str = "pid", .field = PERF_OUTPUT_PID}, {.str = "time", .field = PERF_OUTPUT_TIME}, {.str = "cpu", .field = PERF_OUTPUT_CPU}, {.str = "event", .field = PERF_OUTPUT_EVNAME}, {.str = "trace", .field = PERF_OUTPUT_TRACE}, {.str = "ip", .field = PERF_OUTPUT_IP}, {.str = "sym", .field = PERF_OUTPUT_SYM}, {.str = "dso", .field = PERF_OUTPUT_DSO}, {.str = "dsoff", .field = PERF_OUTPUT_DSOFF}, {.str = "addr", .field = PERF_OUTPUT_ADDR}, {.str = "symoff", .field = PERF_OUTPUT_SYMOFFSET}, {.str = "srcline", .field = PERF_OUTPUT_SRCLINE}, {.str = "period", .field = PERF_OUTPUT_PERIOD}, {.str = "iregs", .field = PERF_OUTPUT_IREGS}, {.str = "uregs", .field = PERF_OUTPUT_UREGS}, {.str = "brstack", .field = PERF_OUTPUT_BRSTACK}, {.str = "brstacksym", .field = PERF_OUTPUT_BRSTACKSYM}, {.str = "data_src", .field = PERF_OUTPUT_DATA_SRC}, {.str = "weight", .field = PERF_OUTPUT_WEIGHT}, {.str = "bpf-output", .field = PERF_OUTPUT_BPF_OUTPUT}, {.str = "callindent", .field = PERF_OUTPUT_CALLINDENT}, {.str = "insn", .field = PERF_OUTPUT_INSN}, {.str = "disasm", .field = PERF_OUTPUT_DISASM}, {.str = "insnlen", .field = PERF_OUTPUT_INSNLEN}, {.str = "brstackinsn", .field = PERF_OUTPUT_BRSTACKINSN}, {.str = "brstackoff", .field = PERF_OUTPUT_BRSTACKOFF}, {.str = "synth", .field = PERF_OUTPUT_SYNTH}, {.str = "phys_addr", .field = PERF_OUTPUT_PHYS_ADDR}, {.str = "metric", .field = PERF_OUTPUT_METRIC}, {.str = "misc", .field = PERF_OUTPUT_MISC}, {.str = "srccode", .field = PERF_OUTPUT_SRCCODE}, {.str = "ipc", .field = PERF_OUTPUT_IPC}, {.str = "tod", .field = PERF_OUTPUT_TOD}, {.str = "data_page_size", .field = PERF_OUTPUT_DATA_PAGE_SIZE}, {.str = "code_page_size", .field = PERF_OUTPUT_CODE_PAGE_SIZE}, {.str = "ins_lat", .field = PERF_OUTPUT_INS_LAT}, {.str = "brstackinsnlen", .field = PERF_OUTPUT_BRSTACKINSNLEN}, {.str = "machine_pid", .field = PERF_OUTPUT_MACHINE_PID}, {.str = "vcpu", .field = PERF_OUTPUT_VCPU}, {.str = "cgroup", .field = PERF_OUTPUT_CGROUP}, {.str = "retire_lat", .field = PERF_OUTPUT_RETIRE_LAT}, {.str = "brstackdisasm", .field = PERF_OUTPUT_BRSTACKDISASM}, {.str = "brcntr", .field = PERF_OUTPUT_BRCNTR},}; enum { OUTPUT_TYPE_SYNTH = PERF_TYPE_MAX, OUTPUT_TYPE_OTHER, OUTPUT_TYPE_MAX}; /* default set to maintain compatibility with current format */static struct { bool user_set; bool wildcard_set; unsigned int print_ip_opts; u64 fields; u64 invalid_fields; u64 user_set_fields; u64 user_unset_fields;} output[OUTPUT_TYPE_MAX] = { [PERF_TYPE_HARDWARE] = { .user_set = false, .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP | PERF_OUTPUT_SYM | PERF_OUTPUT_SYMOFFSET | PERF_OUTPUT_DSO | PERF_OUTPUT_PERIOD, .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT, }, [PERF_TYPE_SOFTWARE] = { .user_set = false, .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP | PERF_OUTPUT_SYM | PERF_OUTPUT_SYMOFFSET | PERF_OUTPUT_DSO | PERF_OUTPUT_PERIOD | PERF_OUTPUT_BPF_OUTPUT, .invalid_fields = PERF_OUTPUT_TRACE, }, [PERF_TYPE_TRACEPOINT] = { .user_set = false, .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | PERF_OUTPUT_EVNAME | PERF_OUTPUT_TRACE }, [PERF_TYPE_HW_CACHE] = { .user_set = false, .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP | PERF_OUTPUT_SYM | PERF_OUTPUT_SYMOFFSET | PERF_OUTPUT_DSO | PERF_OUTPUT_PERIOD, .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT, }, [PERF_TYPE_RAW] = { .user_set = false, .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP | PERF_OUTPUT_SYM | PERF_OUTPUT_SYMOFFSET | PERF_OUTPUT_DSO | PERF_OUTPUT_PERIOD | PERF_OUTPUT_ADDR | PERF_OUTPUT_DATA_SRC | PERF_OUTPUT_WEIGHT | PERF_OUTPUT_PHYS_ADDR | PERF_OUTPUT_DATA_PAGE_SIZE | PERF_OUTPUT_CODE_PAGE_SIZE | PERF_OUTPUT_INS_LAT | PERF_OUTPUT_RETIRE_LAT, .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT, }, [PERF_TYPE_BREAKPOINT] = { .user_set = false, .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP | PERF_OUTPUT_SYM | PERF_OUTPUT_SYMOFFSET | PERF_OUTPUT_DSO | PERF_OUTPUT_PERIOD, .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT, }, [OUTPUT_TYPE_SYNTH] = { .user_set = false, .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP | PERF_OUTPUT_SYM | PERF_OUTPUT_SYMOFFSET | PERF_OUTPUT_DSO | PERF_OUTPUT_SYNTH, .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT, }, [OUTPUT_TYPE_OTHER] = { .user_set = false, .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP | PERF_OUTPUT_SYM | PERF_OUTPUT_SYMOFFSET | PERF_OUTPUT_DSO | PERF_OUTPUT_PERIOD, .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT, },}; struct evsel_script { char *filename; FILE *fp; u64 samples; /* For metric output */ u64 val; int gnum;}; static inline struct evsel_script *evsel_script(struct evsel *evsel){ return (struct evsel_script *)evsel->priv;} static struct evsel_script *evsel_script__new(struct evsel *evsel, struct perf_data *data){ struct evsel_script *es = zalloc(sizeof(*es)); if (es != NULL) { if (asprintf(&es->filename, "%s.%s.dump", data->file.path, evsel__name(evsel)) < 0) goto out_free; es->fp = fopen(es->filename, "w"); if (es->fp == NULL) goto out_free_filename; } return es;out_free_filename: zfree(&es->filename);out_free: free(es); return NULL;} static void evsel_script__delete(struct evsel_script *es){ zfree(&es->filename); fclose(es->fp); es->fp = NULL; free(es);} static int evsel_script__fprintf(struct evsel_script *es, FILE *fp){ struct stat st; fstat(fileno(es->fp), &st); return fprintf(fp, "[ perf script: Wrote %.3f MB %s (%" PRIu64 " samples) ]\n", st.st_size / 1024.0 / 1024.0, es->filename, es->samples);} static inline int output_type(unsigned int type){ switch (type) { case PERF_TYPE_SYNTH: return OUTPUT_TYPE_SYNTH; default: if (type < PERF_TYPE_MAX) return type; } return OUTPUT_TYPE_OTHER;} static bool output_set_by_user(void){ int j; for (j = 0; j < OUTPUT_TYPE_MAX; ++j) { if (output[j].user_set) return true; } return false;} static const char *output_field2str(enum perf_output_field field){ int i, imax = ARRAY_SIZE(all_output_options); const char *str = ""; for (i = 0; i < imax; ++i) { if (all_output_options[i].field == field) { str = all_output_options[i].str; break; } } return str;} #define PRINT_FIELD(x) (output[output_type(attr->type)].fields & PERF_OUTPUT_##x) static int evsel__do_check_stype(struct evsel *evsel, u64 sample_type, const char *sample_msg, enum perf_output_field field, bool allow_user_set){ struct perf_event_attr *attr = &evsel->core.attr; int type = output_type(attr->type); const char *evname; if (attr->sample_type & sample_type) return 0; if (output[type].user_set_fields & field) { if (allow_user_set) return 0; evname = evsel__name(evsel); pr_err("Samples for '%s' event do not have %s attribute set. " "Cannot print '%s' field.\n", evname, sample_msg, output_field2str(field)); return -1; } /* user did not ask for it explicitly so remove from the default list */ output[type].fields &= ~field; evname = evsel__name(evsel); pr_debug("Samples for '%s' event do not have %s attribute set. " "Skipping '%s' field.\n", evname, sample_msg, output_field2str(field)); return 0;} static int evsel__check_stype(struct evsel *evsel, u64 sample_type, const char *sample_msg, enum perf_output_field field){ return evsel__do_check_stype(evsel, sample_type, sample_msg, field, false);} static int evsel__check_attr(struct evsel *evsel, struct perf_session *session){ struct perf_event_attr *attr = &evsel->core.attr; bool allow_user_set; if (evsel__is_dummy_event(evsel)) return 0; if (perf_header__has_feat(&session->header, HEADER_STAT)) return 0; allow_user_set = perf_header__has_feat(&session->header, HEADER_AUXTRACE); if (PRINT_FIELD(TRACE) && !perf_session__has_traces(session, "record -R")) return -EINVAL; if (PRINT_FIELD(IP)) { if (evsel__check_stype(evsel, PERF_SAMPLE_IP, "IP", PERF_OUTPUT_IP)) return -EINVAL; } if (PRINT_FIELD(ADDR) && evsel__do_check_stype(evsel, PERF_SAMPLE_ADDR, "ADDR", PERF_OUTPUT_ADDR, allow_user_set)) return -EINVAL; if (PRINT_FIELD(DATA_SRC) && evsel__do_check_stype(evsel, PERF_SAMPLE_DATA_SRC, "DATA_SRC", PERF_OUTPUT_DATA_SRC, allow_user_set)) return -EINVAL; if (PRINT_FIELD(WEIGHT) && evsel__do_check_stype(evsel, PERF_SAMPLE_WEIGHT_TYPE, "WEIGHT", PERF_OUTPUT_WEIGHT, allow_user_set)) return -EINVAL; if (PRINT_FIELD(SYM) && !(evsel->core.attr.sample_type & (PERF_SAMPLE_IP|PERF_SAMPLE_ADDR))) { pr_err("Display of symbols requested but neither sample IP nor " "sample address\navailable. Hence, no addresses to convert "Lines 1–500 of 4519. Load more
// SPDX-License-Identifier: GPL-2.0 #include "builtin.h" #include "util/counts.h" #include "util/debug.h" #include "util/dso.h" #include <subcmd/exec-cmd.h> #include "util/header.h" #include <subcmd/parse-options.h> #include "util/perf_regs.h" #include "util/session.h" #include "util/tool.h" #include "util/map.h" #include "util/srcline.h" #include "util/symbol.h" #include "util/thread.h" #include "util/trace-event.h" #include "util/env.h" #include "util/evlist.h" #include "util/evsel.h" #include "util/evsel_fprintf.h" #include "util/evswitch.h" #include "util/sort.h" #include "util/data.h" #include "util/auxtrace.h" #include "util/cpumap.h" #include "util/thread_map.h" #include "util/stat.h" #include "util/color.h" #include "util/string2.h" #include "util/thread-stack.h" #include "util/time-utils.h" #include "util/path.h" #include "util/event.h" #include "util/mem-info.h" #include "ui/ui.h" #include "print_binary.h" #include "print_insn.h" #include "archinsn.h" #include <linux/bitmap.h> #include <linux/kernel.h> #include <linux/stringify.h> #include <linux/time64.h> #include <linux/zalloc.h> #include <sys/utsname.h> #include "asm/bug.h" #include "util/mem-events.h" #include "util/dump-insn.h" #include <dirent.h> #include <errno.h> #include <inttypes.h> #include <signal.h> #include <sys/param.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <subcmd/pager.h> #include <perf/evlist.h> #include <linux/err.h> #include "util/dlfilter.h" #include "util/record.h" #include "util/util.h" #include "util/cgroup.h" #include "util/annotate.h" #include "perf.h" #include <linux/ctype.h> #ifdef HAVE_LIBTRACEEVENT #include <event-parse.h> #endif static char const *script_name; static char const *generate_script_lang; static bool reltime; static bool deltatime; static u64 initial_time; static u64 previous_time; static bool debug_mode; static u64 last_timestamp; static u64 nr_unordered; static bool no_callchain; static bool latency_format; static bool system_wide; static bool print_flags; static const char *cpu_list; static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); static struct perf_stat_config stat_config; static int max_blocks; static bool native_arch; static struct dlfilter *dlfilter; static int dlargc; static char **dlargv; unsigned int scripting_max_stack = PERF_MAX_STACK_DEPTH; enum perf_output_field { PERF_OUTPUT_COMM = 1ULL << 0, PERF_OUTPUT_TID = 1ULL << 1, PERF_OUTPUT_PID = 1ULL << 2, PERF_OUTPUT_TIME = 1ULL << 3, PERF_OUTPUT_CPU = 1ULL << 4, PERF_OUTPUT_EVNAME = 1ULL << 5, PERF_OUTPUT_TRACE = 1ULL << 6, PERF_OUTPUT_IP = 1ULL << 7, PERF_OUTPUT_SYM = 1ULL << 8, PERF_OUTPUT_DSO = 1ULL << 9, PERF_OUTPUT_ADDR = 1ULL << 10, PERF_OUTPUT_SYMOFFSET = 1ULL << 11, PERF_OUTPUT_SRCLINE = 1ULL << 12, PERF_OUTPUT_PERIOD = 1ULL << 13, PERF_OUTPUT_IREGS = 1ULL << 14, PERF_OUTPUT_BRSTACK = 1ULL << 15, PERF_OUTPUT_BRSTACKSYM = 1ULL << 16, PERF_OUTPUT_DATA_SRC = 1ULL << 17, PERF_OUTPUT_WEIGHT = 1ULL << 18, PERF_OUTPUT_BPF_OUTPUT = 1ULL << 19, PERF_OUTPUT_CALLINDENT = 1ULL << 20, PERF_OUTPUT_INSN = 1ULL << 21, PERF_OUTPUT_INSNLEN = 1ULL << 22, PERF_OUTPUT_BRSTACKINSN = 1ULL << 23, PERF_OUTPUT_BRSTACKOFF = 1ULL << 24, PERF_OUTPUT_SYNTH = 1ULL << 25, PERF_OUTPUT_PHYS_ADDR = 1ULL << 26, PERF_OUTPUT_UREGS = 1ULL << 27, PERF_OUTPUT_METRIC = 1ULL << 28, PERF_OUTPUT_MISC = 1ULL << 29, PERF_OUTPUT_SRCCODE = 1ULL << 30, PERF_OUTPUT_IPC = 1ULL << 31, PERF_OUTPUT_TOD = 1ULL << 32, PERF_OUTPUT_DATA_PAGE_SIZE = 1ULL << 33, PERF_OUTPUT_CODE_PAGE_SIZE = 1ULL << 34, PERF_OUTPUT_INS_LAT = 1ULL << 35, PERF_OUTPUT_BRSTACKINSNLEN = 1ULL << 36, PERF_OUTPUT_MACHINE_PID = 1ULL << 37, PERF_OUTPUT_VCPU = 1ULL << 38, PERF_OUTPUT_CGROUP = 1ULL << 39, PERF_OUTPUT_RETIRE_LAT = 1ULL << 40, PERF_OUTPUT_DSOFF = 1ULL << 41, PERF_OUTPUT_DISASM = 1ULL << 42, PERF_OUTPUT_BRSTACKDISASM = 1ULL << 43, PERF_OUTPUT_BRCNTR = 1ULL << 44, }; struct perf_script { struct perf_tool tool; struct perf_session *session; bool show_task_events; bool show_mmap_events; bool show_switch_events; bool show_namespace_events; bool show_lost_events; bool show_round_events; bool show_bpf_events; bool show_cgroup_events; bool show_text_poke_events; bool allocated; bool per_event_dump; bool stitch_lbr; struct evswitch evswitch; struct perf_cpu_map *cpus; struct perf_thread_map *threads; int name_width; const char *time_str; struct perf_time_interval *ptime_range; int range_size; int range_num; }; struct output_option { const char *str; enum perf_output_field field; } all_output_options[] = { {.str = "comm", .field = PERF_OUTPUT_COMM}, {.str = "tid", .field = PERF_OUTPUT_TID}, {.str = "pid", .field = PERF_OUTPUT_PID}, {.str = "time", .field = PERF_OUTPUT_TIME}, {.str = "cpu", .field = PERF_OUTPUT_CPU}, {.str = "event", .field = PERF_OUTPUT_EVNAME}, {.str = "trace", .field = PERF_OUTPUT_TRACE}, {.str = "ip", .field = PERF_OUTPUT_IP}, {.str = "sym", .field = PERF_OUTPUT_SYM}, {.str = "dso", .field = PERF_OUTPUT_DSO}, {.str = "dsoff", .field = PERF_OUTPUT_DSOFF}, {.str = "addr", .field = PERF_OUTPUT_ADDR}, {.str = "symoff", .field = PERF_OUTPUT_SYMOFFSET}, {.str = "srcline", .field = PERF_OUTPUT_SRCLINE}, {.str = "period", .field = PERF_OUTPUT_PERIOD}, {.str = "iregs", .field = PERF_OUTPUT_IREGS}, {.str = "uregs", .field = PERF_OUTPUT_UREGS}, {.str = "brstack", .field = PERF_OUTPUT_BRSTACK}, {.str = "brstacksym", .field = PERF_OUTPUT_BRSTACKSYM}, {.str = "data_src", .field = PERF_OUTPUT_DATA_SRC}, {.str = "weight", .field = PERF_OUTPUT_WEIGHT}, {.str = "bpf-output", .field = PERF_OUTPUT_BPF_OUTPUT}, {.str = "callindent", .field = PERF_OUTPUT_CALLINDENT}, {.str = "insn", .field = PERF_OUTPUT_INSN}, {.str = "disasm", .field = PERF_OUTPUT_DISASM}, {.str = "insnlen", .field = PERF_OUTPUT_INSNLEN}, {.str = "brstackinsn", .field = PERF_OUTPUT_BRSTACKINSN}, {.str = "brstackoff", .field = PERF_OUTPUT_BRSTACKOFF}, {.str = "synth", .field = PERF_OUTPUT_SYNTH}, {.str = "phys_addr", .field = PERF_OUTPUT_PHYS_ADDR}, {.str = "metric", .field = PERF_OUTPUT_METRIC}, {.str = "misc", .field = PERF_OUTPUT_MISC}, {.str = "srccode", .field = PERF_OUTPUT_SRCCODE}, {.str = "ipc", .field = PERF_OUTPUT_IPC}, {.str = "tod", .field = PERF_OUTPUT_TOD}, {.str = "data_page_size", .field = PERF_OUTPUT_DATA_PAGE_SIZE}, {.str = "code_page_size", .field = PERF_OUTPUT_CODE_PAGE_SIZE}, {.str = "ins_lat", .field = PERF_OUTPUT_INS_LAT}, {.str = "brstackinsnlen", .field = PERF_OUTPUT_BRSTACKINSNLEN}, {.str = "machine_pid", .field = PERF_OUTPUT_MACHINE_PID}, {.str = "vcpu", .field = PERF_OUTPUT_VCPU}, {.str = "cgroup", .field = PERF_OUTPUT_CGROUP}, {.str = "retire_lat", .field = PERF_OUTPUT_RETIRE_LAT}, {.str = "brstackdisasm", .field = PERF_OUTPUT_BRSTACKDISASM}, {.str = "brcntr", .field = PERF_OUTPUT_BRCNTR}, }; enum { OUTPUT_TYPE_SYNTH = PERF_TYPE_MAX, OUTPUT_TYPE_OTHER, OUTPUT_TYPE_MAX }; /* default set to maintain compatibility with current format */ static struct { bool user_set; bool wildcard_set; unsigned int print_ip_opts; u64 fields; u64 invalid_fields; u64 user_set_fields; u64 user_unset_fields; } output[OUTPUT_TYPE_MAX] = { [PERF_TYPE_HARDWARE] = { .user_set = false, .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP | PERF_OUTPUT_SYM | PERF_OUTPUT_SYMOFFSET | PERF_OUTPUT_DSO | PERF_OUTPUT_PERIOD, .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT, }, [PERF_TYPE_SOFTWARE] = { .user_set = false, .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP | PERF_OUTPUT_SYM | PERF_OUTPUT_SYMOFFSET | PERF_OUTPUT_DSO | PERF_OUTPUT_PERIOD | PERF_OUTPUT_BPF_OUTPUT, .invalid_fields = PERF_OUTPUT_TRACE, }, [PERF_TYPE_TRACEPOINT] = { .user_set = false, .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | PERF_OUTPUT_EVNAME | PERF_OUTPUT_TRACE }, [PERF_TYPE_HW_CACHE] = { .user_set = false, .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP | PERF_OUTPUT_SYM | PERF_OUTPUT_SYMOFFSET | PERF_OUTPUT_DSO | PERF_OUTPUT_PERIOD, .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT, }, [PERF_TYPE_RAW] = { .user_set = false, .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP | PERF_OUTPUT_SYM | PERF_OUTPUT_SYMOFFSET | PERF_OUTPUT_DSO | PERF_OUTPUT_PERIOD | PERF_OUTPUT_ADDR | PERF_OUTPUT_DATA_SRC | PERF_OUTPUT_WEIGHT | PERF_OUTPUT_PHYS_ADDR | PERF_OUTPUT_DATA_PAGE_SIZE | PERF_OUTPUT_CODE_PAGE_SIZE | PERF_OUTPUT_INS_LAT | PERF_OUTPUT_RETIRE_LAT, .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT, }, [PERF_TYPE_BREAKPOINT] = { .user_set = false, .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP | PERF_OUTPUT_SYM | PERF_OUTPUT_SYMOFFSET | PERF_OUTPUT_DSO | PERF_OUTPUT_PERIOD, .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT, }, [OUTPUT_TYPE_SYNTH] = { .user_set = false, .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP | PERF_OUTPUT_SYM | PERF_OUTPUT_SYMOFFSET | PERF_OUTPUT_DSO | PERF_OUTPUT_SYNTH, .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT, }, [OUTPUT_TYPE_OTHER] = { .user_set = false, .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP | PERF_OUTPUT_SYM | PERF_OUTPUT_SYMOFFSET | PERF_OUTPUT_DSO | PERF_OUTPUT_PERIOD, .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT, }, }; struct evsel_script { char *filename; FILE *fp; u64 samples; /* For metric output */ u64 val; int gnum; }; static inline struct evsel_script *evsel_script(struct evsel *evsel) { return (struct evsel_script *)evsel->priv; } static struct evsel_script *evsel_script__new(struct evsel *evsel, struct perf_data *data) { struct evsel_script *es = zalloc(sizeof(*es)); if (es != NULL) { if (asprintf(&es->filename, "%s.%s.dump", data->file.path, evsel__name(evsel)) < 0) goto out_free; es->fp = fopen(es->filename, "w"); if (es->fp == NULL) goto out_free_filename; } return es; out_free_filename: zfree(&es->filename); out_free: free(es); return NULL; } static void evsel_script__delete(struct evsel_script *es) { zfree(&es->filename); fclose(es->fp); es->fp = NULL; free(es); } static int evsel_script__fprintf(struct evsel_script *es, FILE *fp) { struct stat st; fstat(fileno(es->fp), &st); return fprintf(fp, "[ perf script: Wrote %.3f MB %s (%" PRIu64 " samples) ]\n", st.st_size / 1024.0 / 1024.0, es->filename, es->samples); } static inline int output_type(unsigned int type) { switch (type) { case PERF_TYPE_SYNTH: return OUTPUT_TYPE_SYNTH; default: if (type < PERF_TYPE_MAX) return type; } return OUTPUT_TYPE_OTHER; } static bool output_set_by_user(void) { int j; for (j = 0; j < OUTPUT_TYPE_MAX; ++j) { if (output[j].user_set) return true; } return false; } static const char *output_field2str(enum perf_output_field field) { int i, imax = ARRAY_SIZE(all_output_options); const char *str = ""; for (i = 0; i < imax; ++i) { if (all_output_options[i].field == field) { str = all_output_options[i].str; break; } } return str; } #define PRINT_FIELD(x) (output[output_type(attr->type)].fields & PERF_OUTPUT_##x) static int evsel__do_check_stype(struct evsel *evsel, u64 sample_type, const char *sample_msg, enum perf_output_field field, bool allow_user_set) { struct perf_event_attr *attr = &evsel->core.attr; int type = output_type(attr->type); const char *evname; if (attr->sample_type & sample_type) return 0; if (output[type].user_set_fields & field) { if (allow_user_set) return 0; evname = evsel__name(evsel); pr_err("Samples for '%s' event do not have %s attribute set. " "Cannot print '%s' field.\n", evname, sample_msg, output_field2str(field)); return -1; } /* user did not ask for it explicitly so remove from the default list */ output[type].fields &= ~field; evname = evsel__name(evsel); pr_debug("Samples for '%s' event do not have %s attribute set. " "Skipping '%s' field.\n", evname, sample_msg, output_field2str(field)); return 0; } static int evsel__check_stype(struct evsel *evsel, u64 sample_type, const char *sample_msg, enum perf_output_field field) { return evsel__do_check_stype(evsel, sample_type, sample_msg, field, false); } static int evsel__check_attr(struct evsel *evsel, struct perf_session *session) { struct perf_event_attr *attr = &evsel->core.attr; bool allow_user_set; if (evsel__is_dummy_event(evsel)) return 0; if (perf_header__has_feat(&session->header, HEADER_STAT)) return 0; allow_user_set = perf_header__has_feat(&session->header, HEADER_AUXTRACE); if (PRINT_FIELD(TRACE) && !perf_session__has_traces(session, "record -R")) return -EINVAL; if (PRINT_FIELD(IP)) { if (evsel__check_stype(evsel, PERF_SAMPLE_IP, "IP", PERF_OUTPUT_IP)) return -EINVAL; } if (PRINT_FIELD(ADDR) && evsel__do_check_stype(evsel, PERF_SAMPLE_ADDR, "ADDR", PERF_OUTPUT_ADDR, allow_user_set)) return -EINVAL; if (PRINT_FIELD(DATA_SRC) && evsel__do_check_stype(evsel, PERF_SAMPLE_DATA_SRC, "DATA_SRC", PERF_OUTPUT_DATA_SRC, allow_user_set)) return -EINVAL; if (PRINT_FIELD(WEIGHT) && evsel__do_check_stype(evsel, PERF_SAMPLE_WEIGHT_TYPE, "WEIGHT", PERF_OUTPUT_WEIGHT, allow_user_set)) return -EINVAL; if (PRINT_FIELD(SYM) && !(evsel->core.attr.sample_type & (PERF_SAMPLE_IP|PERF_SAMPLE_ADDR))) { pr_err("Display of symbols requested but neither sample IP nor " "sample address\navailable. Hence, no addresses to convert "