diff options
| -rw-r--r-- | tools/perf/builtin-annotate.c | 9 | ||||
| -rw-r--r-- | tools/perf/util/annotate.h | 2 | ||||
| -rw-r--r-- | tools/perf/util/hist.h | 4 | ||||
| -rw-r--r-- | tools/perf/util/ui/browsers/annotate.c | 69 | ||||
| -rw-r--r-- | tools/perf/util/ui/browsers/hists.c | 20 | 
5 files changed, 79 insertions, 25 deletions
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 39e3d382b2d..24db9d2db7b 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -114,7 +114,8 @@ static int hist_entry__tty_annotate(struct hist_entry *he, int evidx)  				    print_line, full_paths, 0, 0);  } -static void hists__find_annotations(struct hists *self, int evidx) +static void hists__find_annotations(struct hists *self, int evidx, +				    int nr_events)  {  	struct rb_node *nd = rb_first(&self->entries), *next;  	int key = KEY_RIGHT; @@ -137,7 +138,8 @@ find_next:  		}  		if (use_browser > 0) { -			key = hist_entry__tui_annotate(he, evidx, NULL, NULL, 0); +			key = hist_entry__tui_annotate(he, evidx, nr_events, +						       NULL, NULL, 0);  			switch (key) {  			case KEY_RIGHT:  				next = rb_next(nd); @@ -215,7 +217,8 @@ static int __cmd_annotate(void)  			total_nr_samples += nr_samples;  			hists__collapse_resort(hists);  			hists__output_resort(hists); -			hists__find_annotations(hists, pos->idx); +			hists__find_annotations(hists, pos->idx, +						session->evlist->nr_entries);  		}  	} diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h index aafbc7e9a9b..d9072523d34 100644 --- a/tools/perf/util/annotate.h +++ b/tools/perf/util/annotate.h @@ -99,7 +99,7 @@ static inline int symbol__tui_annotate(struct symbol *sym __used,  }  #else  int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx, -			 void(*timer)(void *arg), void *arg, +			 int nr_events, void(*timer)(void *arg), void *arg,  			 int delay_secs);  #endif diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index f87677bfaff..7ea1e560e00 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -110,7 +110,7 @@ int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __used,  }  static inline int hist_entry__tui_annotate(struct hist_entry *self __used, -					   int evidx __used, +					   int evidx __used, int nr_events __used,  					   void(*timer)(void *arg) __used,  					   void *arg __used, int delay_secs __used);  { @@ -120,7 +120,7 @@ static inline int hist_entry__tui_annotate(struct hist_entry *self __used,  #define KEY_RIGHT -2  #else  #include <newt.h> -int hist_entry__tui_annotate(struct hist_entry *he, int evidx, +int hist_entry__tui_annotate(struct hist_entry *he, int evidx, int nr_events,  			     void(*timer)(void *arg), void *arg, int delay_secs);  #define KEY_LEFT NEWT_KEY_LEFT diff --git a/tools/perf/util/ui/browsers/annotate.c b/tools/perf/util/ui/browsers/annotate.c index 76c1d083aa9..77421bab8fd 100644 --- a/tools/perf/util/ui/browsers/annotate.c +++ b/tools/perf/util/ui/browsers/annotate.c @@ -20,6 +20,7 @@ struct annotate_browser {  	struct ui_browser b;  	struct rb_root	  entries;  	struct rb_node	  *curr_hot; +	struct objdump_line *selection;  };  struct objdump_line_rb_node { @@ -36,6 +37,7 @@ struct objdump_line_rb_node *objdump_line__rb(struct objdump_line *self)  static void annotate_browser__write(struct ui_browser *self, void *entry, int row)  { +	struct annotate_browser *ab = container_of(self, struct annotate_browser, b);  	struct objdump_line *ol = rb_entry(entry, struct objdump_line, node);  	bool current_entry = ui_browser__is_current_entry(self, row);  	int width = self->width; @@ -58,6 +60,8 @@ static void annotate_browser__write(struct ui_browser *self, void *entry, int ro  	if (!current_entry)  		ui_browser__set_color(self, HE_COLORSET_CODE); +	else +		ab->selection = ol;  }  static double objdump_line__calc_percent(struct objdump_line *self, @@ -141,7 +145,8 @@ static void annotate_browser__set_top(struct annotate_browser *self,  static void annotate_browser__calc_percent(struct annotate_browser *browser,  					   int evidx)  { -	struct symbol *sym = browser->b.priv; +	struct map_symbol *ms = browser->b.priv; +	struct symbol *sym = ms->sym;  	struct annotation *notes = symbol__annotation(sym);  	struct objdump_line *pos; @@ -164,17 +169,18 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,  }  static int annotate_browser__run(struct annotate_browser *self, int evidx, -				 void(*timer)(void *arg) __used, void *arg __used, -				 int delay_secs) +				 int nr_events, void(*timer)(void *arg), +				 void *arg, int delay_secs)  {  	struct rb_node *nd = NULL; -	struct symbol *sym = self->b.priv; +	struct map_symbol *ms = self->b.priv; +	struct symbol *sym = ms->sym;  	/*  	 * RIGHT To allow builtin-annotate to cycle thru multiple symbols by  	 * examining the exit key for this function.  	 */  	int exit_keys[] = { 'H', NEWT_KEY_TAB, NEWT_KEY_UNTAB, -			    NEWT_KEY_RIGHT, 0 }; +			    NEWT_KEY_RIGHT, NEWT_KEY_ENTER, 0 };  	int key;  	if (ui_browser__show(&self->b, sym->name, @@ -238,6 +244,42 @@ static int annotate_browser__run(struct annotate_browser *self, int evidx,  		case 'H':  			nd = self->curr_hot;  			break; +		case NEWT_KEY_ENTER: +			if (self->selection != NULL) { +				char *s = strstr(self->selection->line, "callq "); +				struct annotation *notes; +				struct symbol *target; +				u64 ip; + +				if (s == NULL) +					continue; + +				s = strchr(s, ' '); +				if (s++ == NULL) +					continue; + +				ip = strtoull(s, NULL, 16); +				ip = ms->map->map_ip(ms->map, ip); +				target = map__find_symbol(ms->map, ip, NULL); +				if (target == NULL) +					continue; + +				notes = symbol__annotation(target); +				pthread_mutex_lock(¬es->lock); + +				if (notes->src == NULL && +				    symbol__alloc_hist(target, nr_events) < 0) { +					pthread_mutex_unlock(¬es->lock); +					ui__warning("Not enough memory for annotating '%s' symbol!\n", +						    target->name); +					continue; +				} + +				pthread_mutex_unlock(¬es->lock); +				symbol__tui_annotate(target, ms->map, evidx, nr_events, +						     timer, arg, delay_secs); +			} +			break;  		default:  			goto out;  		} @@ -250,25 +292,29 @@ out:  	return key;  } -int hist_entry__tui_annotate(struct hist_entry *he, int evidx, +int hist_entry__tui_annotate(struct hist_entry *he, int evidx, int nr_events,  			     void(*timer)(void *arg), void *arg, int delay_secs)  { -	return symbol__tui_annotate(he->ms.sym, he->ms.map, evidx, +	return symbol__tui_annotate(he->ms.sym, he->ms.map, evidx, nr_events,  				    timer, arg, delay_secs);  }  int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx, -			void(*timer)(void *arg), void *arg, -			int delay_secs) +			 int nr_events, void(*timer)(void *arg), void *arg, +			 int delay_secs)  {  	struct objdump_line *pos, *n;  	struct annotation *notes; +	struct map_symbol ms = { +		.map = map, +		.sym = sym, +	};  	struct annotate_browser browser = {  		.b = {  			.refresh = ui_browser__list_head_refresh,  			.seek	 = ui_browser__list_head_seek,  			.write	 = annotate_browser__write, -			.priv	 = sym, +			.priv	 = &ms,  		},  	};  	int ret; @@ -300,7 +346,8 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,  	browser.b.entries = ¬es->src->source,  	browser.b.width += 18; /* Percentage */ -	ret = annotate_browser__run(&browser, evidx, timer, arg, delay_secs); +	ret = annotate_browser__run(&browser, evidx, nr_events, +				    timer, arg, delay_secs);  	list_for_each_entry_safe(pos, n, ¬es->src->source, node) {  		list_del(&pos->node);  		objdump_line__free(pos); diff --git a/tools/perf/util/ui/browsers/hists.c b/tools/perf/util/ui/browsers/hists.c index 6244d19bd1f..f0515cbabda 100644 --- a/tools/perf/util/ui/browsers/hists.c +++ b/tools/perf/util/ui/browsers/hists.c @@ -825,7 +825,7 @@ static int hists__browser_title(struct hists *self, char *bf, size_t size,  	return printed;  } -static int perf_evsel__hists_browse(struct perf_evsel *evsel, +static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,  				    const char *helpline, const char *ev_name,  				    bool left_exits,  				    void(*timer)(void *arg), void *arg, @@ -968,7 +968,7 @@ do_annotate:  			if (he == NULL)  				continue; -			hist_entry__tui_annotate(he, evsel->idx, +			hist_entry__tui_annotate(he, evsel->idx, nr_events,  						 timer, arg, delay_secs);  		} else if (choice == browse_map)  			map__browse(browser->selection->map); @@ -1042,7 +1042,8 @@ static void perf_evsel_menu__write(struct ui_browser *browser,  		menu->selection = evsel;  } -static int perf_evsel_menu__run(struct perf_evsel_menu *menu, const char *help, +static int perf_evsel_menu__run(struct perf_evsel_menu *menu, +				int nr_events, const char *help,  				void(*timer)(void *arg), void *arg, int delay_secs)  {  	int exit_keys[] = { NEWT_KEY_ENTER, NEWT_KEY_RIGHT, 0, }; @@ -1077,8 +1078,9 @@ static int perf_evsel_menu__run(struct perf_evsel_menu *menu, const char *help,  			perf_evlist__set_selected(evlist, pos);  browse_hists:  			ev_name = event_name(pos); -			key = perf_evsel__hists_browse(pos, help, ev_name, true, -						       timer, arg, delay_secs); +			key = perf_evsel__hists_browse(pos, nr_events, help, +						       ev_name, true, timer, +						       arg, delay_secs);  			ui_browser__show_title(&menu->b, title);  			break;  		case NEWT_KEY_LEFT: @@ -1150,7 +1152,8 @@ static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist,  			pos->name = strdup(ev_name);  	} -	return perf_evsel_menu__run(&menu, help, timer, arg, delay_secs); +	return perf_evsel_menu__run(&menu, evlist->nr_entries, help, timer, +				    arg, delay_secs);  }  int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help, @@ -1162,8 +1165,9 @@ int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help,  		struct perf_evsel *first = list_entry(evlist->entries.next,  						      struct perf_evsel, node);  		const char *ev_name = event_name(first); -		return perf_evsel__hists_browse(first, help, ev_name, false, -						timer, arg, delay_secs); +		return perf_evsel__hists_browse(first, evlist->nr_entries, help, +						ev_name, false, timer, arg, +						delay_secs);  	}  	return __perf_evlist__tui_browse_hists(evlist, help,  |