diff options
Diffstat (limited to 'tools/perf/builtin-script.c')
-rw-r--r-- | tools/perf/builtin-script.c | 278 |
1 files changed, 205 insertions, 73 deletions
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index c82b033e8942..7ca238277d83 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -15,6 +15,7 @@ #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" @@ -123,6 +124,9 @@ enum perf_output_field { 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, }; struct perf_script { @@ -190,6 +194,9 @@ struct output_option { {.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}, }; enum { @@ -438,6 +445,9 @@ 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; @@ -458,11 +468,11 @@ static int evsel__check_attr(struct evsel *evsel, struct perf_session *session) return -EINVAL; if (PRINT_FIELD(DATA_SRC) && - evsel__check_stype(evsel, PERF_SAMPLE_DATA_SRC, "DATA_SRC", PERF_OUTPUT_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__check_stype(evsel, PERF_SAMPLE_WEIGHT_TYPE, "WEIGHT", PERF_OUTPUT_WEIGHT)) + evsel__do_check_stype(evsel, PERF_SAMPLE_WEIGHT_TYPE, "WEIGHT", PERF_OUTPUT_WEIGHT, allow_user_set)) return -EINVAL; if (PRINT_FIELD(SYM) && @@ -487,7 +497,7 @@ static int evsel__check_attr(struct evsel *evsel, struct perf_session *session) "selected. Hence, no address to lookup the source line number.\n"); return -EINVAL; } - if (PRINT_FIELD(BRSTACKINSN) && !allow_user_set && + if ((PRINT_FIELD(BRSTACKINSN) || PRINT_FIELD(BRSTACKINSNLEN)) && !allow_user_set && !(evlist__combined_branch_type(session->evlist) & PERF_SAMPLE_BRANCH_ANY)) { pr_err("Display of branch stack assembler requested, but non all-branch filter set\n" "Hint: run 'perf record -b ...'\n"); @@ -514,7 +524,7 @@ static int evsel__check_attr(struct evsel *evsel, struct perf_session *session) return -EINVAL; if (PRINT_FIELD(PHYS_ADDR) && - evsel__check_stype(evsel, PERF_SAMPLE_PHYS_ADDR, "PHYS_ADDR", PERF_OUTPUT_PHYS_ADDR)) + evsel__do_check_stype(evsel, PERF_SAMPLE_PHYS_ADDR, "PHYS_ADDR", PERF_OUTPUT_PHYS_ADDR, allow_user_set)) return -EINVAL; if (PRINT_FIELD(DATA_PAGE_SIZE) && @@ -559,6 +569,8 @@ static struct evsel *find_first_output_type(struct evlist *evlist, struct evsel *evsel; evlist__for_each_entry(evlist, evsel) { + if (evsel__is_dummy_event(evsel)) + continue; if (output_type(evsel->core.attr.type) == (int)type) return evsel; } @@ -648,7 +660,7 @@ out: return 0; } -static int perf_sample__fprintf_regs(struct regs_dump *regs, uint64_t mask, +static int perf_sample__fprintf_regs(struct regs_dump *regs, uint64_t mask, const char *arch, FILE *fp) { unsigned i = 0, r; @@ -661,7 +673,7 @@ static int perf_sample__fprintf_regs(struct regs_dump *regs, uint64_t mask, for_each_set_bit(r, (unsigned long *) &mask, sizeof(mask) * 8) { u64 val = regs->regs[i++]; - printed += fprintf(fp, "%5s:0x%"PRIx64" ", perf_reg_name(r), val); + printed += fprintf(fp, "%5s:0x%"PRIx64" ", perf_reg_name(r, arch), val); } return printed; @@ -718,17 +730,17 @@ tod_scnprintf(struct perf_script *script, char *buf, int buflen, } static int perf_sample__fprintf_iregs(struct perf_sample *sample, - struct perf_event_attr *attr, FILE *fp) + struct perf_event_attr *attr, const char *arch, FILE *fp) { return perf_sample__fprintf_regs(&sample->intr_regs, - attr->sample_regs_intr, fp); + attr->sample_regs_intr, arch, fp); } static int perf_sample__fprintf_uregs(struct perf_sample *sample, - struct perf_event_attr *attr, FILE *fp) + struct perf_event_attr *attr, const char *arch, FILE *fp) { return perf_sample__fprintf_regs(&sample->user_regs, - attr->sample_regs_user, fp); + attr->sample_regs_user, arch, fp); } static int perf_sample__fprintf_start(struct perf_script *script, @@ -743,6 +755,13 @@ static int perf_sample__fprintf_start(struct perf_script *script, int printed = 0; char tstr[128]; + if (PRINT_FIELD(MACHINE_PID) && sample->machine_pid) + printed += fprintf(fp, "VM:%5d ", sample->machine_pid); + + /* Print VCPU only for guest events i.e. with machine_pid */ + if (PRINT_FIELD(VCPU) && sample->machine_pid) + printed += fprintf(fp, "VCPU:%03d ", sample->vcpu); + if (PRINT_FIELD(COMM)) { const char *comm = thread ? thread__comm_str(thread) : ":-1"; @@ -856,6 +875,16 @@ mispred_str(struct branch_entry *br) return br->flags.predicted ? 'P' : 'M'; } +static int print_bstack_flags(FILE *fp, struct branch_entry *br) +{ + return fprintf(fp, "/%c/%c/%c/%d/%s ", + mispred_str(br), + br->flags.in_tx ? 'X' : '-', + br->flags.abort ? 'A' : '-', + br->flags.cycles, + get_branch_type(br)); +} + static int perf_sample__fprintf_brstack(struct perf_sample *sample, struct thread *thread, struct perf_event_attr *attr, FILE *fp) @@ -894,11 +923,7 @@ static int perf_sample__fprintf_brstack(struct perf_sample *sample, printed += fprintf(fp, ")"); } - printed += fprintf(fp, "/%c/%c/%c/%d ", - mispred_str(entries + i), - entries[i].flags.in_tx ? 'X' : '-', - entries[i].flags.abort ? 'A' : '-', - entries[i].flags.cycles); + printed += print_bstack_flags(fp, entries + i); } return printed; @@ -940,11 +965,7 @@ static int perf_sample__fprintf_brstacksym(struct perf_sample *sample, printed += map__fprintf_dsoname(alt.map, fp); printed += fprintf(fp, ")"); } - printed += fprintf(fp, "/%c/%c/%c/%d ", - mispred_str(entries + i), - entries[i].flags.in_tx ? 'X' : '-', - entries[i].flags.abort ? 'A' : '-', - entries[i].flags.cycles); + printed += print_bstack_flags(fp, entries + i); } return printed; @@ -990,11 +1011,7 @@ static int perf_sample__fprintf_brstackoff(struct perf_sample *sample, printed += map__fprintf_dsoname(alt.map, fp); printed += fprintf(fp, ")"); } - printed += fprintf(fp, "/%c/%c/%c/%d ", - mispred_str(entries + i), - entries[i].flags.in_tx ? 'X' : '-', - entries[i].flags.abort ? 'A' : '-', - entries[i].flags.cycles); + printed += print_bstack_flags(fp, entries + i); } return printed; @@ -1121,10 +1138,17 @@ static int print_srccode(struct thread *thread, u8 cpumode, uint64_t addr) static int ip__fprintf_jump(uint64_t ip, struct branch_entry *en, struct perf_insn *x, u8 *inbuf, int len, - int insn, FILE *fp, int *total_cycles) + int insn, FILE *fp, int *total_cycles, + struct perf_event_attr *attr) { - int printed = fprintf(fp, "\t%016" PRIx64 "\t%-30s\t#%s%s%s%s", ip, - dump_insn(x, ip, inbuf, len, NULL), + int ilen = 0; + int printed = fprintf(fp, "\t%016" PRIx64 "\t%-30s\t", ip, + dump_insn(x, ip, inbuf, len, &ilen)); + + if (PRINT_FIELD(BRSTACKINSNLEN)) + printed += fprintf(fp, "ilen: %d\t", ilen); + + printed += fprintf(fp, "#%s%s%s%s", en->flags.predicted ? " PRED" : "", en->flags.mispred ? " MISPRED" : "", en->flags.in_tx ? " INTX" : "", @@ -1210,7 +1234,8 @@ static int perf_sample__fprintf_brstackinsn(struct perf_sample *sample, printed += ip__fprintf_sym(entries[nr - 1].from, thread, x.cpumode, x.cpu, &lastsym, attr, fp); printed += ip__fprintf_jump(entries[nr - 1].from, &entries[nr - 1], - &x, buffer, len, 0, fp, &total_cycles); + &x, buffer, len, 0, fp, &total_cycles, + attr); if (PRINT_FIELD(SRCCODE)) printed += print_srccode(thread, x.cpumode, entries[nr - 1].from); } @@ -1241,14 +1266,17 @@ static int perf_sample__fprintf_brstackinsn(struct perf_sample *sample, printed += ip__fprintf_sym(ip, thread, x.cpumode, x.cpu, &lastsym, attr, fp); if (ip == end) { printed += ip__fprintf_jump(ip, &entries[i], &x, buffer + off, len - off, ++insn, fp, - &total_cycles); + &total_cycles, attr); if (PRINT_FIELD(SRCCODE)) printed += print_srccode(thread, x.cpumode, ip); break; } else { ilen = 0; - printed += fprintf(fp, "\t%016" PRIx64 "\t%s\n", ip, + printed += fprintf(fp, "\t%016" PRIx64 "\t%s", ip, dump_insn(&x, ip, buffer + off, len - off, &ilen)); + if (PRINT_FIELD(BRSTACKINSNLEN)) + printed += fprintf(fp, "\tilen: %d", ilen); + printed += fprintf(fp, "\n"); if (ilen == 0) break; if (PRINT_FIELD(SRCCODE)) @@ -1291,16 +1319,23 @@ static int perf_sample__fprintf_brstackinsn(struct perf_sample *sample, machine, thread, &x.is64bit, &x.cpumode, false); if (len <= 0) goto out; - printed += fprintf(fp, "\t%016" PRIx64 "\t%s\n", sample->ip, - dump_insn(&x, sample->ip, buffer, len, NULL)); + ilen = 0; + printed += fprintf(fp, "\t%016" PRIx64 "\t%s", sample->ip, + dump_insn(&x, sample->ip, buffer, len, &ilen)); + if (PRINT_FIELD(BRSTACKINSNLEN)) + printed += fprintf(fp, "\tilen: %d", ilen); + printed += fprintf(fp, "\n"); if (PRINT_FIELD(SRCCODE)) print_srccode(thread, x.cpumode, sample->ip); goto out; } for (off = 0; off <= end - start; off += ilen) { ilen = 0; - printed += fprintf(fp, "\t%016" PRIx64 "\t%s\n", start + off, + printed += fprintf(fp, "\t%016" PRIx64 "\t%s", start + off, dump_insn(&x, start + off, buffer + off, len - off, &ilen)); + if (PRINT_FIELD(BRSTACKINSNLEN)) + printed += fprintf(fp, "\tilen: %d", ilen); + printed += fprintf(fp, "\n"); if (ilen == 0) break; if (arch_is_branch(buffer + off, len - off, x.is64bit) && start + off != sample->ip) { @@ -1458,7 +1493,7 @@ static int perf_sample__fprintf_insn(struct perf_sample *sample, for (i = 0; i < sample->insn_len; i++) printed += fprintf(fp, " %02x", (unsigned char)sample->insn[i]); } - if (PRINT_FIELD(BRSTACKINSN)) + if (PRINT_FIELD(BRSTACKINSN) || PRINT_FIELD(BRSTACKINSNLEN)) printed += perf_sample__fprintf_brstackinsn(sample, thread, attr, machine, fp); return printed; @@ -1578,26 +1613,34 @@ static const char *sample_flags_to_name(u32 flags) int perf_sample__sprintf_flags(u32 flags, char *str, size_t sz) { + u32 xf = PERF_IP_FLAG_IN_TX | PERF_IP_FLAG_INTR_DISABLE | + PERF_IP_FLAG_INTR_TOGGLE; const char *chars = PERF_IP_FLAG_CHARS; const size_t n = strlen(PERF_IP_FLAG_CHARS); - bool in_tx = flags & PERF_IP_FLAG_IN_TX; const char *name = NULL; size_t i, pos = 0; + char xs[16] = {0}; + + if (flags & xf) + snprintf(xs, sizeof(xs), "(%s%s%s)", + flags & PERF_IP_FLAG_IN_TX ? "x" : "", + flags & PERF_IP_FLAG_INTR_DISABLE ? "D" : "", + flags & PERF_IP_FLAG_INTR_TOGGLE ? "t" : ""); - name = sample_flags_to_name(flags & ~PERF_IP_FLAG_IN_TX); + name = sample_flags_to_name(flags & ~xf); if (name) - return snprintf(str, sz, "%-15s%4s", name, in_tx ? "(x)" : ""); + return snprintf(str, sz, "%-15s%6s", name, xs); if (flags & PERF_IP_FLAG_TRACE_BEGIN) { - name = sample_flags_to_name(flags & ~(PERF_IP_FLAG_IN_TX | PERF_IP_FLAG_TRACE_BEGIN)); + name = sample_flags_to_name(flags & ~(xf | PERF_IP_FLAG_TRACE_BEGIN)); if (name) - return snprintf(str, sz, "tr strt %-7s%4s", name, in_tx ? "(x)" : ""); + return snprintf(str, sz, "tr strt %-7s%6s", name, xs); } if (flags & PERF_IP_FLAG_TRACE_END) { - name = sample_flags_to_name(flags & ~(PERF_IP_FLAG_IN_TX | PERF_IP_FLAG_TRACE_END)); + name = sample_flags_to_name(flags & ~(xf | PERF_IP_FLAG_TRACE_END)); if (name) - return snprintf(str, sz, "tr end %-7s%4s", name, in_tx ? "(x)" : ""); + return snprintf(str, sz, "tr end %-7s%6s", name, xs); } for (i = 0; i < n; i++, flags >>= 1) { @@ -1619,7 +1662,7 @@ static int perf_sample__fprintf_flags(u32 flags, FILE *fp) char str[SAMPLE_FLAGS_BUF_SIZE]; perf_sample__sprintf_flags(flags, str, sizeof(str)); - return fprintf(fp, " %-19s ", str); + return fprintf(fp, " %-21s ", str); } struct printer_data { @@ -1715,16 +1758,44 @@ static int perf_sample__fprintf_pt_spacing(int len, FILE *fp) return perf_sample__fprintf_spacing(len, 34, fp); } +/* If a value contains only printable ASCII characters padded with NULLs */ +static bool ptw_is_prt(u64 val) +{ + char c; + u32 i; + + for (i = 0; i < sizeof(val); i++) { + c = ((char *)&val)[i]; + if (!c) + break; + if (!isprint(c) || !isascii(c)) + return false; + } + for (; i < sizeof(val); i++) { + c = ((char *)&val)[i]; + if (c) + return false; + } + return true; +} + static int perf_sample__fprintf_synth_ptwrite(struct perf_sample *sample, FILE *fp) { struct perf_synth_intel_ptwrite *data = perf_sample__synth_ptr(sample); + char str[sizeof(u64) + 1] = ""; int len; + u64 val; if (perf_sample__bad_synth_size(sample, *data)) return 0; - len = fprintf(fp, " IP: %u payload: %#" PRIx64 " ", - data->ip, le64_to_cpu(data->payload)); + val = le64_to_cpu(data->payload); + if (ptw_is_prt(val)) { + memcpy(str, &val, sizeof(val)); + str[sizeof(val)] = 0; + } + len = fprintf(fp, " IP: %u payload: %#" PRIx64 " %s ", + data->ip, val, str); return len + perf_sample__fprintf_pt_spacing(len, fp); } @@ -1810,6 +1881,56 @@ static int perf_sample__fprintf_synth_psb(struct perf_sample *sample, FILE *fp) return len + perf_sample__fprintf_pt_spacing(len, fp); } +/* Intel PT Event Trace */ +static int perf_sample__fprintf_synth_evt(struct perf_sample *sample, FILE *fp) +{ + struct perf_synth_intel_evt *data = perf_sample__synth_ptr(sample); + const char *cfe[32] = {NULL, "INTR", "IRET", "SMI", "RSM", "SIPI", + "INIT", "VMENTRY", "VMEXIT", "VMEXIT_INTR", + "SHUTDOWN"}; + const char *evd[64] = {"PFA", "VMXQ", "VMXR"}; + const char *s; + int len, i; + + if (perf_sample__bad_synth_size(sample, *data)) + return 0; + + s = cfe[data->type]; + if (s) { + len = fprintf(fp, " cfe: %s IP: %d vector: %u", + s, data->ip, data->vector); + } else { + len = fprintf(fp, " cfe: %u IP: %d vector: %u", + data->type, data->ip, data->vector); + } + for (i = 0; i < data->evd_cnt; i++) { + unsigned int et = data->evd[i].evd_type & 0x3f; + + s = evd[et]; + if (s) { + len += fprintf(fp, " %s: %#" PRIx64, + s, data->evd[i].payload); + } else { + len += fprintf(fp, " EVD_%u: %#" PRIx64, + et, data->evd[i].payload); + } + } + return len + perf_sample__fprintf_pt_spacing(len, fp); +} + +static int perf_sample__fprintf_synth_iflag_chg(struct perf_sample *sample, FILE *fp) +{ + struct perf_synth_intel_iflag_chg *data = perf_sample__synth_ptr(sample); + int len; + + if (perf_sample__bad_synth_size(sample, *data)) + return 0; + + len = fprintf(fp, " IFLAG: %d->%d %s branch", !data->iflag, data->iflag, + data->via_branch ? "via" : "non"); + return len + perf_sample__fprintf_pt_spacing(len, fp); +} + static int perf_sample__fprintf_synth(struct perf_sample *sample, struct evsel *evsel, FILE *fp) { @@ -1828,6 +1949,10 @@ static int perf_sample__fprintf_synth(struct perf_sample *sample, return perf_sample__fprintf_synth_cbr(sample, fp); case PERF_SYNTH_INTEL_PSB: return perf_sample__fprintf_synth_psb(sample, fp); + case PERF_SYNTH_INTEL_EVT: + return perf_sample__fprintf_synth_evt(sample, fp); + case PERF_SYNTH_INTEL_IFLAG_CHG: + return perf_sample__fprintf_synth_iflag_chg(sample, fp); default: break; } @@ -2000,6 +2125,7 @@ static void process_event(struct perf_script *script, struct evsel_script *es = evsel->priv; FILE *fp = es->fp; char str[PAGE_SIZE_NAME_LEN]; + const char *arch = perf_env__arch(machine->env); if (output[type].fields == 0) return; @@ -2066,10 +2192,10 @@ static void process_event(struct perf_script *script, } if (PRINT_FIELD(IREGS)) - perf_sample__fprintf_iregs(sample, attr, fp); + perf_sample__fprintf_iregs(sample, attr, arch, fp); if (PRINT_FIELD(UREGS)) - perf_sample__fprintf_uregs(sample, attr, fp); + perf_sample__fprintf_uregs(sample, attr, arch, fp); if (PRINT_FIELD(BRSTACK)) perf_sample__fprintf_brstack(sample, thread, attr, fp); @@ -2113,13 +2239,10 @@ static struct scripting_ops *scripting_ops; static void __process_stat(struct evsel *counter, u64 tstamp) { int nthreads = perf_thread_map__nr(counter->core.threads); - int ncpus = evsel__nr_cpus(counter); - int cpu, thread; + int idx, thread; + struct perf_cpu cpu; static int header_printed; - if (counter->core.system_wide) - nthreads = 1; - if (!header_printed) { printf("%3s %8s %15s %15s %15s %15s %s\n", "CPU", "THREAD", "VAL", "ENA", "RUN", "TIME", "EVENT"); @@ -2127,13 +2250,13 @@ static void __process_stat(struct evsel *counter, u64 tstamp) } for (thread = 0; thread < nthreads; thread++) { - for (cpu = 0; cpu < ncpus; cpu++) { + perf_cpu_map__for_each_cpu(cpu, idx, evsel__cpus(counter)) { struct perf_counts_values *counts; - counts = perf_counts(counter->counts, cpu, thread); + counts = perf_counts(counter->counts, idx, thread); printf("%3d %8d %15" PRIu64 " %15" PRIu64 " %15" PRIu64 " %15" PRIu64 " %s\n", - counter->core.cpus->map[cpu], + cpu.cpu, perf_thread_map__pid(counter->core.threads, thread), counts->val, counts->ena, @@ -2316,7 +2439,7 @@ static int process_attr(struct perf_tool *tool, union perf_event *event, * on events sample_type. */ sample_type = evlist__combined_sample_type(evlist); - callchain_param_setup(sample_type); + callchain_param_setup(sample_type, perf_env__arch((*pevlist)->env)); /* Enable fields for callchain entries */ if (symbol_conf.use_callchain && @@ -3466,16 +3589,7 @@ static void script__setup_sample_type(struct perf_script *script) struct perf_session *session = script->session; u64 sample_type = evlist__combined_sample_type(session->evlist); - if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain) { - if ((sample_type & PERF_SAMPLE_REGS_USER) && - (sample_type & PERF_SAMPLE_STACK_USER)) { - callchain_param.record_mode = CALLCHAIN_DWARF; - dwarf_callchain_users = true; - } else if (sample_type & PERF_SAMPLE_BRANCH_STACK) - callchain_param.record_mode = CALLCHAIN_LBR; - else - callchain_param.record_mode = CALLCHAIN_FP; - } + callchain_param_setup(sample_type, perf_env__arch(session->machines.host.env)); if (script->stitch_lbr && (callchain_param.record_mode != CALLCHAIN_LBR)) { pr_warning("Can't find LBR callchain. Switch off --stitch-lbr.\n" @@ -3532,6 +3646,9 @@ int process_thread_map_event(struct perf_session *session, struct perf_tool *tool = session->tool; struct perf_script *script = container_of(tool, struct perf_script, tool); + if (dump_trace) + perf_event__fprintf_thread_map(event, stdout); + if (script->threads) { pr_warning("Extra thread map event, ignoring.\n"); return 0; @@ -3551,6 +3668,9 @@ int process_cpu_map_event(struct perf_session *session, struct perf_tool *tool = session->tool; struct perf_script *script = container_of(tool, struct perf_script, tool); + if (dump_trace) + perf_event__fprintf_cpu_map(event, stdout); + if (script->cpus) { pr_warning("Extra cpu map event, ignoring.\n"); return 0; @@ -3639,6 +3759,7 @@ int cmd_script(int argc, const char **argv) bool header = false; bool header_only = false; bool script_started = false; + bool unsorted_dump = false; char *rec_script_path = NULL; char *rep_script_path = NULL; struct perf_session *session; @@ -3687,6 +3808,8 @@ int cmd_script(int argc, const char **argv) const struct option options[] = { OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, "dump raw trace in ASCII"), + OPT_BOOLEAN(0, "dump-unsorted-raw-trace", &unsorted_dump, + "dump unsorted raw trace in ASCII"), OPT_INCR('v', "verbose", &verbose, "be more verbose (show symbol address, etc)"), OPT_BOOLEAN('L', "Latency", &latency_format, @@ -3723,9 +3846,10 @@ int cmd_script(int argc, const char **argv) "Valid types: hw,sw,trace,raw,synth. " "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso," "addr,symoff,srcline,period,iregs,uregs,brstack," - "brstacksym,flags,bpf-output,brstackinsn,brstackoff," - "callindent,insn,insnlen,synth,phys_addr,metric,misc,ipc,tod," - "data_page_size,code_page_size,ins_lat", + "brstacksym,flags,data_src,weight,bpf-output,brstackinsn," + "brstackinsnlen,brstackoff,callindent,insn,insnlen,synth," + "phys_addr,metric,misc,srccode,ipc,tod,data_page_size," + "code_page_size,ins_lat", parse_output_fields), OPT_BOOLEAN('a', "all-cpus", &system_wide, "system-wide collection from all CPUs"), @@ -3740,7 +3864,7 @@ int cmd_script(int argc, const char **argv) OPT_CALLBACK_OPTARG(0, "xed", NULL, NULL, NULL, "Run xed disassembler on output", parse_xed), OPT_CALLBACK_OPTARG(0, "call-trace", &itrace_synth_opts, NULL, NULL, - "Decode calls from from itrace", parse_call_trace), + "Decode calls from itrace", parse_call_trace), OPT_CALLBACK_OPTARG(0, "call-ret-trace", &itrace_synth_opts, NULL, NULL, "Decode calls and returns from itrace", parse_callret_trace), OPT_STRING(0, "graph-function", &symbol_conf.graph_function, "symbol[,symbol...]", @@ -3811,6 +3935,8 @@ int cmd_script(int argc, const char **argv) "file", "file saving guest os /proc/kallsyms"), OPT_STRING(0, "guestmodules", &symbol_conf.default_guest_modules, "file", "file saving guest os /proc/modules"), + OPT_BOOLEAN(0, "guest-code", &symbol_conf.guest_code, + "Guest code can be found in hypervisor process"), OPT_BOOLEAN('\0', "stitch-lbr", &script.stitch_lbr, "Enable LBR callgraph stitching approach"), OPTS_EVSWITCH(&script.evswitch), @@ -3836,7 +3962,8 @@ int cmd_script(int argc, const char **argv) if (symbol_conf.guestmount || symbol_conf.default_guest_vmlinux_name || symbol_conf.default_guest_kallsyms || - symbol_conf.default_guest_modules) { + symbol_conf.default_guest_modules || + symbol_conf.guest_code) { /* * Enable guest sample processing. */ @@ -3846,16 +3973,21 @@ int cmd_script(int argc, const char **argv) data.path = input_name; data.force = symbol_conf.force; + if (unsorted_dump) { + dump_trace = true; + script.tool.ordered_events = false; + } + if (symbol__validate_sym_arguments()) return -1; - if (argc > 1 && !strncmp(argv[0], "rec", strlen("rec"))) { + if (argc > 1 && strlen(argv[0]) > 2 && strstarts("record", argv[0])) { rec_script_path = get_script_path(argv[1], RECORD_SUFFIX); if (!rec_script_path) return cmd_record(argc, argv); } - if (argc > 1 && !strncmp(argv[0], "rep", strlen("rep"))) { + if (argc > 1 && strlen(argv[0]) > 2 && strstarts("report", argv[0])) { rep_script_path = get_script_path(argv[1], REPORT_SUFFIX); if (!rep_script_path) { fprintf(stderr, |