perf report: Fix a wrong offset issue when using /proc/kcore
When a valid vmlinux is not found, 'perf report' falls back to look at /proc/kcore. In this case, it will report the impossible large offset. For example: # perf record -b -e cycles:k find /etc/ > /dev/null # perf report --stdio --branch-history 22.77% _vm_normal_page+18446603336221188162 | ---page_remove_rmap +18446603336221188324 page_remove_rmap +18446603336221188487 (cycles:5) unlock_page_memcg +18446603336221188096 page_remove_rmap +18446603336221188327 (cycles:1) The issue is the value which is passed to parameter 'addr' in __get_srcline() is the objdump address. It's not correct if we calculate the offset by using 'addr - sym->start'. This patch creates a new parameter 'ip' in __get_srcline(). It is not converted to objdump address. With this patch, the perf report output is: 22.77% _vm_normal_page+66 | ---page_remove_rmap +228 page_remove_rmap +391 (cycles:5) unlock_page_memcg +0 page_remove_rmap +231 (cycles:1) page_remove_rmap +236 Committer testing: Make sure you get any valid vmlinux out of the way, using '-v' on the 'perf report' case and deleting it from places where perf searches them, like your kernel build dir and the build-id cache, in ~/.debug/. Reported-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Jin Yao <yao.jin@linux.intel.com> Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Kan Liang <kan.liang@intel.com> Cc: Peter Zijlstra <peterz@infradead.org> Link: http://lkml.kernel.org/r/1514564812-17344-1-git-send-email-yao.jin@linux.intel.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
44df1afdb1
commit
935f5a9d45
|
@ -1960,7 +1960,8 @@ static void annotation__calc_lines(struct annotation *notes, struct map *map,
|
|||
if (percent_max <= 0.5)
|
||||
continue;
|
||||
|
||||
al->path = get_srcline(map->dso, start + al->offset, NULL, false, true);
|
||||
al->path = get_srcline(map->dso, start + al->offset, NULL,
|
||||
false, true, start + al->offset);
|
||||
insert_source_line(&tmp_root, al);
|
||||
}
|
||||
|
||||
|
|
|
@ -1726,7 +1726,7 @@ static char *callchain_srcline(struct map *map, struct symbol *sym, u64 ip)
|
|||
bool show_addr = callchain_param.key == CCKEY_ADDRESS;
|
||||
|
||||
srcline = get_srcline(map->dso, map__rip_2objdump(map, ip),
|
||||
sym, show_sym, show_addr);
|
||||
sym, show_sym, show_addr, ip);
|
||||
srcline__tree_insert(&map->dso->srclines, ip, srcline);
|
||||
}
|
||||
|
||||
|
|
|
@ -419,7 +419,7 @@ int map__fprintf_srcline(struct map *map, u64 addr, const char *prefix,
|
|||
if (map && map->dso) {
|
||||
srcline = get_srcline(map->dso,
|
||||
map__rip_2objdump(map, addr), NULL,
|
||||
true, true);
|
||||
true, true, addr);
|
||||
if (srcline != SRCLINE_UNKNOWN)
|
||||
ret = fprintf(fp, "%s%s", prefix, srcline);
|
||||
free_srcline(srcline);
|
||||
|
|
|
@ -336,7 +336,7 @@ char *hist_entry__get_srcline(struct hist_entry *he)
|
|||
return SRCLINE_UNKNOWN;
|
||||
|
||||
return get_srcline(map->dso, map__rip_2objdump(map, he->ip),
|
||||
he->ms.sym, true, true);
|
||||
he->ms.sym, true, true, he->ip);
|
||||
}
|
||||
|
||||
static int64_t
|
||||
|
@ -380,7 +380,8 @@ sort__srcline_from_cmp(struct hist_entry *left, struct hist_entry *right)
|
|||
map__rip_2objdump(map,
|
||||
left->branch_info->from.al_addr),
|
||||
left->branch_info->from.sym,
|
||||
true, true);
|
||||
true, true,
|
||||
left->branch_info->from.al_addr);
|
||||
}
|
||||
if (!right->branch_info->srcline_from) {
|
||||
struct map *map = right->branch_info->from.map;
|
||||
|
@ -391,7 +392,8 @@ sort__srcline_from_cmp(struct hist_entry *left, struct hist_entry *right)
|
|||
map__rip_2objdump(map,
|
||||
right->branch_info->from.al_addr),
|
||||
right->branch_info->from.sym,
|
||||
true, true);
|
||||
true, true,
|
||||
right->branch_info->from.al_addr);
|
||||
}
|
||||
return strcmp(right->branch_info->srcline_from, left->branch_info->srcline_from);
|
||||
}
|
||||
|
@ -423,7 +425,8 @@ sort__srcline_to_cmp(struct hist_entry *left, struct hist_entry *right)
|
|||
map__rip_2objdump(map,
|
||||
left->branch_info->to.al_addr),
|
||||
left->branch_info->from.sym,
|
||||
true, true);
|
||||
true, true,
|
||||
left->branch_info->to.al_addr);
|
||||
}
|
||||
if (!right->branch_info->srcline_to) {
|
||||
struct map *map = right->branch_info->to.map;
|
||||
|
@ -434,7 +437,8 @@ sort__srcline_to_cmp(struct hist_entry *left, struct hist_entry *right)
|
|||
map__rip_2objdump(map,
|
||||
right->branch_info->to.al_addr),
|
||||
right->branch_info->to.sym,
|
||||
true, true);
|
||||
true, true,
|
||||
right->branch_info->to.al_addr);
|
||||
}
|
||||
return strcmp(right->branch_info->srcline_to, left->branch_info->srcline_to);
|
||||
}
|
||||
|
@ -465,7 +469,7 @@ static char *hist_entry__get_srcfile(struct hist_entry *e)
|
|||
return no_srcfile;
|
||||
|
||||
sf = __get_srcline(map->dso, map__rip_2objdump(map, e->ip),
|
||||
e->ms.sym, false, true, true);
|
||||
e->ms.sym, false, true, true, e->ip);
|
||||
if (!strcmp(sf, SRCLINE_UNKNOWN))
|
||||
return no_srcfile;
|
||||
p = strchr(sf, ':');
|
||||
|
|
|
@ -496,7 +496,8 @@ out:
|
|||
#define A2L_FAIL_LIMIT 123
|
||||
|
||||
char *__get_srcline(struct dso *dso, u64 addr, struct symbol *sym,
|
||||
bool show_sym, bool show_addr, bool unwind_inlines)
|
||||
bool show_sym, bool show_addr, bool unwind_inlines,
|
||||
u64 ip)
|
||||
{
|
||||
char *file = NULL;
|
||||
unsigned line = 0;
|
||||
|
@ -536,7 +537,7 @@ out:
|
|||
|
||||
if (sym) {
|
||||
if (asprintf(&srcline, "%s+%" PRIu64, show_sym ? sym->name : "",
|
||||
addr - sym->start) < 0)
|
||||
ip - sym->start) < 0)
|
||||
return SRCLINE_UNKNOWN;
|
||||
} else if (asprintf(&srcline, "%s[%" PRIx64 "]", dso->short_name, addr) < 0)
|
||||
return SRCLINE_UNKNOWN;
|
||||
|
@ -550,9 +551,9 @@ void free_srcline(char *srcline)
|
|||
}
|
||||
|
||||
char *get_srcline(struct dso *dso, u64 addr, struct symbol *sym,
|
||||
bool show_sym, bool show_addr)
|
||||
bool show_sym, bool show_addr, u64 ip)
|
||||
{
|
||||
return __get_srcline(dso, addr, sym, show_sym, show_addr, false);
|
||||
return __get_srcline(dso, addr, sym, show_sym, show_addr, false, ip);
|
||||
}
|
||||
|
||||
struct srcline_node {
|
||||
|
|
|
@ -11,9 +11,10 @@ struct symbol;
|
|||
|
||||
extern bool srcline_full_filename;
|
||||
char *get_srcline(struct dso *dso, u64 addr, struct symbol *sym,
|
||||
bool show_sym, bool show_addr);
|
||||
bool show_sym, bool show_addr, u64 ip);
|
||||
char *__get_srcline(struct dso *dso, u64 addr, struct symbol *sym,
|
||||
bool show_sym, bool show_addr, bool unwind_inlines);
|
||||
bool show_sym, bool show_addr, bool unwind_inlines,
|
||||
u64 ip);
|
||||
void free_srcline(char *srcline);
|
||||
|
||||
/* insert the srcline into the DSO, which will take ownership */
|
||||
|
|
Loading…
Reference in New Issue