#include "builtin.h" #include "perf.h"#include "util/cache.h"#include "util/debug.h"#include "util/exec_cmd.h"#include "util/header.h"#include "util/parse-options.h"#include "util/session.h"#include "util/tool.h"#include "util/symbol.h"#include "util/thread.h"#include "util/trace-event.h"#include "util/util.h"#include "util/evlist.h"#include "util/evsel.h"#include "util/sort.h"#include "util/data.h"#include "util/auxtrace.h"#include <linux/bitmap.h> static char const *script_name;static char const *generate_script_lang;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); enum perf_output_field { PERF_OUTPUT_COMM = 1U << 0, PERF_OUTPUT_TID = 1U << 1, PERF_OUTPUT_PID = 1U << 2, PERF_OUTPUT_TIME = 1U << 3, PERF_OUTPUT_CPU = 1U << 4, PERF_OUTPUT_EVNAME = 1U << 5, PERF_OUTPUT_TRACE = 1U << 6, PERF_OUTPUT_IP = 1U << 7, PERF_OUTPUT_SYM = 1U << 8, PERF_OUTPUT_DSO = 1U << 9, PERF_OUTPUT_ADDR = 1U << 10, PERF_OUTPUT_SYMOFFSET = 1U << 11, PERF_OUTPUT_SRCLINE = 1U << 12, PERF_OUTPUT_PERIOD = 1U << 13,}; 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 = "addr", .field = PERF_OUTPUT_ADDR}, {.str = "symoff", .field = PERF_OUTPUT_SYMOFFSET}, {.str = "srcline", .field = PERF_OUTPUT_SRCLINE}, {.str = "period", .field = PERF_OUTPUT_PERIOD},}; /* 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;} output[PERF_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_DSO | PERF_OUTPUT_PERIOD, .invalid_fields = PERF_OUTPUT_TRACE, }, [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_DSO | PERF_OUTPUT_PERIOD, .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_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_DSO | PERF_OUTPUT_PERIOD, .invalid_fields = PERF_OUTPUT_TRACE, },}; static bool output_set_by_user(void){ int j; for (j = 0; j < PERF_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[attr->type].fields & PERF_OUTPUT_##x) static int perf_evsel__do_check_stype(struct perf_evsel *evsel, u64 sample_type, const char *sample_msg, enum perf_output_field field, bool allow_user_set){ struct perf_event_attr *attr = &evsel->attr; int type = attr->type; const char *evname; if (attr->sample_type & sample_type) return 0; if (output[type].user_set) { if (allow_user_set) return 0; evname = perf_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 = perf_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 perf_evsel__check_stype(struct perf_evsel *evsel, u64 sample_type, const char *sample_msg, enum perf_output_field field){ return perf_evsel__do_check_stype(evsel, sample_type, sample_msg, field, false);} static int perf_evsel__check_attr(struct perf_evsel *evsel, struct perf_session *session){ struct perf_event_attr *attr = &evsel->attr; bool allow_user_set; 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 (perf_evsel__check_stype(evsel, PERF_SAMPLE_IP, "IP", PERF_OUTPUT_IP)) return -EINVAL; } if (PRINT_FIELD(ADDR) && perf_evsel__do_check_stype(evsel, PERF_SAMPLE_ADDR, "ADDR", PERF_OUTPUT_ADDR, allow_user_set)) return -EINVAL; if (PRINT_FIELD(SYM) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) { pr_err("Display of symbols requested but neither sample IP nor " "sample address\nis selected. Hence, no addresses to convert " "to symbols.\n"); return -EINVAL; } if (PRINT_FIELD(SYMOFFSET) && !PRINT_FIELD(SYM)) { pr_err("Display of offsets requested but symbol is not" "selected.\n"); return -EINVAL; } if (PRINT_FIELD(DSO) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) { pr_err("Display of DSO requested but neither sample IP nor " "sample address\nis selected. Hence, no addresses to convert " "to DSO.\n"); return -EINVAL; } if (PRINT_FIELD(SRCLINE) && !PRINT_FIELD(IP)) { pr_err("Display of source line number requested but sample IP is not\n" "selected. Hence, no address to lookup the source line number.\n"); return -EINVAL; } if ((PRINT_FIELD(PID) || PRINT_FIELD(TID)) && perf_evsel__check_stype(evsel, PERF_SAMPLE_TID, "TID", PERF_OUTPUT_TID|PERF_OUTPUT_PID)) return -EINVAL; if (PRINT_FIELD(TIME) && perf_evsel__check_stype(evsel, PERF_SAMPLE_TIME, "TIME", PERF_OUTPUT_TIME)) return -EINVAL; if (PRINT_FIELD(CPU) && perf_evsel__do_check_stype(evsel, PERF_SAMPLE_CPU, "CPU", PERF_OUTPUT_CPU, allow_user_set)) return -EINVAL; if (PRINT_FIELD(PERIOD) && perf_evsel__check_stype(evsel, PERF_SAMPLE_PERIOD, "PERIOD", PERF_OUTPUT_PERIOD)) return -EINVAL; return 0;} static void set_print_ip_opts(struct perf_event_attr *attr){ unsigned int type = attr->type; output[type].print_ip_opts = 0; if (PRINT_FIELD(IP)) output[type].print_ip_opts |= PRINT_IP_OPT_IP; if (PRINT_FIELD(SYM)) output[type].print_ip_opts |= PRINT_IP_OPT_SYM; if (PRINT_FIELD(DSO)) output[type].print_ip_opts |= PRINT_IP_OPT_DSO; if (PRINT_FIELD(SYMOFFSET)) output[type].print_ip_opts |= PRINT_IP_OPT_SYMOFFSET; if (PRINT_FIELD(SRCLINE)) output[type].print_ip_opts |= PRINT_IP_OPT_SRCLINE;} /* * verify all user requested events exist and the samples * have the expected data */static int perf_session__check_output_opt(struct perf_session *session){ int j; struct perf_evsel *evsel; for (j = 0; j < PERF_TYPE_MAX; ++j) { evsel = perf_session__find_first_evtype(session, j); /* * even if fields is set to 0 (ie., show nothing) event must * exist if user explicitly includes it on the command line */ if (!evsel && output[j].user_set && !output[j].wildcard_set) { pr_err("%s events do not exist. " "Remove corresponding -f option to proceed.\n", event_type(j)); return -1; } if (evsel && output[j].fields && perf_evsel__check_attr(evsel, session)) return -1; if (evsel == NULL) continue; set_print_ip_opts(&evsel->attr); } if (!no_callchain) { bool use_callchain = false; evlist__for_each(session->evlist, evsel) { if (evsel->attr.sample_type & PERF_SAMPLE_CALLCHAIN) { use_callchain = true; break; } } if (!use_callchain) symbol_conf.use_callchain = false; } /* * set default for tracepoints to print symbols only * if callchains are present */ if (symbol_conf.use_callchain && !output[PERF_TYPE_TRACEPOINT].user_set) { struct perf_event_attr *attr; j = PERF_TYPE_TRACEPOINT; evsel = perf_session__find_first_evtype(session, j); if (evsel == NULL) goto out; attr = &evsel->attr; if (attr->sample_type & PERF_SAMPLE_CALLCHAIN) { output[j].fields |= PERF_OUTPUT_IP; output[j].fields |= PERF_OUTPUT_SYM; output[j].fields |= PERF_OUTPUT_DSO; set_print_ip_opts(attr); } } out: return 0;} static void print_sample_start(struct perf_sample *sample, struct thread *thread, struct perf_evsel *evsel){ struct perf_event_attr *attr = &evsel->attr; unsigned long secs; unsigned long usecs; unsigned long long nsecs; if (PRINT_FIELD(COMM)) { if (latency_format) printf("%8.8s ", thread__comm_str(thread)); else if (PRINT_FIELD(IP) && symbol_conf.use_callchain) printf("%s ", thread__comm_str(thread)); else printf("%16s ", thread__comm_str(thread)); } if (PRINT_FIELD(PID) && PRINT_FIELD(TID)) printf("%5d/%-5d ", sample->pid, sample->tid); else if (PRINT_FIELD(PID)) printf("%5d ", sample->pid); else if (PRINT_FIELD(TID)) printf("%5d ", sample->tid); if (PRINT_FIELD(CPU)) { if (latency_format) printf("%3d ", sample->cpu); else printf("[%03d] ", sample->cpu); } if (PRINT_FIELD(TIME)) { nsecs = sample->time; secs = nsecs / NSECS_PER_SEC; nsecs -= secs * NSECS_PER_SEC; usecs = nsecs / NSECS_PER_USEC; printf("%5lu.%06lu: ", secs, usecs); }} static void print_sample_addr(union perf_event *event, struct perf_sample *sample, struct thread *thread, struct perf_event_attr *attr){ struct addr_location al; printf("%16" PRIx64, sample->addr); if (!sample_addr_correlates_sym(attr)) return; perf_event__preprocess_sample_addr(event, sample, thread, &al); if (PRINT_FIELD(SYM)) { printf(" "); if (PRINT_FIELD(SYMOFFSET)) symbol__fprintf_symname_offs(al.sym, &al, stdout); else symbol__fprintf_symname(al.sym, stdout); } if (PRINT_FIELD(DSO)) { printf(" ("); map__fprintf_dsoname(al.map, stdout); printf(")"); }} static void print_sample_bts(union perf_event *event, struct perf_sample *sample, struct perf_evsel *evsel, struct thread *thread, struct addr_location *al){ struct perf_event_attr *attr = &evsel->attr; bool print_srcline_last = false; /* print branch_from information */ if (PRINT_FIELD(IP)) { unsigned int print_opts = output[attr->type].print_ip_opts; if (symbol_conf.use_callchain && sample->callchain) { printf("\n"); } else { printf(" "); if (print_opts & PRINT_IP_OPT_SRCLINE) { print_srcline_last = true; print_opts &= ~PRINT_IP_OPT_SRCLINE; } } perf_evsel__print_ip(evsel, sample, al, print_opts, PERF_MAX_STACK_DEPTH); } /* print branch_to information */ if (PRINT_FIELD(ADDR) || ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) && !output[attr->type].user_set)) { printf(" => "); print_sample_addr(event, sample, thread, attr); } if (print_srcline_last) map__fprintf_srcline(al->map, al->addr, "\n ", stdout); printf("\n");} static void print_sample_flags(u32 flags){ const char *chars = PERF_IP_FLAG_CHARS; const int n = strlen(PERF_IP_FLAG_CHARS); char str[33]; int i, pos = 0; for (i = 0; i < n; i++, flags >>= 1) { if (flags & 1) str[pos++] = chars[i]; } for (; i < 32; i++, flags >>= 1) { if (flags & 1) str[pos++] = '?'; } str[pos] = 0; printf(" %-4s ", str);} static void process_event(union perf_event *event, struct perf_sample *sample, struct perf_evsel *evsel, struct addr_location *al){ struct thread *thread = al->thread; struct perf_event_attr *attr = &evsel->attr; if (output[attr->type].fields == 0) return; print_sample_start(sample, thread, evsel); if (PRINT_FIELD(PERIOD)) printf("%10" PRIu64 " ", sample->period); if (PRINT_FIELD(EVNAME)) { const char *evname = perf_evsel__name(evsel); printf("%s: ", evname ? evname : "[unknown]");Lines 1–500 of 1898. Load more
#include "builtin.h" #include "perf.h" #include "util/cache.h" #include "util/debug.h" #include "util/exec_cmd.h" #include "util/header.h" #include "util/parse-options.h" #include "util/session.h" #include "util/tool.h" #include "util/symbol.h" #include "util/thread.h" #include "util/trace-event.h" #include "util/util.h" #include "util/evlist.h" #include "util/evsel.h" #include "util/sort.h" #include "util/data.h" #include "util/auxtrace.h" #include <linux/bitmap.h> static char const *script_name; static char const *generate_script_lang; 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); enum perf_output_field { PERF_OUTPUT_COMM = 1U << 0, PERF_OUTPUT_TID = 1U << 1, PERF_OUTPUT_PID = 1U << 2, PERF_OUTPUT_TIME = 1U << 3, PERF_OUTPUT_CPU = 1U << 4, PERF_OUTPUT_EVNAME = 1U << 5, PERF_OUTPUT_TRACE = 1U << 6, PERF_OUTPUT_IP = 1U << 7, PERF_OUTPUT_SYM = 1U << 8, PERF_OUTPUT_DSO = 1U << 9, PERF_OUTPUT_ADDR = 1U << 10, PERF_OUTPUT_SYMOFFSET = 1U << 11, PERF_OUTPUT_SRCLINE = 1U << 12, PERF_OUTPUT_PERIOD = 1U << 13, }; 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 = "addr", .field = PERF_OUTPUT_ADDR}, {.str = "symoff", .field = PERF_OUTPUT_SYMOFFSET}, {.str = "srcline", .field = PERF_OUTPUT_SRCLINE}, {.str = "period", .field = PERF_OUTPUT_PERIOD}, }; /* 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; } output[PERF_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_DSO | PERF_OUTPUT_PERIOD, .invalid_fields = PERF_OUTPUT_TRACE, }, [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_DSO | PERF_OUTPUT_PERIOD, .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_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_DSO | PERF_OUTPUT_PERIOD, .invalid_fields = PERF_OUTPUT_TRACE, }, }; static bool output_set_by_user(void) { int j; for (j = 0; j < PERF_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[attr->type].fields & PERF_OUTPUT_##x) static int perf_evsel__do_check_stype(struct perf_evsel *evsel, u64 sample_type, const char *sample_msg, enum perf_output_field field, bool allow_user_set) { struct perf_event_attr *attr = &evsel->attr; int type = attr->type; const char *evname; if (attr->sample_type & sample_type) return 0; if (output[type].user_set) { if (allow_user_set) return 0; evname = perf_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 = perf_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 perf_evsel__check_stype(struct perf_evsel *evsel, u64 sample_type, const char *sample_msg, enum perf_output_field field) { return perf_evsel__do_check_stype(evsel, sample_type, sample_msg, field, false); } static int perf_evsel__check_attr(struct perf_evsel *evsel, struct perf_session *session) { struct perf_event_attr *attr = &evsel->attr; bool allow_user_set; 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 (perf_evsel__check_stype(evsel, PERF_SAMPLE_IP, "IP", PERF_OUTPUT_IP)) return -EINVAL; } if (PRINT_FIELD(ADDR) && perf_evsel__do_check_stype(evsel, PERF_SAMPLE_ADDR, "ADDR", PERF_OUTPUT_ADDR, allow_user_set)) return -EINVAL; if (PRINT_FIELD(SYM) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) { pr_err("Display of symbols requested but neither sample IP nor " "sample address\nis selected. Hence, no addresses to convert " "to symbols.\n"); return -EINVAL; } if (PRINT_FIELD(SYMOFFSET) && !PRINT_FIELD(SYM)) { pr_err("Display of offsets requested but symbol is not" "selected.\n"); return -EINVAL; } if (PRINT_FIELD(DSO) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) { pr_err("Display of DSO requested but neither sample IP nor " "sample address\nis selected. Hence, no addresses to convert " "to DSO.\n"); return -EINVAL; } if (PRINT_FIELD(SRCLINE) && !PRINT_FIELD(IP)) { pr_err("Display of source line number requested but sample IP is not\n" "selected. Hence, no address to lookup the source line number.\n"); return -EINVAL; } if ((PRINT_FIELD(PID) || PRINT_FIELD(TID)) && perf_evsel__check_stype(evsel, PERF_SAMPLE_TID, "TID", PERF_OUTPUT_TID|PERF_OUTPUT_PID)) return -EINVAL; if (PRINT_FIELD(TIME) && perf_evsel__check_stype(evsel, PERF_SAMPLE_TIME, "TIME", PERF_OUTPUT_TIME)) return -EINVAL; if (PRINT_FIELD(CPU) && perf_evsel__do_check_stype(evsel, PERF_SAMPLE_CPU, "CPU", PERF_OUTPUT_CPU, allow_user_set)) return -EINVAL; if (PRINT_FIELD(PERIOD) && perf_evsel__check_stype(evsel, PERF_SAMPLE_PERIOD, "PERIOD", PERF_OUTPUT_PERIOD)) return -EINVAL; return 0; } static void set_print_ip_opts(struct perf_event_attr *attr) { unsigned int type = attr->type; output[type].print_ip_opts = 0; if (PRINT_FIELD(IP)) output[type].print_ip_opts |= PRINT_IP_OPT_IP; if (PRINT_FIELD(SYM)) output[type].print_ip_opts |= PRINT_IP_OPT_SYM; if (PRINT_FIELD(DSO)) output[type].print_ip_opts |= PRINT_IP_OPT_DSO; if (PRINT_FIELD(SYMOFFSET)) output[type].print_ip_opts |= PRINT_IP_OPT_SYMOFFSET; if (PRINT_FIELD(SRCLINE)) output[type].print_ip_opts |= PRINT_IP_OPT_SRCLINE; } /* * verify all user requested events exist and the samples * have the expected data */ static int perf_session__check_output_opt(struct perf_session *session) { int j; struct perf_evsel *evsel; for (j = 0; j < PERF_TYPE_MAX; ++j) { evsel = perf_session__find_first_evtype(session, j); /* * even if fields is set to 0 (ie., show nothing) event must * exist if user explicitly includes it on the command line */ if (!evsel && output[j].user_set && !output[j].wildcard_set) { pr_err("%s events do not exist. " "Remove corresponding -f option to proceed.\n", event_type(j)); return -1; } if (evsel && output[j].fields && perf_evsel__check_attr(evsel, session)) return -1; if (evsel == NULL) continue; set_print_ip_opts(&evsel->attr); } if (!no_callchain) { bool use_callchain = false; evlist__for_each(session->evlist, evsel) { if (evsel->attr.sample_type & PERF_SAMPLE_CALLCHAIN) { use_callchain = true; break; } } if (!use_callchain) symbol_conf.use_callchain = false; } /* * set default for tracepoints to print symbols only * if callchains are present */ if (symbol_conf.use_callchain && !output[PERF_TYPE_TRACEPOINT].user_set) { struct perf_event_attr *attr; j = PERF_TYPE_TRACEPOINT; evsel = perf_session__find_first_evtype(session, j); if (evsel == NULL) goto out; attr = &evsel->attr; if (attr->sample_type & PERF_SAMPLE_CALLCHAIN) { output[j].fields |= PERF_OUTPUT_IP; output[j].fields |= PERF_OUTPUT_SYM; output[j].fields |= PERF_OUTPUT_DSO; set_print_ip_opts(attr); } } out: return 0; } static void print_sample_start(struct perf_sample *sample, struct thread *thread, struct perf_evsel *evsel) { struct perf_event_attr *attr = &evsel->attr; unsigned long secs; unsigned long usecs; unsigned long long nsecs; if (PRINT_FIELD(COMM)) { if (latency_format) printf("%8.8s ", thread__comm_str(thread)); else if (PRINT_FIELD(IP) && symbol_conf.use_callchain) printf("%s ", thread__comm_str(thread)); else printf("%16s ", thread__comm_str(thread)); } if (PRINT_FIELD(PID) && PRINT_FIELD(TID)) printf("%5d/%-5d ", sample->pid, sample->tid); else if (PRINT_FIELD(PID)) printf("%5d ", sample->pid); else if (PRINT_FIELD(TID)) printf("%5d ", sample->tid); if (PRINT_FIELD(CPU)) { if (latency_format) printf("%3d ", sample->cpu); else printf("[%03d] ", sample->cpu); } if (PRINT_FIELD(TIME)) { nsecs = sample->time; secs = nsecs / NSECS_PER_SEC; nsecs -= secs * NSECS_PER_SEC; usecs = nsecs / NSECS_PER_USEC; printf("%5lu.%06lu: ", secs, usecs); } } static void print_sample_addr(union perf_event *event, struct perf_sample *sample, struct thread *thread, struct perf_event_attr *attr) { struct addr_location al; printf("%16" PRIx64, sample->addr); if (!sample_addr_correlates_sym(attr)) return; perf_event__preprocess_sample_addr(event, sample, thread, &al); if (PRINT_FIELD(SYM)) { printf(" "); if (PRINT_FIELD(SYMOFFSET)) symbol__fprintf_symname_offs(al.sym, &al, stdout); else symbol__fprintf_symname(al.sym, stdout); } if (PRINT_FIELD(DSO)) { printf(" ("); map__fprintf_dsoname(al.map, stdout); printf(")"); } } static void print_sample_bts(union perf_event *event, struct perf_sample *sample, struct perf_evsel *evsel, struct thread *thread, struct addr_location *al) { struct perf_event_attr *attr = &evsel->attr; bool print_srcline_last = false; /* print branch_from information */ if (PRINT_FIELD(IP)) { unsigned int print_opts = output[attr->type].print_ip_opts; if (symbol_conf.use_callchain && sample->callchain) { printf("\n"); } else { printf(" "); if (print_opts & PRINT_IP_OPT_SRCLINE) { print_srcline_last = true; print_opts &= ~PRINT_IP_OPT_SRCLINE; } } perf_evsel__print_ip(evsel, sample, al, print_opts, PERF_MAX_STACK_DEPTH); } /* print branch_to information */ if (PRINT_FIELD(ADDR) || ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) && !output[attr->type].user_set)) { printf(" => "); print_sample_addr(event, sample, thread, attr); } if (print_srcline_last) map__fprintf_srcline(al->map, al->addr, "\n ", stdout); printf("\n"); } static void print_sample_flags(u32 flags) { const char *chars = PERF_IP_FLAG_CHARS; const int n = strlen(PERF_IP_FLAG_CHARS); char str[33]; int i, pos = 0; for (i = 0; i < n; i++, flags >>= 1) { if (flags & 1) str[pos++] = chars[i]; } for (; i < 32; i++, flags >>= 1) { if (flags & 1) str[pos++] = '?'; } str[pos] = 0; printf(" %-4s ", str); } static void process_event(union perf_event *event, struct perf_sample *sample, struct perf_evsel *evsel, struct addr_location *al) { struct thread *thread = al->thread; struct perf_event_attr *attr = &evsel->attr; if (output[attr->type].fields == 0) return; print_sample_start(sample, thread, evsel); if (PRINT_FIELD(PERIOD)) printf("%10" PRIu64 " ", sample->period); if (PRINT_FIELD(EVNAME)) { const char *evname = perf_evsel__name(evsel); printf("%s: ", evname ? evname : "[unknown]");