All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 1/6] perf report: Add a popup menu to ask what operation is to be performed
@ 2010-03-24 19:40 Arnaldo Carvalho de Melo
  2010-03-24 19:40 ` [PATCH v2 2/6] perf symbols: Avoid unnecessary symbol loading when dso list is specified Arnaldo Carvalho de Melo
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Arnaldo Carvalho de Melo @ 2010-03-24 19:40 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Arnaldo Carvalho de Melo,
	Frédéric Weisbecker, Mike Galbraith, Peter Zijlstra,
	Paul Mackerras

From: Arnaldo Carvalho de Melo <acme@redhat.com>

Right now it presents a menu with these options:

 +------------------------------+
 | Annotate CURRENT_SYMBOL_NAME |
 | Exit                         |
 +------------------------------+

If the highlighted (current) symbol is not annotatable only the "Exit"
option will appear.

Also add a confirmation dialog when ESC is pressed on the top level to
avoid exiting the application by pressing one too many ESC key.

To get to the menu just press the -> (Right navigation key), to exit
just press ESC.

Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/newt.c |   96 ++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 88 insertions(+), 8 deletions(-)

diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c
index 12b229b..a3465a0 100644
--- a/tools/perf/util/newt.c
+++ b/tools/perf/util/newt.c
@@ -28,6 +28,47 @@ static newtComponent newt_form__new(void)
 	return self;
 }
 
+static int popup_menu(int argc, const char *argv[])
+{
+	struct newtExitStruct es;
+	int i, rc = -1, max_len = 5;
+	newtComponent listbox, form = newt_form__new();
+
+	if (form == NULL)
+		return -1;
+
+	listbox = newtListbox(0, 0, argc, NEWT_FLAG_RETURNEXIT);
+	if (listbox == NULL)
+		goto out_destroy_form;
+
+	newtFormAddComponents(form, listbox, NULL);
+
+	for (i = 0; i < argc; ++i) {
+		int len = strlen(argv[i]);
+		if (len > max_len)
+			max_len = len;
+		if (newtListboxAddEntry(listbox, argv[i], (void *)(long)i))
+			goto out_destroy_form;
+	}
+
+	newtCenteredWindow(max_len, argc, NULL);
+	newtFormRun(form, &es);
+	rc = newtListboxGetCurrent(listbox) - NULL;
+	if (es.reason == NEWT_EXIT_HOTKEY)
+		rc = -1;
+	newtPopWindow();
+out_destroy_form:
+	newtFormDestroy(form);
+	return rc;
+}
+
+static bool dialog_yesno(const char *msg)
+{
+	/* newtWinChoice should really be accepting const char pointers... */
+	char yes[] = "Yes", no[] = "No";
+	return newtWinChoice(NULL, no, yes, (char *)msg) == 2;
+}
+
 /*
  * When debugging newt problems it was useful to be able to "unroll"
  * the calls to newtCheckBoxTreeAdd{Array,Item}, so that we can generate
@@ -309,6 +350,19 @@ out_free_str:
 	free(str);
 }
 
+static const void *newt__symbol_tree_get_current(newtComponent self)
+{
+	if (symbol_conf.use_callchain)
+		return newtCheckboxTreeGetCurrent(self);
+	return newtListboxGetCurrent(self);
+}
+
+static void perf_session__selection(newtComponent self, void *data)
+{
+	const struct symbol **symbol_ptr = data;
+	*symbol_ptr = newt__symbol_tree_get_current(self);
+}
+
 void perf_session__browse_hists(struct rb_root *hists, u64 session_total,
 				const char *helpline)
 {
@@ -322,6 +376,7 @@ void perf_session__browse_hists(struct rb_root *hists, u64 session_total,
 	char str[1024];
 	newtComponent form, tree;
 	struct newtExitStruct es;
+	const struct symbol *selection;
 
 	snprintf(str, sizeof(str), "Samples: %Ld", session_total);
 	newtDrawRootText(0, 0, str);
@@ -336,6 +391,8 @@ void perf_session__browse_hists(struct rb_root *hists, u64 session_total,
 		tree = newtListbox(0, 0, rows - 5, (NEWT_FLAG_SCROLL |
 						       NEWT_FLAG_RETURNEXIT));
 
+	newtComponentAddCallback(tree, perf_session__selection, &selection);
+
 	list_for_each_entry(se, &hist_entry__sort_list, list) {
 		if (se->elide)
 			continue;
@@ -377,20 +434,43 @@ void perf_session__browse_hists(struct rb_root *hists, u64 session_total,
 	form = newt_form__new();
 	newtFormAddHotKey(form, 'A');
 	newtFormAddHotKey(form, 'a');
+	newtFormAddHotKey(form, NEWT_KEY_RIGHT);
 	newtFormAddComponents(form, tree, NULL);
+	selection = newt__symbol_tree_get_current(tree);
 
 	while (1) {
-		const struct symbol *selection;
+		char annotate[512];
+		const char *options[2];
+		int nr_options = 0, choice;
 
 		newtFormRun(form, &es);
-		if (es.reason == NEWT_EXIT_HOTKEY &&
-		    toupper(es.u.key) != 'A')
+		if (es.reason == NEWT_EXIT_HOTKEY) {
+			if (toupper(es.u.key) == 'A') {
+				symbol__annotate_browser(selection);
+				continue;
+			}
+			if (es.u.key == NEWT_KEY_ESCAPE ||
+			    toupper(es.u.key) == 'Q' ||
+			    es.u.key == CTRL('c')) {
+				if (dialog_yesno("Do you really want to exit?"))
+					break;
+				else
+					continue;
+			}
+		}
+
+		if (selection != NULL) {
+			snprintf(annotate, sizeof(annotate),
+				 "Annotate %s", selection->name);
+			options[nr_options++] = annotate;
+		}
+
+		options[nr_options++] = "Exit";
+		choice = popup_menu(nr_options, options);
+		if (choice == nr_options - 1)
 			break;
-		if (!symbol_conf.use_callchain)
-			selection = newtListboxGetCurrent(tree);
-		else
-			selection = newtCheckboxTreeGetCurrent(tree);
-		symbol__annotate_browser(selection);
+		else if (selection != NULL && choice >= 0)
+			symbol__annotate_browser(selection);
 	}
 
 	newtFormDestroy(form);
-- 
1.6.2.5


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v2 2/6] perf symbols: Avoid unnecessary symbol loading when dso list is specified
  2010-03-24 19:40 [PATCH v2 1/6] perf report: Add a popup menu to ask what operation is to be performed Arnaldo Carvalho de Melo
@ 2010-03-24 19:40 ` Arnaldo Carvalho de Melo
  2010-03-24 19:40 ` [PATCH v2 3/6] perf annotate: Allow specifying DSOs where to look for symbol Arnaldo Carvalho de Melo
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Arnaldo Carvalho de Melo @ 2010-03-24 19:40 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Arnaldo Carvalho de Melo,
	Frédéric Weisbecker, Mike Galbraith, Peter Zijlstra,
	Paul Mackerras

From: Arnaldo Carvalho de Melo <acme@redhat.com>

We were performing the full thread__find_addr_location operation, i.e.
resolving to a map/dso _and_ loading its symbols when we can optimize it
by first calling thread__find_addr_map to find just the map/dso, check
if it is one that we are interested in (passed via --dsos/-d in 'perf
annotate', 'perf report', etc) and if not avoid loading the symtab.

Nice speedup when we know which DSO we're interested in.

Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/event.c |   38 +++++++++++++++++++++++---------------
 1 files changed, 23 insertions(+), 15 deletions(-)

diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 705ec63..c2808ad 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -513,24 +513,32 @@ int event__preprocess_sample(const event_t *self, struct perf_session *session,
 
 	dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
 
-	thread__find_addr_location(thread, session, cpumode, MAP__FUNCTION,
-				   self->ip.ip, al, filter);
+	thread__find_addr_map(thread, session, cpumode, MAP__FUNCTION,
+			      self->ip.ip, al);
 	dump_printf(" ...... dso: %s\n",
 		    al->map ? al->map->dso->long_name :
 			al->level == 'H' ? "[hypervisor]" : "<not found>");
-	/*
-	 * We have to do this here as we may have a dso with no symbol hit that
-	 * has a name longer than the ones with symbols sampled.
-	 */
-	if (al->map && !sort_dso.elide && !al->map->dso->slen_calculated)
-		dso__calc_col_width(al->map->dso);
-
-	if (symbol_conf.dso_list &&
-	    (!al->map || !al->map->dso ||
-	     !(strlist__has_entry(symbol_conf.dso_list, al->map->dso->short_name) ||
-	       (al->map->dso->short_name != al->map->dso->long_name &&
-		strlist__has_entry(symbol_conf.dso_list, al->map->dso->long_name)))))
-		goto out_filtered;
+	al->sym = NULL;
+
+	if (al->map) {
+		if (symbol_conf.dso_list &&
+		    (!al->map || !al->map->dso ||
+		     !(strlist__has_entry(symbol_conf.dso_list,
+					  al->map->dso->short_name) ||
+		       (al->map->dso->short_name != al->map->dso->long_name &&
+			strlist__has_entry(symbol_conf.dso_list,
+					   al->map->dso->long_name)))))
+			goto out_filtered;
+		/*
+		 * We have to do this here as we may have a dso with no symbol
+		 * hit that has a name longer than the ones with symbols
+		 * sampled.
+		 */
+		if (!sort_dso.elide && !al->map->dso->slen_calculated)
+			dso__calc_col_width(al->map->dso);
+
+		al->sym = map__find_symbol(al->map, al->addr, filter);
+	}
 
 	if (symbol_conf.sym_list && al->sym &&
 	    !strlist__has_entry(symbol_conf.sym_list, al->sym->name))
-- 
1.6.2.5


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v2 3/6] perf annotate: Allow specifying DSOs where to look for symbol
  2010-03-24 19:40 [PATCH v2 1/6] perf report: Add a popup menu to ask what operation is to be performed Arnaldo Carvalho de Melo
  2010-03-24 19:40 ` [PATCH v2 2/6] perf symbols: Avoid unnecessary symbol loading when dso list is specified Arnaldo Carvalho de Melo
@ 2010-03-24 19:40 ` Arnaldo Carvalho de Melo
  2010-03-24 19:40 ` [PATCH v2 4/6] perf tools: Introduce struct map_symbol Arnaldo Carvalho de Melo
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Arnaldo Carvalho de Melo @ 2010-03-24 19:40 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Arnaldo Carvalho de Melo,
	Frédéric Weisbecker, Mike Galbraith, Peter Zijlstra,
	Paul Mackerras

From: Arnaldo Carvalho de Melo <acme@redhat.com>

Using the same parameter as in 'perf report', allowing to specify just
one and disambiguate between DSOs that have the symbol of interest.

Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-annotate.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 45d1466..ce9b1ef 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -591,6 +591,8 @@ static const char * const annotate_usage[] = {
 static const struct option options[] = {
 	OPT_STRING('i', "input", &input_name, "file",
 		    "input file name"),
+	OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
+		   "only consider symbols in these dsos"),
 	OPT_STRING('s', "symbol", &sym_hist_filter, "symbol",
 		    "symbol to annotate"),
 	OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
-- 
1.6.2.5


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v2 4/6] perf tools: Introduce struct map_symbol
  2010-03-24 19:40 [PATCH v2 1/6] perf report: Add a popup menu to ask what operation is to be performed Arnaldo Carvalho de Melo
  2010-03-24 19:40 ` [PATCH v2 2/6] perf symbols: Avoid unnecessary symbol loading when dso list is specified Arnaldo Carvalho de Melo
  2010-03-24 19:40 ` [PATCH v2 3/6] perf annotate: Allow specifying DSOs where to look for symbol Arnaldo Carvalho de Melo
@ 2010-03-24 19:40 ` Arnaldo Carvalho de Melo
  2010-03-24 19:40 ` [PATCH v2 5/6] perf callchains: Store the map together with the symbol Arnaldo Carvalho de Melo
  2010-03-24 19:40 ` [PATCH v2 6/6] perf report: Pass the DSO to 'perf annotate' Arnaldo Carvalho de Melo
  4 siblings, 0 replies; 6+ messages in thread
From: Arnaldo Carvalho de Melo @ 2010-03-24 19:40 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Arnaldo Carvalho de Melo,
	Frédéric Weisbecker, Mike Galbraith, Peter Zijlstra,
	Paul Mackerras

From: Arnaldo Carvalho de Melo <acme@redhat.com>

That will be in both struct hist_entry and struct callchain_list, so
that the TUI can store a pointer to the pair (map, symbol) in the trees
where hist_entries and callchain_lists are present, to allow precise
annotation instead of looking for the first symbol with the selected
name.

Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-annotate.c |   34 +++++++++++++++++-----------------
 tools/perf/util/hist.c        |    8 +++++---
 tools/perf/util/newt.c        |    4 ++--
 tools/perf/util/sort.c        |   22 +++++++++++-----------
 tools/perf/util/sort.h        |    3 +--
 tools/perf/util/symbol.h      |    5 +++++
 6 files changed, 41 insertions(+), 35 deletions(-)

diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index ce9b1ef..887e8e0 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -69,13 +69,13 @@ static int sym__alloc_hist(struct symbol *self)
 static int annotate__hist_hit(struct hist_entry *he, u64 ip)
 {
 	unsigned int sym_size, offset;
-	struct symbol *sym = he->sym;
+	struct symbol *sym = he->ms.sym;
 	struct sym_priv *priv;
 	struct sym_hist *h;
 
 	he->count++;
 
-	if (!sym || !he->map)
+	if (!sym || !he->ms.map)
 		return 0;
 
 	priv = symbol__priv(sym);
@@ -85,7 +85,7 @@ static int annotate__hist_hit(struct hist_entry *he, u64 ip)
 	sym_size = sym->end - sym->start;
 	offset = ip - sym->start;
 
-	pr_debug3("%s: ip=%#Lx\n", __func__, he->map->unmap_ip(he->map, ip));
+	pr_debug3("%s: ip=%#Lx\n", __func__, he->ms.map->unmap_ip(he->ms.map, ip));
 
 	if (offset >= sym_size)
 		return 0;
@@ -94,8 +94,8 @@ static int annotate__hist_hit(struct hist_entry *he, u64 ip)
 	h->sum++;
 	h->ip[offset]++;
 
-	pr_debug3("%#Lx %s: count++ [ip: %#Lx, %#Lx] => %Ld\n", he->sym->start,
-		  he->sym->name, ip, ip - he->sym->start, h->ip[offset]);
+	pr_debug3("%#Lx %s: count++ [ip: %#Lx, %#Lx] => %Ld\n", he->ms.sym->start,
+		  he->ms.sym->name, ip, ip - he->ms.sym->start, h->ip[offset]);
 	return 0;
 }
 
@@ -187,7 +187,7 @@ static struct objdump_line *objdump__get_next_ip_line(struct list_head *head,
 static int parse_line(FILE *file, struct hist_entry *he,
 		      struct list_head *head)
 {
-	struct symbol *sym = he->sym;
+	struct symbol *sym = he->ms.sym;
 	struct objdump_line *objdump_line;
 	char *line = NULL, *tmp, *tmp2;
 	size_t line_len;
@@ -226,7 +226,7 @@ static int parse_line(FILE *file, struct hist_entry *he,
 	}
 
 	if (line_ip != -1) {
-		u64 start = map__rip_2objdump(he->map, sym->start);
+		u64 start = map__rip_2objdump(he->ms.map, sym->start);
 		offset = line_ip - start;
 	}
 
@@ -244,7 +244,7 @@ static int objdump_line__print(struct objdump_line *self,
 			       struct list_head *head,
 			       struct hist_entry *he, u64 len)
 {
-	struct symbol *sym = he->sym;
+	struct symbol *sym = he->ms.sym;
 	static const char *prev_line;
 	static const char *prev_color;
 
@@ -327,7 +327,7 @@ static void insert_source_line(struct sym_ext *sym_ext)
 
 static void free_source_line(struct hist_entry *he, int len)
 {
-	struct sym_priv *priv = symbol__priv(he->sym);
+	struct sym_priv *priv = symbol__priv(he->ms.sym);
 	struct sym_ext *sym_ext = priv->ext;
 	int i;
 
@@ -346,7 +346,7 @@ static void free_source_line(struct hist_entry *he, int len)
 static void
 get_source_line(struct hist_entry *he, int len, const char *filename)
 {
-	struct symbol *sym = he->sym;
+	struct symbol *sym = he->ms.sym;
 	u64 start;
 	int i;
 	char cmd[PATH_MAX * 2];
@@ -361,7 +361,7 @@ get_source_line(struct hist_entry *he, int len, const char *filename)
 	if (!priv->ext)
 		return;
 
-	start = he->map->unmap_ip(he->map, sym->start);
+	start = he->ms.map->unmap_ip(he->ms.map, sym->start);
 
 	for (i = 0; i < len; i++) {
 		char *path = NULL;
@@ -425,7 +425,7 @@ static void print_summary(const char *filename)
 
 static void hist_entry__print_hits(struct hist_entry *self)
 {
-	struct symbol *sym = self->sym;
+	struct symbol *sym = self->ms.sym;
 	struct sym_priv *priv = symbol__priv(sym);
 	struct sym_hist *h = priv->hist;
 	u64 len = sym->end - sym->start, offset;
@@ -439,9 +439,9 @@ static void hist_entry__print_hits(struct hist_entry *self)
 
 static void annotate_sym(struct hist_entry *he)
 {
-	struct map *map = he->map;
+	struct map *map = he->ms.map;
 	struct dso *dso = map->dso;
-	struct symbol *sym = he->sym;
+	struct symbol *sym = he->ms.sym;
 	const char *filename = dso->long_name, *d_filename;
 	u64 len;
 	char command[PATH_MAX*2];
@@ -526,17 +526,17 @@ static void perf_session__find_annotations(struct perf_session *self)
 		struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node);
 		struct sym_priv *priv;
 
-		if (he->sym == NULL)
+		if (he->ms.sym == NULL)
 			continue;
 
-		priv = symbol__priv(he->sym);
+		priv = symbol__priv(he->ms.sym);
 		if (priv->hist == NULL)
 			continue;
 
 		annotate_sym(he);
 		/*
 		 * Since we have a hist_entry per IP for the same symbol, free
-		 * he->sym->hist to signal we already processed this symbol.
+		 * he->ms.sym->hist to signal we already processed this symbol.
 		 */
 		free(priv->hist);
 		priv->hist = NULL;
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 5843a9c..4eefb52 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -22,8 +22,10 @@ struct hist_entry *__perf_session__add_hist_entry(struct rb_root *hists,
 	struct hist_entry *he;
 	struct hist_entry entry = {
 		.thread	= al->thread,
-		.map	= al->map,
-		.sym	= al->sym,
+		.ms = {
+			.map	= al->map,
+			.sym	= al->sym,
+		},
 		.ip	= al->addr,
 		.level	= al->level,
 		.count	= count,
@@ -654,7 +656,7 @@ print_entries:
 		if (symbol_conf.use_callchain)
 			ret += hist_entry__fprintf_callchain(h, fp, session_total);
 
-		if (h->map == NULL && verbose > 1) {
+		if (h->ms.map == NULL && verbose > 1) {
 			__map_groups__fprintf_maps(&h->thread->mg,
 						   MAP__FUNCTION, fp);
 			fprintf(fp, "%.10s end\n", graph_dotted_line);
diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c
index a3465a0..25cd2e1 100644
--- a/tools/perf/util/newt.c
+++ b/tools/perf/util/newt.c
@@ -287,9 +287,9 @@ static size_t hist_entry__append_browser(struct hist_entry *self,
 
 		indexes[0] = NEWT_ARG_APPEND;
 		indexes[1] = NEWT_ARG_LAST;
-		newt_checkbox_tree__add(tree, s, self->sym, indexes);
+		newt_checkbox_tree__add(tree, s, self->ms.sym, indexes);
 	} else
-		newtListboxAppendEntry(tree, s, self->sym);
+		newtListboxAppendEntry(tree, s, self->ms.sym);
 
 	return strlen(s);
 }
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index cb0f327..9b80c13 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -131,8 +131,8 @@ sort__comm_print(FILE *fp, struct hist_entry *self, unsigned int width)
 int64_t
 sort__dso_cmp(struct hist_entry *left, struct hist_entry *right)
 {
-	struct dso *dso_l = left->map ? left->map->dso : NULL;
-	struct dso *dso_r = right->map ? right->map->dso : NULL;
+	struct dso *dso_l = left->ms.map ? left->ms.map->dso : NULL;
+	struct dso *dso_r = right->ms.map ? right->ms.map->dso : NULL;
 	const char *dso_name_l, *dso_name_r;
 
 	if (!dso_l || !dso_r)
@@ -152,9 +152,9 @@ sort__dso_cmp(struct hist_entry *left, struct hist_entry *right)
 size_t
 sort__dso_print(FILE *fp, struct hist_entry *self, unsigned int width)
 {
-	if (self->map && self->map->dso) {
-		const char *dso_name = !verbose ? self->map->dso->short_name :
-						  self->map->dso->long_name;
+	if (self->ms.map && self->ms.map->dso) {
+		const char *dso_name = !verbose ? self->ms.map->dso->short_name :
+						  self->ms.map->dso->long_name;
 		return repsep_fprintf(fp, "%-*s", width, dso_name);
 	}
 
@@ -168,11 +168,11 @@ sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
 {
 	u64 ip_l, ip_r;
 
-	if (left->sym == right->sym)
+	if (left->ms.sym == right->ms.sym)
 		return 0;
 
-	ip_l = left->sym ? left->sym->start : left->ip;
-	ip_r = right->sym ? right->sym->start : right->ip;
+	ip_l = left->ms.sym ? left->ms.sym->start : left->ip;
+	ip_r = right->ms.sym ? right->ms.sym->start : right->ip;
 
 	return (int64_t)(ip_r - ip_l);
 }
@@ -184,13 +184,13 @@ sort__sym_print(FILE *fp, struct hist_entry *self, unsigned int width __used)
 	size_t ret = 0;
 
 	if (verbose) {
-		char o = self->map ? dso__symtab_origin(self->map->dso) : '!';
+		char o = self->ms.map ? dso__symtab_origin(self->ms.map->dso) : '!';
 		ret += repsep_fprintf(fp, "%#018llx %c ", (u64)self->ip, o);
 	}
 
 	ret += repsep_fprintf(fp, "[%c] ", self->level);
-	if (self->sym)
-		ret += repsep_fprintf(fp, "%s", self->sym->name);
+	if (self->ms.sym)
+		ret += repsep_fprintf(fp, "%s", self->ms.sym->name);
 	else
 		ret += repsep_fprintf(fp, "%#016llx", (u64)self->ip);
 
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 753f9ea..5985686 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -45,8 +45,7 @@ struct hist_entry {
 	struct rb_node		rb_node;
 	u64			count;
 	struct thread		*thread;
-	struct map		*map;
-	struct symbol		*sym;
+	struct map_symbol	ms;
 	u64			ip;
 	char			level;
 	struct symbol	  *parent;
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 0da2455..a4a894b 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -88,6 +88,11 @@ struct ref_reloc_sym {
 	u64		unrelocated_addr;
 };
 
+struct map_symbol {
+	struct map    *map;
+	struct symbol *sym;
+};
+
 struct addr_location {
 	struct thread *thread;
 	struct map    *map;
-- 
1.6.2.5


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v2 5/6] perf callchains: Store the map together with the symbol
  2010-03-24 19:40 [PATCH v2 1/6] perf report: Add a popup menu to ask what operation is to be performed Arnaldo Carvalho de Melo
                   ` (2 preceding siblings ...)
  2010-03-24 19:40 ` [PATCH v2 4/6] perf tools: Introduce struct map_symbol Arnaldo Carvalho de Melo
@ 2010-03-24 19:40 ` Arnaldo Carvalho de Melo
  2010-03-24 19:40 ` [PATCH v2 6/6] perf report: Pass the DSO to 'perf annotate' Arnaldo Carvalho de Melo
  4 siblings, 0 replies; 6+ messages in thread
From: Arnaldo Carvalho de Melo @ 2010-03-24 19:40 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Arnaldo Carvalho de Melo,
	Frédéric Weisbecker, Mike Galbraith, Peter Zijlstra,
	Paul Mackerras

From: Arnaldo Carvalho de Melo <acme@redhat.com>

We need this to know where a symbol in a callchain came from, for
various reasons, among them precise annotation from a TUI/GUI tool.

Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-report.c |    3 ++-
 tools/perf/util/callchain.c |   21 ++++++++++-----------
 tools/perf/util/callchain.h |    4 ++--
 tools/perf/util/hist.c      |   14 +++++++-------
 tools/perf/util/newt.c      |    8 ++++----
 tools/perf/util/session.c   |   13 +++++++------
 tools/perf/util/session.h   |    8 ++++----
 7 files changed, 36 insertions(+), 35 deletions(-)

diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index d609afb..6ab1698 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -81,7 +81,8 @@ static int perf_session__add_hist_entry(struct perf_session *self,
 					struct addr_location *al,
 					struct sample_data *data)
 {
-	struct symbol **syms = NULL, *parent = NULL;
+	struct map_symbol *syms = NULL;
+	struct symbol *parent = NULL;
 	bool hit;
 	int err;
 	struct hist_entry *he;
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index 883844e..db628af 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -185,8 +185,8 @@ create_child(struct callchain_node *parent, bool inherit_children)
 
 
 struct resolved_ip {
-	u64		ip;
-	struct symbol	*sym;
+	u64		  ip;
+	struct map_symbol ms;
 };
 
 struct resolved_chain {
@@ -212,7 +212,7 @@ fill_node(struct callchain_node *node, struct resolved_chain *chain, int start)
 			return;
 		}
 		call->ip = chain->ips[i].ip;
-		call->sym = chain->ips[i].sym;
+		call->ms = chain->ips[i].ms;
 		list_add_tail(&call->list, &node->val);
 	}
 	node->val_nr = chain->nr - start;
@@ -318,10 +318,10 @@ __append_chain(struct callchain_node *root, struct resolved_chain *chain,
 		if (i == chain->nr)
 			break;
 
-		sym = chain->ips[i].sym;
+		sym = chain->ips[i].ms.sym;
 
-		if (cnode->sym && sym) {
-			if (cnode->sym->start != sym->start)
+		if (cnode->ms.sym && sym) {
+			if (cnode->ms.sym->start != sym->start)
 				break;
 		} else if (cnode->ip != chain->ips[i].ip)
 			break;
@@ -353,9 +353,8 @@ __append_chain(struct callchain_node *root, struct resolved_chain *chain,
 	return 0;
 }
 
-static void
-filter_context(struct ip_callchain *old, struct resolved_chain *new,
-	       struct symbol **syms)
+static void filter_context(struct ip_callchain *old, struct resolved_chain *new,
+			   struct map_symbol *syms)
 {
 	int i, j = 0;
 
@@ -364,7 +363,7 @@ filter_context(struct ip_callchain *old, struct resolved_chain *new,
 			continue;
 
 		new->ips[j].ip = old->ips[i];
-		new->ips[j].sym = syms[i];
+		new->ips[j].ms = syms[i];
 		j++;
 	}
 
@@ -373,7 +372,7 @@ filter_context(struct ip_callchain *old, struct resolved_chain *new,
 
 
 int append_chain(struct callchain_node *root, struct ip_callchain *chain,
-		  struct symbol **syms)
+		 struct map_symbol *syms)
 {
 	struct resolved_chain *filtered;
 
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index bbd76da..8a7e8bb 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -39,7 +39,7 @@ struct callchain_param {
 
 struct callchain_list {
 	u64			ip;
-	struct symbol		*sym;
+	struct map_symbol	ms;
 	struct list_head	list;
 };
 
@@ -57,5 +57,5 @@ static inline u64 cumul_hits(struct callchain_node *node)
 
 int register_callchain_param(struct callchain_param *param);
 int append_chain(struct callchain_node *root, struct ip_callchain *chain,
-		 struct symbol **syms);
+		 struct map_symbol *syms);
 #endif	/* __PERF_CALLCHAIN_H */
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 4eefb52..09e09e7 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -260,8 +260,8 @@ static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain,
 		} else
 			ret += fprintf(fp, "%s", "          ");
 	}
-	if (chain->sym)
-		ret += fprintf(fp, "%s\n", chain->sym->name);
+	if (chain->ms.sym)
+		ret += fprintf(fp, "%s\n", chain->ms.sym->name);
 	else
 		ret += fprintf(fp, "%p\n", (void *)(long)chain->ip);
 
@@ -280,7 +280,7 @@ static void init_rem_hits(void)
 	}
 
 	strcpy(rem_sq_bracket->name, "[...]");
-	rem_hits.sym = rem_sq_bracket;
+	rem_hits.ms.sym = rem_sq_bracket;
 }
 
 static size_t __callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
@@ -382,8 +382,8 @@ static size_t callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
 		} else
 			ret += callchain__fprintf_left_margin(fp, left_margin);
 
-		if (chain->sym)
-			ret += fprintf(fp, " %s\n", chain->sym->name);
+		if (chain->ms.sym)
+			ret += fprintf(fp, " %s\n", chain->ms.sym->name);
 		else
 			ret += fprintf(fp, " %p\n", (void *)(long)chain->ip);
 	}
@@ -408,8 +408,8 @@ static size_t callchain__fprintf_flat(FILE *fp, struct callchain_node *self,
 	list_for_each_entry(chain, &self->val, list) {
 		if (chain->ip >= PERF_CONTEXT_MAX)
 			continue;
-		if (chain->sym)
-			ret += fprintf(fp, "                %s\n", chain->sym->name);
+		if (chain->ms.sym)
+			ret += fprintf(fp, "                %s\n", chain->ms.sym->name);
 		else
 			ret += fprintf(fp, "                %p\n",
 					(void *)(long)chain->ip);
diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c
index 25cd2e1..f6953ca 100644
--- a/tools/perf/util/newt.c
+++ b/tools/perf/util/newt.c
@@ -104,8 +104,8 @@ static void newt_checkbox_tree__add(newtComponent tree, const char *str,
 static char *callchain_list__sym_name(struct callchain_list *self,
 				      char *bf, size_t bfsize)
 {
-	if (self->sym)
-		return self->sym->name;
+	if (self->ms.sym)
+		return self->ms.sym->name;
 
 	snprintf(bf, bfsize, "%#Lx", self->ip);
 	return bf;
@@ -157,7 +157,7 @@ static void __callchain__append_graph_browser(struct callchain_node *self,
 				indexes[depth + 2] = NEWT_ARG_LAST;
 				++chain_idx;
 			}
-			newt_checkbox_tree__add(tree, str, chain->sym, indexes);
+			newt_checkbox_tree__add(tree, str, chain->ms.sym, indexes);
 			free(alloc_str);
 			++printed;
 		}
@@ -193,7 +193,7 @@ static void callchain__append_graph_browser(struct callchain_node *self,
 			continue;
 
 		str = callchain_list__sym_name(chain, ipstr, sizeof(ipstr));
-		newt_checkbox_tree__add(tree, str, chain->sym, indexes);
+		newt_checkbox_tree__add(tree, str, chain->ms.sym, indexes);
 	}
 
 	indexes[1] = parent_idx;
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index eed1cb8..2cef373 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -117,13 +117,13 @@ static bool symbol__match_parent_regex(struct symbol *sym)
 	return 0;
 }
 
-struct symbol **perf_session__resolve_callchain(struct perf_session *self,
-						struct thread *thread,
-						struct ip_callchain *chain,
-						struct symbol **parent)
+struct map_symbol *perf_session__resolve_callchain(struct perf_session *self,
+						   struct thread *thread,
+						   struct ip_callchain *chain,
+						   struct symbol **parent)
 {
 	u8 cpumode = PERF_RECORD_MISC_USER;
-	struct symbol **syms = NULL;
+	struct map_symbol *syms = NULL;
 	unsigned int i;
 
 	if (symbol_conf.use_callchain) {
@@ -160,7 +160,8 @@ struct symbol **perf_session__resolve_callchain(struct perf_session *self,
 				*parent = al.sym;
 			if (!symbol_conf.use_callchain)
 				break;
-			syms[i] = al.sym;
+			syms[i].map = al.map;
+			syms[i].sym = al.sym;
 		}
 	}
 
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 34d7339..631f815 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -57,10 +57,10 @@ int __perf_session__process_events(struct perf_session *self,
 int perf_session__process_events(struct perf_session *self,
 				 struct perf_event_ops *event_ops);
 
-struct symbol **perf_session__resolve_callchain(struct perf_session *self,
-						struct thread *thread,
-						struct ip_callchain *chain,
-						struct symbol **parent);
+struct map_symbol *perf_session__resolve_callchain(struct perf_session *self,
+						   struct thread *thread,
+						   struct ip_callchain *chain,
+						   struct symbol **parent);
 
 bool perf_session__has_traces(struct perf_session *self, const char *msg);
 
-- 
1.6.2.5


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v2 6/6] perf report: Pass the DSO to 'perf annotate'
  2010-03-24 19:40 [PATCH v2 1/6] perf report: Add a popup menu to ask what operation is to be performed Arnaldo Carvalho de Melo
                   ` (3 preceding siblings ...)
  2010-03-24 19:40 ` [PATCH v2 5/6] perf callchains: Store the map together with the symbol Arnaldo Carvalho de Melo
@ 2010-03-24 19:40 ` Arnaldo Carvalho de Melo
  4 siblings, 0 replies; 6+ messages in thread
From: Arnaldo Carvalho de Melo @ 2010-03-24 19:40 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Arnaldo Carvalho de Melo,
	Frédéric Weisbecker, Mike Galbraith, Peter Zijlstra,
	Paul Mackerras

From: Arnaldo Carvalho de Melo <acme@redhat.com>

So that we ensure that the symbol asked for annotation really is in the
DSO we are interested in.

Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/newt.c |   49 ++++++++++++++++++++++++++---------------------
 1 files changed, 27 insertions(+), 22 deletions(-)

diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c
index f6953ca..12572b5 100644
--- a/tools/perf/util/newt.c
+++ b/tools/perf/util/newt.c
@@ -157,7 +157,7 @@ static void __callchain__append_graph_browser(struct callchain_node *self,
 				indexes[depth + 2] = NEWT_ARG_LAST;
 				++chain_idx;
 			}
-			newt_checkbox_tree__add(tree, str, chain->ms.sym, indexes);
+			newt_checkbox_tree__add(tree, str, &chain->ms, indexes);
 			free(alloc_str);
 			++printed;
 		}
@@ -193,7 +193,7 @@ static void callchain__append_graph_browser(struct callchain_node *self,
 			continue;
 
 		str = callchain_list__sym_name(chain, ipstr, sizeof(ipstr));
-		newt_checkbox_tree__add(tree, str, chain->ms.sym, indexes);
+		newt_checkbox_tree__add(tree, str, &chain->ms, indexes);
 	}
 
 	indexes[1] = parent_idx;
@@ -287,14 +287,14 @@ static size_t hist_entry__append_browser(struct hist_entry *self,
 
 		indexes[0] = NEWT_ARG_APPEND;
 		indexes[1] = NEWT_ARG_LAST;
-		newt_checkbox_tree__add(tree, s, self->ms.sym, indexes);
+		newt_checkbox_tree__add(tree, s, &self->ms, indexes);
 	} else
-		newtListboxAppendEntry(tree, s, self->ms.sym);
+		newtListboxAppendEntry(tree, s, &self->ms);
 
 	return strlen(s);
 }
 
-static void symbol__annotate_browser(const struct symbol *self)
+static void map_symbol__annotate_browser(const struct map_symbol *self)
 {
 	FILE *fp;
 	int cols, rows;
@@ -305,10 +305,11 @@ static void symbol__annotate_browser(const struct symbol *self)
 	size_t max_usable_width;
 	char *line = NULL;
 
-	if (self == NULL)
+	if (self->sym == NULL)
 		return;
 
-	if (asprintf(&str, "perf annotate %s 2>&1 | expand", self->name) < 0)
+	if (asprintf(&str, "perf annotate -d \"%s\" %s 2>&1 | expand",
+		     self->map->dso->name, self->sym->name) < 0)
 		return;
 
 	fp = popen(str, "r");
@@ -338,7 +339,7 @@ static void symbol__annotate_browser(const struct symbol *self)
 
 	newtListboxSetWidth(tree, max_line_len);
 
-	newtCenteredWindow(max_line_len + 2, rows - 5, self->name);
+	newtCenteredWindow(max_line_len + 2, rows - 5, self->sym->name);
 	form = newt_form__new();
 	newtFormAddComponents(form, tree, NULL);
 
@@ -359,7 +360,7 @@ static const void *newt__symbol_tree_get_current(newtComponent self)
 
 static void perf_session__selection(newtComponent self, void *data)
 {
-	const struct symbol **symbol_ptr = data;
+	const struct map_symbol **symbol_ptr = data;
 	*symbol_ptr = newt__symbol_tree_get_current(self);
 }
 
@@ -376,7 +377,7 @@ void perf_session__browse_hists(struct rb_root *hists, u64 session_total,
 	char str[1024];
 	newtComponent form, tree;
 	struct newtExitStruct es;
-	const struct symbol *selection;
+	const struct map_symbol *selection;
 
 	snprintf(str, sizeof(str), "Samples: %Ld", session_total);
 	newtDrawRootText(0, 0, str);
@@ -416,11 +417,8 @@ void perf_session__browse_hists(struct rb_root *hists, u64 session_total,
 		int len = hist_entry__append_browser(h, tree, session_total);
 		if (len > max_len)
 			max_len = len;
-		if (symbol_conf.use_callchain) {
+		if (symbol_conf.use_callchain)
 			hist_entry__append_callchain_browser(h, tree, session_total, idx++);
-			if (idx > 3300)
-				break;
-		}
 	}
 
 	if (max_len > cols)
@@ -445,10 +443,8 @@ void perf_session__browse_hists(struct rb_root *hists, u64 session_total,
 
 		newtFormRun(form, &es);
 		if (es.reason == NEWT_EXIT_HOTKEY) {
-			if (toupper(es.u.key) == 'A') {
-				symbol__annotate_browser(selection);
-				continue;
-			}
+			if (toupper(es.u.key) == 'A')
+				goto do_annotate;
 			if (es.u.key == NEWT_KEY_ESCAPE ||
 			    toupper(es.u.key) == 'Q' ||
 			    es.u.key == CTRL('c')) {
@@ -459,9 +455,9 @@ void perf_session__browse_hists(struct rb_root *hists, u64 session_total,
 			}
 		}
 
-		if (selection != NULL) {
+		if (selection->sym != NULL) {
 			snprintf(annotate, sizeof(annotate),
-				 "Annotate %s", selection->name);
+				 "Annotate %s", selection->sym->name);
 			options[nr_options++] = annotate;
 		}
 
@@ -469,8 +465,17 @@ void perf_session__browse_hists(struct rb_root *hists, u64 session_total,
 		choice = popup_menu(nr_options, options);
 		if (choice == nr_options - 1)
 			break;
-		else if (selection != NULL && choice >= 0)
-			symbol__annotate_browser(selection);
+do_annotate:
+		if (selection->sym != NULL && choice >= 0) {
+			if (selection->map->dso->origin == DSO__ORIG_KERNEL) {
+				newtPopHelpLine();
+				newtPushHelpLine("No vmlinux file found, can't "
+						 "annotate with just a "
+						 "kallsyms file");
+				continue;
+			}
+			map_symbol__annotate_browser(selection);
+		}
 	}
 
 	newtFormDestroy(form);
-- 
1.6.2.5


^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2010-03-24 19:41 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-03-24 19:40 [PATCH v2 1/6] perf report: Add a popup menu to ask what operation is to be performed Arnaldo Carvalho de Melo
2010-03-24 19:40 ` [PATCH v2 2/6] perf symbols: Avoid unnecessary symbol loading when dso list is specified Arnaldo Carvalho de Melo
2010-03-24 19:40 ` [PATCH v2 3/6] perf annotate: Allow specifying DSOs where to look for symbol Arnaldo Carvalho de Melo
2010-03-24 19:40 ` [PATCH v2 4/6] perf tools: Introduce struct map_symbol Arnaldo Carvalho de Melo
2010-03-24 19:40 ` [PATCH v2 5/6] perf callchains: Store the map together with the symbol Arnaldo Carvalho de Melo
2010-03-24 19:40 ` [PATCH v2 6/6] perf report: Pass the DSO to 'perf annotate' Arnaldo Carvalho de Melo

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.