Skip to content

Commit d9b62ab

Browse files
ahunter6acmel
authored andcommitted
perf tools: Adjust kallsyms for relocated kernel
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]>
1 parent c080f72 commit d9b62ab

File tree

1 file changed

+38
-2
lines changed

1 file changed

+38
-2
lines changed

tools/perf/util/symbol.c

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -627,7 +627,7 @@ static int dso__split_kallsyms_for_kcore(struct dso *dso, struct map *map,
627627
* kernel range is broken in several maps, named [kernel].N, as we don't have
628628
* the original ELF section names vmlinux have.
629629
*/
630-
static int dso__split_kallsyms(struct dso *dso, struct map *map,
630+
static int dso__split_kallsyms(struct dso *dso, struct map *map, u64 delta,
631631
symbol_filter_t filter)
632632
{
633633
struct map_groups *kmaps = map__kmap(map)->kmaps;
@@ -692,6 +692,12 @@ static int dso__split_kallsyms(struct dso *dso, struct map *map,
692692
char dso_name[PATH_MAX];
693693
struct dso *ndso;
694694

695+
if (delta) {
696+
/* Kernel was relocated at boot time */
697+
pos->start -= delta;
698+
pos->end -= delta;
699+
}
700+
695701
if (count == 0) {
696702
curr_map = map;
697703
goto filter_symbol;
@@ -721,6 +727,10 @@ static int dso__split_kallsyms(struct dso *dso, struct map *map,
721727
curr_map->map_ip = curr_map->unmap_ip = identity__map_ip;
722728
map_groups__insert(kmaps, curr_map);
723729
++kernel_range;
730+
} else if (delta) {
731+
/* Kernel was relocated at boot time */
732+
pos->start -= delta;
733+
pos->end -= delta;
724734
}
725735
filter_symbol:
726736
if (filter && filter(curr_map, pos)) {
@@ -1130,15 +1140,41 @@ static int dso__load_kcore(struct dso *dso, struct map *map,
11301140
return -EINVAL;
11311141
}
11321142

1143+
/*
1144+
* If the kernel is relocated at boot time, kallsyms won't match. Compute the
1145+
* delta based on the relocation reference symbol.
1146+
*/
1147+
static int kallsyms__delta(struct map *map, const char *filename, u64 *delta)
1148+
{
1149+
struct kmap *kmap = map__kmap(map);
1150+
u64 addr;
1151+
1152+
if (!kmap->ref_reloc_sym || !kmap->ref_reloc_sym->name)
1153+
return 0;
1154+
1155+
addr = kallsyms__get_function_start(filename,
1156+
kmap->ref_reloc_sym->name);
1157+
if (!addr)
1158+
return -1;
1159+
1160+
*delta = addr - kmap->ref_reloc_sym->addr;
1161+
return 0;
1162+
}
1163+
11331164
int dso__load_kallsyms(struct dso *dso, const char *filename,
11341165
struct map *map, symbol_filter_t filter)
11351166
{
1167+
u64 delta = 0;
1168+
11361169
if (symbol__restricted_filename(filename, "/proc/kallsyms"))
11371170
return -1;
11381171

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

1175+
if (kallsyms__delta(map, filename, &delta))
1176+
return -1;
1177+
11421178
symbols__fixup_duplicate(&dso->symbols[map->type]);
11431179
symbols__fixup_end(&dso->symbols[map->type]);
11441180

@@ -1150,7 +1186,7 @@ int dso__load_kallsyms(struct dso *dso, const char *filename,
11501186
if (!dso__load_kcore(dso, map, filename))
11511187
return dso__split_kallsyms_for_kcore(dso, map, filter);
11521188
else
1153-
return dso__split_kallsyms(dso, map, filter);
1189+
return dso__split_kallsyms(dso, map, delta, filter);
11541190
}
11551191

11561192
static int dso__load_perf_map(struct dso *dso, struct map *map,

0 commit comments

Comments
 (0)