Skip to content

Commit

Permalink
perf tools: Adjust kallsyms for relocated kernel
Browse files Browse the repository at this point in the history
If the kernel is relocated at boot time, kallsyms will not match data
recorded previously.

That does not matter for modules because they are corrected anyway.  It
also does not matter if vmlinux is being used for symbols. But if perf
tools has only kallsyms then the symbols will not match.

Fix by applying the delta gained by comparing the old and current
addresses of the relocation reference symbol.

Signed-off-by: Adrian Hunter <[email protected]>
Tested-by: Jiri Olsa <[email protected]>
Cc: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
  • Loading branch information
ahunter6 authored and acmel committed Jan 31, 2014
1 parent c080f72 commit d9b62ab
Showing 1 changed file with 38 additions and 2 deletions.
40 changes: 38 additions & 2 deletions tools/perf/util/symbol.c
Original file line number Diff line number Diff line change
Expand Up @@ -627,7 +627,7 @@ static int dso__split_kallsyms_for_kcore(struct dso *dso, struct map *map,
* kernel range is broken in several maps, named [kernel].N, as we don't have
* the original ELF section names vmlinux have.
*/
static int dso__split_kallsyms(struct dso *dso, struct map *map,
static int dso__split_kallsyms(struct dso *dso, struct map *map, u64 delta,
symbol_filter_t filter)
{
struct map_groups *kmaps = map__kmap(map)->kmaps;
Expand Down Expand Up @@ -692,6 +692,12 @@ static int dso__split_kallsyms(struct dso *dso, struct map *map,
char dso_name[PATH_MAX];
struct dso *ndso;

if (delta) {
/* Kernel was relocated at boot time */
pos->start -= delta;
pos->end -= delta;
}

if (count == 0) {
curr_map = map;
goto filter_symbol;
Expand Down Expand Up @@ -721,6 +727,10 @@ static int dso__split_kallsyms(struct dso *dso, struct map *map,
curr_map->map_ip = curr_map->unmap_ip = identity__map_ip;
map_groups__insert(kmaps, curr_map);
++kernel_range;
} else if (delta) {
/* Kernel was relocated at boot time */
pos->start -= delta;
pos->end -= delta;
}
filter_symbol:
if (filter && filter(curr_map, pos)) {
Expand Down Expand Up @@ -1130,15 +1140,41 @@ static int dso__load_kcore(struct dso *dso, struct map *map,
return -EINVAL;
}

/*
* If the kernel is relocated at boot time, kallsyms won't match. Compute the
* delta based on the relocation reference symbol.
*/
static int kallsyms__delta(struct map *map, const char *filename, u64 *delta)
{
struct kmap *kmap = map__kmap(map);
u64 addr;

if (!kmap->ref_reloc_sym || !kmap->ref_reloc_sym->name)
return 0;

addr = kallsyms__get_function_start(filename,
kmap->ref_reloc_sym->name);
if (!addr)
return -1;

*delta = addr - kmap->ref_reloc_sym->addr;
return 0;
}

int dso__load_kallsyms(struct dso *dso, const char *filename,
struct map *map, symbol_filter_t filter)
{
u64 delta = 0;

if (symbol__restricted_filename(filename, "/proc/kallsyms"))
return -1;

if (dso__load_all_kallsyms(dso, filename, map) < 0)
return -1;

if (kallsyms__delta(map, filename, &delta))
return -1;

symbols__fixup_duplicate(&dso->symbols[map->type]);
symbols__fixup_end(&dso->symbols[map->type]);

Expand All @@ -1150,7 +1186,7 @@ int dso__load_kallsyms(struct dso *dso, const char *filename,
if (!dso__load_kcore(dso, map, filename))
return dso__split_kallsyms_for_kcore(dso, map, filter);
else
return dso__split_kallsyms(dso, map, filter);
return dso__split_kallsyms(dso, map, delta, filter);
}

static int dso__load_perf_map(struct dso *dso, struct map *map,
Expand Down

0 comments on commit d9b62ab

Please sign in to comment.