mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-24 09:50:04 +00:00
perf tools: Introduce struct map_symbol
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. 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-4-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
parent
ac73c5a9c1
commit
59fd53062f
6 changed files with 41 additions and 35 deletions
|
@ -69,13 +69,13 @@ static int sym__alloc_hist(struct symbol *self)
|
||||||
static int annotate__hist_hit(struct hist_entry *he, u64 ip)
|
static int annotate__hist_hit(struct hist_entry *he, u64 ip)
|
||||||
{
|
{
|
||||||
unsigned int sym_size, offset;
|
unsigned int sym_size, offset;
|
||||||
struct symbol *sym = he->sym;
|
struct symbol *sym = he->ms.sym;
|
||||||
struct sym_priv *priv;
|
struct sym_priv *priv;
|
||||||
struct sym_hist *h;
|
struct sym_hist *h;
|
||||||
|
|
||||||
he->count++;
|
he->count++;
|
||||||
|
|
||||||
if (!sym || !he->map)
|
if (!sym || !he->ms.map)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
priv = symbol__priv(sym);
|
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;
|
sym_size = sym->end - sym->start;
|
||||||
offset = ip - 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)
|
if (offset >= sym_size)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -94,8 +94,8 @@ static int annotate__hist_hit(struct hist_entry *he, u64 ip)
|
||||||
h->sum++;
|
h->sum++;
|
||||||
h->ip[offset]++;
|
h->ip[offset]++;
|
||||||
|
|
||||||
pr_debug3("%#Lx %s: count++ [ip: %#Lx, %#Lx] => %Ld\n", he->sym->start,
|
pr_debug3("%#Lx %s: count++ [ip: %#Lx, %#Lx] => %Ld\n", he->ms.sym->start,
|
||||||
he->sym->name, ip, ip - he->sym->start, h->ip[offset]);
|
he->ms.sym->name, ip, ip - he->ms.sym->start, h->ip[offset]);
|
||||||
return 0;
|
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,
|
static int parse_line(FILE *file, struct hist_entry *he,
|
||||||
struct list_head *head)
|
struct list_head *head)
|
||||||
{
|
{
|
||||||
struct symbol *sym = he->sym;
|
struct symbol *sym = he->ms.sym;
|
||||||
struct objdump_line *objdump_line;
|
struct objdump_line *objdump_line;
|
||||||
char *line = NULL, *tmp, *tmp2;
|
char *line = NULL, *tmp, *tmp2;
|
||||||
size_t line_len;
|
size_t line_len;
|
||||||
|
@ -226,7 +226,7 @@ static int parse_line(FILE *file, struct hist_entry *he,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (line_ip != -1) {
|
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;
|
offset = line_ip - start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,7 +244,7 @@ static int objdump_line__print(struct objdump_line *self,
|
||||||
struct list_head *head,
|
struct list_head *head,
|
||||||
struct hist_entry *he, u64 len)
|
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_line;
|
||||||
static const char *prev_color;
|
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)
|
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;
|
struct sym_ext *sym_ext = priv->ext;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -346,7 +346,7 @@ static void free_source_line(struct hist_entry *he, int len)
|
||||||
static void
|
static void
|
||||||
get_source_line(struct hist_entry *he, int len, const char *filename)
|
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;
|
u64 start;
|
||||||
int i;
|
int i;
|
||||||
char cmd[PATH_MAX * 2];
|
char cmd[PATH_MAX * 2];
|
||||||
|
@ -361,7 +361,7 @@ get_source_line(struct hist_entry *he, int len, const char *filename)
|
||||||
if (!priv->ext)
|
if (!priv->ext)
|
||||||
return;
|
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++) {
|
for (i = 0; i < len; i++) {
|
||||||
char *path = NULL;
|
char *path = NULL;
|
||||||
|
@ -425,7 +425,7 @@ static void print_summary(const char *filename)
|
||||||
|
|
||||||
static void hist_entry__print_hits(struct hist_entry *self)
|
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_priv *priv = symbol__priv(sym);
|
||||||
struct sym_hist *h = priv->hist;
|
struct sym_hist *h = priv->hist;
|
||||||
u64 len = sym->end - sym->start, offset;
|
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)
|
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 dso *dso = map->dso;
|
||||||
struct symbol *sym = he->sym;
|
struct symbol *sym = he->ms.sym;
|
||||||
const char *filename = dso->long_name, *d_filename;
|
const char *filename = dso->long_name, *d_filename;
|
||||||
u64 len;
|
u64 len;
|
||||||
char command[PATH_MAX*2];
|
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 hist_entry *he = rb_entry(nd, struct hist_entry, rb_node);
|
||||||
struct sym_priv *priv;
|
struct sym_priv *priv;
|
||||||
|
|
||||||
if (he->sym == NULL)
|
if (he->ms.sym == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
priv = symbol__priv(he->sym);
|
priv = symbol__priv(he->ms.sym);
|
||||||
if (priv->hist == NULL)
|
if (priv->hist == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
annotate_sym(he);
|
annotate_sym(he);
|
||||||
/*
|
/*
|
||||||
* Since we have a hist_entry per IP for the same symbol, free
|
* 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);
|
free(priv->hist);
|
||||||
priv->hist = NULL;
|
priv->hist = NULL;
|
||||||
|
|
|
@ -22,8 +22,10 @@ struct hist_entry *__perf_session__add_hist_entry(struct rb_root *hists,
|
||||||
struct hist_entry *he;
|
struct hist_entry *he;
|
||||||
struct hist_entry entry = {
|
struct hist_entry entry = {
|
||||||
.thread = al->thread,
|
.thread = al->thread,
|
||||||
.map = al->map,
|
.ms = {
|
||||||
.sym = al->sym,
|
.map = al->map,
|
||||||
|
.sym = al->sym,
|
||||||
|
},
|
||||||
.ip = al->addr,
|
.ip = al->addr,
|
||||||
.level = al->level,
|
.level = al->level,
|
||||||
.count = count,
|
.count = count,
|
||||||
|
@ -654,7 +656,7 @@ size_t perf_session__fprintf_hists(struct rb_root *hists,
|
||||||
if (symbol_conf.use_callchain)
|
if (symbol_conf.use_callchain)
|
||||||
ret += hist_entry__fprintf_callchain(h, fp, session_total);
|
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_groups__fprintf_maps(&h->thread->mg,
|
||||||
MAP__FUNCTION, fp);
|
MAP__FUNCTION, fp);
|
||||||
fprintf(fp, "%.10s end\n", graph_dotted_line);
|
fprintf(fp, "%.10s end\n", graph_dotted_line);
|
||||||
|
|
|
@ -287,9 +287,9 @@ static size_t hist_entry__append_browser(struct hist_entry *self,
|
||||||
|
|
||||||
indexes[0] = NEWT_ARG_APPEND;
|
indexes[0] = NEWT_ARG_APPEND;
|
||||||
indexes[1] = NEWT_ARG_LAST;
|
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
|
} else
|
||||||
newtListboxAppendEntry(tree, s, self->sym);
|
newtListboxAppendEntry(tree, s, self->ms.sym);
|
||||||
|
|
||||||
return strlen(s);
|
return strlen(s);
|
||||||
}
|
}
|
||||||
|
|
|
@ -131,8 +131,8 @@ sort__comm_print(FILE *fp, struct hist_entry *self, unsigned int width)
|
||||||
int64_t
|
int64_t
|
||||||
sort__dso_cmp(struct hist_entry *left, struct hist_entry *right)
|
sort__dso_cmp(struct hist_entry *left, struct hist_entry *right)
|
||||||
{
|
{
|
||||||
struct dso *dso_l = left->map ? left->map->dso : NULL;
|
struct dso *dso_l = left->ms.map ? left->ms.map->dso : NULL;
|
||||||
struct dso *dso_r = right->map ? right->map->dso : NULL;
|
struct dso *dso_r = right->ms.map ? right->ms.map->dso : NULL;
|
||||||
const char *dso_name_l, *dso_name_r;
|
const char *dso_name_l, *dso_name_r;
|
||||||
|
|
||||||
if (!dso_l || !dso_r)
|
if (!dso_l || !dso_r)
|
||||||
|
@ -152,9 +152,9 @@ sort__dso_cmp(struct hist_entry *left, struct hist_entry *right)
|
||||||
size_t
|
size_t
|
||||||
sort__dso_print(FILE *fp, struct hist_entry *self, unsigned int width)
|
sort__dso_print(FILE *fp, struct hist_entry *self, unsigned int width)
|
||||||
{
|
{
|
||||||
if (self->map && self->map->dso) {
|
if (self->ms.map && self->ms.map->dso) {
|
||||||
const char *dso_name = !verbose ? self->map->dso->short_name :
|
const char *dso_name = !verbose ? self->ms.map->dso->short_name :
|
||||||
self->map->dso->long_name;
|
self->ms.map->dso->long_name;
|
||||||
return repsep_fprintf(fp, "%-*s", width, dso_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;
|
u64 ip_l, ip_r;
|
||||||
|
|
||||||
if (left->sym == right->sym)
|
if (left->ms.sym == right->ms.sym)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
ip_l = left->sym ? left->sym->start : left->ip;
|
ip_l = left->ms.sym ? left->ms.sym->start : left->ip;
|
||||||
ip_r = right->sym ? right->sym->start : right->ip;
|
ip_r = right->ms.sym ? right->ms.sym->start : right->ip;
|
||||||
|
|
||||||
return (int64_t)(ip_r - ip_l);
|
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;
|
size_t ret = 0;
|
||||||
|
|
||||||
if (verbose) {
|
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, "%#018llx %c ", (u64)self->ip, o);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret += repsep_fprintf(fp, "[%c] ", self->level);
|
ret += repsep_fprintf(fp, "[%c] ", self->level);
|
||||||
if (self->sym)
|
if (self->ms.sym)
|
||||||
ret += repsep_fprintf(fp, "%s", self->sym->name);
|
ret += repsep_fprintf(fp, "%s", self->ms.sym->name);
|
||||||
else
|
else
|
||||||
ret += repsep_fprintf(fp, "%#016llx", (u64)self->ip);
|
ret += repsep_fprintf(fp, "%#016llx", (u64)self->ip);
|
||||||
|
|
||||||
|
|
|
@ -45,8 +45,7 @@ struct hist_entry {
|
||||||
struct rb_node rb_node;
|
struct rb_node rb_node;
|
||||||
u64 count;
|
u64 count;
|
||||||
struct thread *thread;
|
struct thread *thread;
|
||||||
struct map *map;
|
struct map_symbol ms;
|
||||||
struct symbol *sym;
|
|
||||||
u64 ip;
|
u64 ip;
|
||||||
char level;
|
char level;
|
||||||
struct symbol *parent;
|
struct symbol *parent;
|
||||||
|
|
|
@ -88,6 +88,11 @@ struct ref_reloc_sym {
|
||||||
u64 unrelocated_addr;
|
u64 unrelocated_addr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct map_symbol {
|
||||||
|
struct map *map;
|
||||||
|
struct symbol *sym;
|
||||||
|
};
|
||||||
|
|
||||||
struct addr_location {
|
struct addr_location {
|
||||||
struct thread *thread;
|
struct thread *thread;
|
||||||
struct map *map;
|
struct map *map;
|
||||||
|
|
Loading…
Reference in a new issue