Skip to content

Commit 973f4a6

Browse files
chucklevergregkh
authored andcommitted
perf tools: Fix module symbol resolution for non-zero .text sh_addr
[ Upstream commit 9a82bfd ] When perf resolves symbols from kernel module ELF files (ET_REL), it converts symbol addresses to file offsets so that sample IPs can be matched to the correct symbol. The conversion adjusts each symbol's st_value: sym->st_value -= shdr->sh_addr - shdr->sh_offset; For vmlinux (ET_EXEC), st_value is a virtual address and sh_addr is the section's virtual base, so subtracting sh_addr and adding sh_offset correctly yields a file offset. For kernel modules (ET_REL), st_value is a section-relative offset. The module loader ignores sh_addr entirely and places symbols at module_base + st_value. Converting to file offset requires only adding sh_offset; subtracting sh_addr introduces an error equal to sh_addr bytes. When .text has sh_addr == 0 -- the historical norm for simple modules -- both formulas produce the same result and the bug is latent. As modules gain more metadata sections before .text (.note, .static_call.text, etc.), the linker assigns .text a non-zero sh_addr, exposing the defect. For example, nfsd.ko on this kernel has sh_addr=0xa80, kvm-intel.ko has sh_addr=0x1e90. The effect is that all .text symbols in affected modules shift by sh_addr bytes relative to sample IPs, causing perf report to attribute samples to incorrect, nearby symbols. This was observed as 13% of LLC-load-miss samples misattributed to nfsd_file_get_dio_attrs when the actual hot function was nfsd_cache_lookup, approximately 0xa80 bytes away in the symbol table. Use the existing dso__rel() flag (already set for ET_REL modules) to select the correct adjustment: add sh_offset for ET_REL, subtract (sh_addr - sh_offset) for ET_EXEC/ET_DYN. Fixes: 0131c4e ("perf tools: Make it possible to read object code from kernel modules") Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Reviewed-by: Ian Rogers <irogers@google.com> Tested-by: Thomas Richter <tmricht@linux.ibm.com> Signed-off-by: Namhyung Kim <namhyung@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 4b4f05f commit 973f4a6

1 file changed

Lines changed: 6 additions & 2 deletions

File tree

tools/perf/util/symbol-elf.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1429,8 +1429,12 @@ static int dso__process_kernel_symbol(struct dso *dso, struct map *map,
14291429
char dso_name[PATH_MAX];
14301430

14311431
/* Adjust symbol to map to file offset */
1432-
if (adjust_kernel_syms)
1433-
sym->st_value -= shdr->sh_addr - shdr->sh_offset;
1432+
if (adjust_kernel_syms) {
1433+
if (dso__rel(dso))
1434+
sym->st_value += shdr->sh_offset;
1435+
else
1436+
sym->st_value -= shdr->sh_addr - shdr->sh_offset;
1437+
}
14341438

14351439
if (strcmp(section_name, (dso__short_name(curr_dso) + dso__short_name_len(dso))) == 0)
14361440
return 0;

0 commit comments

Comments
 (0)