diff options
Diffstat (limited to 'tools/perf/builtin-annotate.c')
| -rw-r--r-- | tools/perf/builtin-annotate.c | 88 | 
1 files changed, 82 insertions, 6 deletions
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index f15731a3d438..ead6ae4549e5 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -44,6 +44,7 @@ struct perf_annotate {  	bool	   full_paths;  	bool	   print_line;  	bool	   skip_missing; +	bool	   has_br_stack;  	const char *sym_hist_filter;  	const char *cpu_list;  	DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); @@ -146,16 +147,73 @@ static void process_branch_stack(struct branch_stack *bs, struct addr_location *  	free(bi);  } +static int hist_iter__branch_callback(struct hist_entry_iter *iter, +				      struct addr_location *al __maybe_unused, +				      bool single __maybe_unused, +				      void *arg __maybe_unused) +{ +	struct hist_entry *he = iter->he; +	struct branch_info *bi; +	struct perf_sample *sample = iter->sample; +	struct perf_evsel *evsel = iter->evsel; +	int err; + +	hist__account_cycles(sample->branch_stack, al, sample, false); + +	bi = he->branch_info; +	err = addr_map_symbol__inc_samples(&bi->from, sample, evsel->idx); + +	if (err) +		goto out; + +	err = addr_map_symbol__inc_samples(&bi->to, sample, evsel->idx); + +out: +	return err; +} + +static int process_branch_callback(struct perf_evsel *evsel, +				   struct perf_sample *sample, +				   struct addr_location *al __maybe_unused, +				   struct perf_annotate *ann, +				   struct machine *machine) +{ +	struct hist_entry_iter iter = { +		.evsel		= evsel, +		.sample		= sample, +		.add_entry_cb	= hist_iter__branch_callback, +		.hide_unresolved	= symbol_conf.hide_unresolved, +		.ops		= &hist_iter_branch, +	}; + +	struct addr_location a; +	int ret; + +	if (machine__resolve(machine, &a, sample) < 0) +		return -1; + +	if (a.sym == NULL) +		return 0; + +	if (a.map != NULL) +		a.map->dso->hit = 1; + +	ret = hist_entry_iter__add(&iter, &a, PERF_MAX_STACK_DEPTH, ann); +	return ret; +} +  static int perf_evsel__add_sample(struct perf_evsel *evsel,  				  struct perf_sample *sample,  				  struct addr_location *al, -				  struct perf_annotate *ann) +				  struct perf_annotate *ann, +				  struct machine *machine)  {  	struct hists *hists = evsel__hists(evsel);  	struct hist_entry *he;  	int ret; -	if (ann->sym_hist_filter != NULL && +	if ((!ann->has_br_stack || !ui__has_annotation()) && +	    ann->sym_hist_filter != NULL &&  	    (al->sym == NULL ||  	     strcmp(ann->sym_hist_filter, al->sym->name) != 0)) {  		/* We're only interested in a symbol named sym_hist_filter */ @@ -178,6 +236,9 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel,  	 */  	process_branch_stack(sample->branch_stack, al, sample); +	if (ann->has_br_stack && ui__has_annotation()) +		return process_branch_callback(evsel, sample, al, ann, machine); +  	he = hists__add_entry(hists, al, NULL, NULL, NULL, sample, true);  	if (he == NULL)  		return -ENOMEM; @@ -206,7 +267,8 @@ static int process_sample_event(struct perf_tool *tool,  	if (ann->cpu_list && !test_bit(sample->cpu, ann->cpu_bitmap))  		goto out_put; -	if (!al.filtered && perf_evsel__add_sample(evsel, sample, &al, ann)) { +	if (!al.filtered && +	    perf_evsel__add_sample(evsel, sample, &al, ann, machine)) {  		pr_warning("problem incrementing symbol count, "  			   "skipping event\n");  		ret = -1; @@ -238,6 +300,10 @@ static void hists__find_annotations(struct hists *hists,  		if (he->ms.sym == NULL || he->ms.map->dso->annotate_warned)  			goto find_next; +		if (ann->sym_hist_filter && +		    (strcmp(he->ms.sym->name, ann->sym_hist_filter) != 0)) +			goto find_next; +  		notes = symbol__annotation(he->ms.sym);  		if (notes->src == NULL) {  find_next: @@ -269,6 +335,7 @@ find_next:  			nd = rb_next(nd);  		} else if (use_browser == 1) {  			key = hist_entry__tui_annotate(he, evsel, NULL); +  			switch (key) {  			case -1:  				if (!ann->skip_missing) @@ -489,6 +556,9 @@ int cmd_annotate(int argc, const char **argv)  	if (annotate.session == NULL)  		return -1; +	annotate.has_br_stack = perf_header__has_feat(&annotate.session->header, +						      HEADER_BRANCH_STACK); +  	ret = symbol__annotation_init();  	if (ret < 0)  		goto out_delete; @@ -499,9 +569,6 @@ int cmd_annotate(int argc, const char **argv)  	if (ret < 0)  		goto out_delete; -	if (setup_sorting(NULL) < 0) -		usage_with_options(annotate_usage, options); -  	if (annotate.use_stdio)  		use_browser = 0;  	else if (annotate.use_tui) @@ -511,6 +578,15 @@ int cmd_annotate(int argc, const char **argv)  	setup_browser(true); +	if (use_browser == 1 && annotate.has_br_stack) { +		sort__mode = SORT_MODE__BRANCH; +		if (setup_sorting(annotate.session->evlist) < 0) +			usage_with_options(annotate_usage, options); +	} else { +		if (setup_sorting(NULL) < 0) +			usage_with_options(annotate_usage, options); +	} +  	ret = __cmd_annotate(&annotate);  out_delete:  |