perf callchains: Store the map together with the symbol
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. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> 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> LKML-Reference: <1269459619-982-5-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
parent
59fd53062f
commit
b3c9ac0846
|
@ -81,7 +81,8 @@ static int perf_session__add_hist_entry(struct perf_session *self,
|
||||||
struct addr_location *al,
|
struct addr_location *al,
|
||||||
struct sample_data *data)
|
struct sample_data *data)
|
||||||
{
|
{
|
||||||
struct symbol **syms = NULL, *parent = NULL;
|
struct map_symbol *syms = NULL;
|
||||||
|
struct symbol *parent = NULL;
|
||||||
bool hit;
|
bool hit;
|
||||||
int err;
|
int err;
|
||||||
struct hist_entry *he;
|
struct hist_entry *he;
|
||||||
|
|
|
@ -185,8 +185,8 @@ create_child(struct callchain_node *parent, bool inherit_children)
|
||||||
|
|
||||||
|
|
||||||
struct resolved_ip {
|
struct resolved_ip {
|
||||||
u64 ip;
|
u64 ip;
|
||||||
struct symbol *sym;
|
struct map_symbol ms;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct resolved_chain {
|
struct resolved_chain {
|
||||||
|
@ -212,7 +212,7 @@ fill_node(struct callchain_node *node, struct resolved_chain *chain, int start)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
call->ip = chain->ips[i].ip;
|
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);
|
list_add_tail(&call->list, &node->val);
|
||||||
}
|
}
|
||||||
node->val_nr = chain->nr - start;
|
node->val_nr = chain->nr - start;
|
||||||
|
@ -318,10 +318,10 @@ __append_chain(struct callchain_node *root, struct resolved_chain *chain,
|
||||||
if (i == chain->nr)
|
if (i == chain->nr)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
sym = chain->ips[i].sym;
|
sym = chain->ips[i].ms.sym;
|
||||||
|
|
||||||
if (cnode->sym && sym) {
|
if (cnode->ms.sym && sym) {
|
||||||
if (cnode->sym->start != sym->start)
|
if (cnode->ms.sym->start != sym->start)
|
||||||
break;
|
break;
|
||||||
} else if (cnode->ip != chain->ips[i].ip)
|
} else if (cnode->ip != chain->ips[i].ip)
|
||||||
break;
|
break;
|
||||||
|
@ -353,9 +353,8 @@ __append_chain(struct callchain_node *root, struct resolved_chain *chain,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void filter_context(struct ip_callchain *old, struct resolved_chain *new,
|
||||||
filter_context(struct ip_callchain *old, struct resolved_chain *new,
|
struct map_symbol *syms)
|
||||||
struct symbol **syms)
|
|
||||||
{
|
{
|
||||||
int i, j = 0;
|
int i, j = 0;
|
||||||
|
|
||||||
|
@ -364,7 +363,7 @@ filter_context(struct ip_callchain *old, struct resolved_chain *new,
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
new->ips[j].ip = old->ips[i];
|
new->ips[j].ip = old->ips[i];
|
||||||
new->ips[j].sym = syms[i];
|
new->ips[j].ms = syms[i];
|
||||||
j++;
|
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,
|
int append_chain(struct callchain_node *root, struct ip_callchain *chain,
|
||||||
struct symbol **syms)
|
struct map_symbol *syms)
|
||||||
{
|
{
|
||||||
struct resolved_chain *filtered;
|
struct resolved_chain *filtered;
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ struct callchain_param {
|
||||||
|
|
||||||
struct callchain_list {
|
struct callchain_list {
|
||||||
u64 ip;
|
u64 ip;
|
||||||
struct symbol *sym;
|
struct map_symbol ms;
|
||||||
struct list_head list;
|
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 register_callchain_param(struct callchain_param *param);
|
||||||
int append_chain(struct callchain_node *root, struct ip_callchain *chain,
|
int append_chain(struct callchain_node *root, struct ip_callchain *chain,
|
||||||
struct symbol **syms);
|
struct map_symbol *syms);
|
||||||
#endif /* __PERF_CALLCHAIN_H */
|
#endif /* __PERF_CALLCHAIN_H */
|
||||||
|
|
|
@ -260,8 +260,8 @@ static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain,
|
||||||
} else
|
} else
|
||||||
ret += fprintf(fp, "%s", " ");
|
ret += fprintf(fp, "%s", " ");
|
||||||
}
|
}
|
||||||
if (chain->sym)
|
if (chain->ms.sym)
|
||||||
ret += fprintf(fp, "%s\n", chain->sym->name);
|
ret += fprintf(fp, "%s\n", chain->ms.sym->name);
|
||||||
else
|
else
|
||||||
ret += fprintf(fp, "%p\n", (void *)(long)chain->ip);
|
ret += fprintf(fp, "%p\n", (void *)(long)chain->ip);
|
||||||
|
|
||||||
|
@ -280,7 +280,7 @@ static void init_rem_hits(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
strcpy(rem_sq_bracket->name, "[...]");
|
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,
|
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
|
} else
|
||||||
ret += callchain__fprintf_left_margin(fp, left_margin);
|
ret += callchain__fprintf_left_margin(fp, left_margin);
|
||||||
|
|
||||||
if (chain->sym)
|
if (chain->ms.sym)
|
||||||
ret += fprintf(fp, " %s\n", chain->sym->name);
|
ret += fprintf(fp, " %s\n", chain->ms.sym->name);
|
||||||
else
|
else
|
||||||
ret += fprintf(fp, " %p\n", (void *)(long)chain->ip);
|
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) {
|
list_for_each_entry(chain, &self->val, list) {
|
||||||
if (chain->ip >= PERF_CONTEXT_MAX)
|
if (chain->ip >= PERF_CONTEXT_MAX)
|
||||||
continue;
|
continue;
|
||||||
if (chain->sym)
|
if (chain->ms.sym)
|
||||||
ret += fprintf(fp, " %s\n", chain->sym->name);
|
ret += fprintf(fp, " %s\n", chain->ms.sym->name);
|
||||||
else
|
else
|
||||||
ret += fprintf(fp, " %p\n",
|
ret += fprintf(fp, " %p\n",
|
||||||
(void *)(long)chain->ip);
|
(void *)(long)chain->ip);
|
||||||
|
|
|
@ -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,
|
static char *callchain_list__sym_name(struct callchain_list *self,
|
||||||
char *bf, size_t bfsize)
|
char *bf, size_t bfsize)
|
||||||
{
|
{
|
||||||
if (self->sym)
|
if (self->ms.sym)
|
||||||
return self->sym->name;
|
return self->ms.sym->name;
|
||||||
|
|
||||||
snprintf(bf, bfsize, "%#Lx", self->ip);
|
snprintf(bf, bfsize, "%#Lx", self->ip);
|
||||||
return bf;
|
return bf;
|
||||||
|
@ -157,7 +157,7 @@ static void __callchain__append_graph_browser(struct callchain_node *self,
|
||||||
indexes[depth + 2] = NEWT_ARG_LAST;
|
indexes[depth + 2] = NEWT_ARG_LAST;
|
||||||
++chain_idx;
|
++chain_idx;
|
||||||
}
|
}
|
||||||
newt_checkbox_tree__add(tree, str, chain->sym, indexes);
|
newt_checkbox_tree__add(tree, str, chain->ms.sym, indexes);
|
||||||
free(alloc_str);
|
free(alloc_str);
|
||||||
++printed;
|
++printed;
|
||||||
}
|
}
|
||||||
|
@ -193,7 +193,7 @@ static void callchain__append_graph_browser(struct callchain_node *self,
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
str = callchain_list__sym_name(chain, ipstr, sizeof(ipstr));
|
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;
|
indexes[1] = parent_idx;
|
||||||
|
|
|
@ -117,13 +117,13 @@ static bool symbol__match_parent_regex(struct symbol *sym)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct symbol **perf_session__resolve_callchain(struct perf_session *self,
|
struct map_symbol *perf_session__resolve_callchain(struct perf_session *self,
|
||||||
struct thread *thread,
|
struct thread *thread,
|
||||||
struct ip_callchain *chain,
|
struct ip_callchain *chain,
|
||||||
struct symbol **parent)
|
struct symbol **parent)
|
||||||
{
|
{
|
||||||
u8 cpumode = PERF_RECORD_MISC_USER;
|
u8 cpumode = PERF_RECORD_MISC_USER;
|
||||||
struct symbol **syms = NULL;
|
struct map_symbol *syms = NULL;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
if (symbol_conf.use_callchain) {
|
if (symbol_conf.use_callchain) {
|
||||||
|
@ -160,7 +160,8 @@ struct symbol **perf_session__resolve_callchain(struct perf_session *self,
|
||||||
*parent = al.sym;
|
*parent = al.sym;
|
||||||
if (!symbol_conf.use_callchain)
|
if (!symbol_conf.use_callchain)
|
||||||
break;
|
break;
|
||||||
syms[i] = al.sym;
|
syms[i].map = al.map;
|
||||||
|
syms[i].sym = al.sym;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,10 +57,10 @@ int __perf_session__process_events(struct perf_session *self,
|
||||||
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 perf_event_ops *event_ops);
|
||||||
|
|
||||||
struct symbol **perf_session__resolve_callchain(struct perf_session *self,
|
struct map_symbol *perf_session__resolve_callchain(struct perf_session *self,
|
||||||
struct thread *thread,
|
struct thread *thread,
|
||||||
struct ip_callchain *chain,
|
struct ip_callchain *chain,
|
||||||
struct symbol **parent);
|
struct symbol **parent);
|
||||||
|
|
||||||
bool perf_session__has_traces(struct perf_session *self, const char *msg);
|
bool perf_session__has_traces(struct perf_session *self, const char *msg);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue