diff options
Diffstat (limited to 'tools/perf/builtin-top.c')
-rw-r--r-- | tools/perf/builtin-top.c | 67 |
1 files changed, 54 insertions, 13 deletions
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index d4b5b02bab73..eb5740154bc0 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -114,6 +114,7 @@ static int perf_top__parse_source(struct perf_top *top, struct hist_entry *he) struct symbol *sym; struct annotation *notes; struct map *map; + struct dso *dso; int err = -1; if (!he || !he->ms.sym) @@ -123,12 +124,12 @@ static int perf_top__parse_source(struct perf_top *top, struct hist_entry *he) sym = he->ms.sym; map = he->ms.map; + dso = map__dso(map); /* * We can't annotate with just /proc/kallsyms */ - if (map->dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS && - !dso__is_kcore(map->dso)) { + if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS && !dso__is_kcore(dso)) { pr_err("Can't annotate %s: No vmlinux file was found in the " "path\n", sym->name); sleep(1); @@ -169,6 +170,7 @@ static void ui__warn_map_erange(struct map *map, struct symbol *sym, u64 ip) { struct utsname uts; int err = uname(&uts); + struct dso *dso = map__dso(map); ui__warning("Out of bounds address found:\n\n" "Addr: %" PRIx64 "\n" @@ -180,8 +182,8 @@ static void ui__warn_map_erange(struct map *map, struct symbol *sym, u64 ip) "Tools: %s\n\n" "Not all samples will be on the annotation output.\n\n" "Please report to linux-kernel@vger.kernel.org\n", - ip, map->dso->long_name, dso__symtab_origin(map->dso), - map->start, map->end, sym->start, sym->end, + ip, dso->long_name, dso__symtab_origin(dso), + map__start(map), map__end(map), sym->start, sym->end, sym->binding == STB_GLOBAL ? 'g' : sym->binding == STB_LOCAL ? 'l' : 'w', sym->name, err ? "[unknown]" : uts.machine, @@ -189,7 +191,7 @@ static void ui__warn_map_erange(struct map *map, struct symbol *sym, u64 ip) if (use_browser <= 0) sleep(5); - map->erange_warned = true; + map__set_erange_warned(map, true); } static void perf_top__record_precise_ip(struct perf_top *top, @@ -223,7 +225,7 @@ static void perf_top__record_precise_ip(struct perf_top *top, */ mutex_unlock(&he->hists->lock); - if (err == -ERANGE && !he->ms.map->erange_warned) + if (err == -ERANGE && !map__erange_warned(he->ms.map)) ui__warn_map_erange(he->ms.map, sym, ip); else if (err == -ENOMEM) { pr_err("Not enough memory for annotating '%s' symbol!\n", @@ -707,7 +709,7 @@ repeat: case -1: if (errno == EINTR) continue; - __fallthrough; + fallthrough; default: c = getc(stdin); tcsetattr(0, TCSAFLUSH, &save); @@ -810,7 +812,8 @@ static void perf_event__process_sample(struct perf_tool *tool, __map__is_kernel(al.map) && map__has_symbols(al.map)) { if (symbol_conf.vmlinux_name) { char serr[256]; - dso__strerror_load(al.map->dso, serr, sizeof(serr)); + + dso__strerror_load(map__dso(al.map), serr, sizeof(serr)); ui__warning("The %s file can't be used: %s\n%s", symbol_conf.vmlinux_name, serr, msg); } else { @@ -1273,8 +1276,7 @@ static int __cmd_top(struct perf_top *top) top->evlist->core.threads, true, false, top->nr_threads_synthesize); - if (top->nr_threads_synthesize > 1) - perf_set_singlethreaded(); + perf_set_multithreaded(); if (perf_hpp_list.socket) { ret = perf_env__read_cpu_topology_map(&perf_env); @@ -1352,6 +1354,7 @@ out_join: out_join_thread: cond_signal(&top->qe.cond); pthread_join(thread_process, NULL); + perf_set_singlethreaded(); return ret; } @@ -1435,11 +1438,12 @@ int cmd_top(int argc, const char **argv) .sample_time_set = true, }, .max_stack = sysctl__max_stack(), - .annotation_opts = annotation__default_options, .nr_threads_synthesize = UINT_MAX, }; + bool branch_call_mode = false; struct record_opts *opts = &top.record_opts; struct target *target = &opts->target; + const char *disassembler_style = NULL, *objdump_path = NULL, *addr2line_path = NULL; const struct option options[] = { OPT_CALLBACK('e', "event", &top.evlist, "event", "event selector. use 'perf list' to list available events", @@ -1525,9 +1529,11 @@ int cmd_top(int argc, const char **argv) OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel, "Enable kernel symbol demangling"), OPT_BOOLEAN(0, "no-bpf-event", &top.record_opts.no_bpf_event, "do not record bpf events"), - OPT_STRING(0, "objdump", &top.annotation_opts.objdump_path, "path", + OPT_STRING(0, "objdump", &objdump_path, "path", "objdump binary to use for disassembly and annotations"), - OPT_STRING('M', "disassembler-style", &top.annotation_opts.disassembler_style, "disassembler style", + OPT_STRING(0, "addr2line", &addr2line_path, "path", + "addr2line binary to use for line numbers"), + OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style", "Specify disassembler style (e.g. -M intel for intel syntax)"), OPT_STRING(0, "prefix", &top.annotation_opts.prefix, "prefix", "Add prefix to source file path names in programs (with --prefix-strip)"), @@ -1549,6 +1555,8 @@ int cmd_top(int argc, const char **argv) OPT_CALLBACK('j', "branch-filter", &opts->branch_stack, "branch filter mask", "branch stack filter modes", parse_branch_stack), + OPT_BOOLEAN(0, "branch-history", &branch_call_mode, + "add last branch records to call history"), OPT_BOOLEAN(0, "raw-trace", &symbol_conf.raw_trace, "Show raw trace event output (do not use print fmt or plugins)"), OPT_BOOLEAN(0, "hierarchy", &symbol_conf.report_hierarchy, @@ -1587,6 +1595,8 @@ int cmd_top(int argc, const char **argv) if (status < 0) return status; + annotation_options__init(&top.annotation_opts); + top.annotation_opts.min_pcnt = 5; top.annotation_opts.context = 4; @@ -1617,6 +1627,22 @@ int cmd_top(int argc, const char **argv) if (argc) usage_with_options(top_usage, options); + if (disassembler_style) { + top.annotation_opts.disassembler_style = strdup(disassembler_style); + if (!top.annotation_opts.disassembler_style) + return -ENOMEM; + } + if (objdump_path) { + top.annotation_opts.objdump_path = strdup(objdump_path); + if (!top.annotation_opts.objdump_path) + return -ENOMEM; + } + if (addr2line_path) { + symbol_conf.addr2line_path = strdup(addr2line_path); + if (!symbol_conf.addr2line_path) + return -ENOMEM; + } + status = symbol__validate_sym_arguments(); if (status) goto out_delete_evlist; @@ -1657,6 +1683,20 @@ int cmd_top(int argc, const char **argv) goto out_delete_evlist; } + if (branch_call_mode) { + if (!opts->branch_stack) + opts->branch_stack = PERF_SAMPLE_BRANCH_ANY; + symbol_conf.use_callchain = true; + callchain_param.key = CCKEY_ADDRESS; + callchain_param.branch_callstack = true; + callchain_param.enabled = true; + if (callchain_param.record_mode == CALLCHAIN_NONE) + callchain_param.record_mode = CALLCHAIN_FP; + callchain_register_param(&callchain_param); + if (!sort_order) + sort_order = "srcline,symbol,dso"; + } + if (opts->branch_stack && callchain_param.enabled) symbol_conf.show_branchflag_count = true; @@ -1783,6 +1823,7 @@ int cmd_top(int argc, const char **argv) out_delete_evlist: evlist__delete(top.evlist); perf_session__delete(top.session); + annotation_options__exit(&top.annotation_opts); return status; } |