Commit 935f5a9d authored by Jin Yao's avatar Jin Yao Committed by Arnaldo Carvalho de Melo

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: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: default avatarJin Yao <yao.jin@linux.intel.com>
Tested-by: default avatarArnaldo 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.comSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 44df1afd
...@@ -1960,7 +1960,8 @@ static void annotation__calc_lines(struct annotation *notes, struct map *map, ...@@ -1960,7 +1960,8 @@ static void annotation__calc_lines(struct annotation *notes, struct map *map,
if (percent_max <= 0.5) if (percent_max <= 0.5)
continue; 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); insert_source_line(&tmp_root, al);
} }
......
...@@ -1726,7 +1726,7 @@ static char *callchain_srcline(struct map *map, struct symbol *sym, u64 ip) ...@@ -1726,7 +1726,7 @@ static char *callchain_srcline(struct map *map, struct symbol *sym, u64 ip)
bool show_addr = callchain_param.key == CCKEY_ADDRESS; bool show_addr = callchain_param.key == CCKEY_ADDRESS;
srcline = get_srcline(map->dso, map__rip_2objdump(map, ip), 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); srcline__tree_insert(&map->dso->srclines, ip, srcline);
} }
......
...@@ -419,7 +419,7 @@ int map__fprintf_srcline(struct map *map, u64 addr, const char *prefix, ...@@ -419,7 +419,7 @@ int map__fprintf_srcline(struct map *map, u64 addr, const char *prefix,
if (map && map->dso) { if (map && map->dso) {
srcline = get_srcline(map->dso, srcline = get_srcline(map->dso,
map__rip_2objdump(map, addr), NULL, map__rip_2objdump(map, addr), NULL,
true, true); true, true, addr);
if (srcline != SRCLINE_UNKNOWN) if (srcline != SRCLINE_UNKNOWN)
ret = fprintf(fp, "%s%s", prefix, srcline); ret = fprintf(fp, "%s%s", prefix, srcline);
free_srcline(srcline); free_srcline(srcline);
......
...@@ -336,7 +336,7 @@ char *hist_entry__get_srcline(struct hist_entry *he) ...@@ -336,7 +336,7 @@ char *hist_entry__get_srcline(struct hist_entry *he)
return SRCLINE_UNKNOWN; return SRCLINE_UNKNOWN;
return get_srcline(map->dso, map__rip_2objdump(map, he->ip), 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 static int64_t
...@@ -380,7 +380,8 @@ sort__srcline_from_cmp(struct hist_entry *left, struct hist_entry *right) ...@@ -380,7 +380,8 @@ sort__srcline_from_cmp(struct hist_entry *left, struct hist_entry *right)
map__rip_2objdump(map, map__rip_2objdump(map,
left->branch_info->from.al_addr), left->branch_info->from.al_addr),
left->branch_info->from.sym, left->branch_info->from.sym,
true, true); true, true,
left->branch_info->from.al_addr);
} }
if (!right->branch_info->srcline_from) { if (!right->branch_info->srcline_from) {
struct map *map = right->branch_info->from.map; struct map *map = right->branch_info->from.map;
...@@ -391,7 +392,8 @@ sort__srcline_from_cmp(struct hist_entry *left, struct hist_entry *right) ...@@ -391,7 +392,8 @@ sort__srcline_from_cmp(struct hist_entry *left, struct hist_entry *right)
map__rip_2objdump(map, map__rip_2objdump(map,
right->branch_info->from.al_addr), right->branch_info->from.al_addr),
right->branch_info->from.sym, 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); 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) ...@@ -423,7 +425,8 @@ sort__srcline_to_cmp(struct hist_entry *left, struct hist_entry *right)
map__rip_2objdump(map, map__rip_2objdump(map,
left->branch_info->to.al_addr), left->branch_info->to.al_addr),
left->branch_info->from.sym, left->branch_info->from.sym,
true, true); true, true,
left->branch_info->to.al_addr);
} }
if (!right->branch_info->srcline_to) { if (!right->branch_info->srcline_to) {
struct map *map = right->branch_info->to.map; struct map *map = right->branch_info->to.map;
...@@ -434,7 +437,8 @@ sort__srcline_to_cmp(struct hist_entry *left, struct hist_entry *right) ...@@ -434,7 +437,8 @@ sort__srcline_to_cmp(struct hist_entry *left, struct hist_entry *right)
map__rip_2objdump(map, map__rip_2objdump(map,
right->branch_info->to.al_addr), right->branch_info->to.al_addr),
right->branch_info->to.sym, 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); 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) ...@@ -465,7 +469,7 @@ static char *hist_entry__get_srcfile(struct hist_entry *e)
return no_srcfile; return no_srcfile;
sf = __get_srcline(map->dso, map__rip_2objdump(map, e->ip), 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)) if (!strcmp(sf, SRCLINE_UNKNOWN))
return no_srcfile; return no_srcfile;
p = strchr(sf, ':'); p = strchr(sf, ':');
......
...@@ -496,7 +496,8 @@ static struct inline_node *addr2inlines(const char *dso_name, u64 addr, ...@@ -496,7 +496,8 @@ static struct inline_node *addr2inlines(const char *dso_name, u64 addr,
#define A2L_FAIL_LIMIT 123 #define A2L_FAIL_LIMIT 123
char *__get_srcline(struct dso *dso, u64 addr, struct symbol *sym, 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; char *file = NULL;
unsigned line = 0; unsigned line = 0;
...@@ -536,7 +537,7 @@ char *__get_srcline(struct dso *dso, u64 addr, struct symbol *sym, ...@@ -536,7 +537,7 @@ char *__get_srcline(struct dso *dso, u64 addr, struct symbol *sym,
if (sym) { if (sym) {
if (asprintf(&srcline, "%s+%" PRIu64, show_sym ? sym->name : "", if (asprintf(&srcline, "%s+%" PRIu64, show_sym ? sym->name : "",
addr - sym->start) < 0) ip - sym->start) < 0)
return SRCLINE_UNKNOWN; return SRCLINE_UNKNOWN;
} else if (asprintf(&srcline, "%s[%" PRIx64 "]", dso->short_name, addr) < 0) } else if (asprintf(&srcline, "%s[%" PRIx64 "]", dso->short_name, addr) < 0)
return SRCLINE_UNKNOWN; return SRCLINE_UNKNOWN;
...@@ -550,9 +551,9 @@ void free_srcline(char *srcline) ...@@ -550,9 +551,9 @@ void free_srcline(char *srcline)
} }
char *get_srcline(struct dso *dso, u64 addr, struct symbol *sym, 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 { struct srcline_node {
......
...@@ -11,9 +11,10 @@ struct symbol; ...@@ -11,9 +11,10 @@ struct symbol;
extern bool srcline_full_filename; extern bool srcline_full_filename;
char *get_srcline(struct dso *dso, u64 addr, struct symbol *sym, 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, 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); void free_srcline(char *srcline);
/* insert the srcline into the DSO, which will take ownership */ /* insert the srcline into the DSO, which will take ownership */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment