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 [email protected]\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;  }  |