correlate_symbols will always try to match full name first. If there is no match, try match only demangled_name.
In very rare cases, it is possible to have multiple foo.llvm.<hash> in the same kernel. So this match is not guaranteed to be correct. Show a warning here so that the user can double check. Signed-off-by: Song Liu <[email protected]> --- tools/objtool/elf.c | 13 +++++++++++++ tools/objtool/include/objtool/elf.h | 2 ++ tools/objtool/klp-diff.c | 23 +++++++++++++++++++++++ 3 files changed, 38 insertions(+) diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c index efb13ec0a89d..d26ee877e613 100644 --- a/tools/objtool/elf.c +++ b/tools/objtool/elf.c @@ -323,6 +323,19 @@ struct symbol *find_global_symbol_by_name(const struct elf *elf, const char *nam return NULL; } +struct symbol *find_global_symbol_by_demangled_name(const struct elf *elf, + const char *demangled_name) +{ + struct symbol *sym; + + elf_hash_for_each_possible(symbol_name, sym, name_hash, str_hash(demangled_name)) { + if (!strcmp(sym->demangled_name, demangled_name) && !is_local_sym(sym)) + return sym; + } + + return NULL; +} + struct reloc *find_reloc_by_dest_range(const struct elf *elf, struct section *sec, unsigned long offset, unsigned int len) { diff --git a/tools/objtool/include/objtool/elf.h b/tools/objtool/include/objtool/elf.h index e12c516bd320..f757850b8ff1 100644 --- a/tools/objtool/include/objtool/elf.h +++ b/tools/objtool/include/objtool/elf.h @@ -186,6 +186,8 @@ struct symbol *find_func_by_offset(struct section *sec, unsigned long offset); struct symbol *find_symbol_by_offset(struct section *sec, unsigned long offset); struct symbol *find_symbol_by_name(const struct elf *elf, const char *name); struct symbol *find_global_symbol_by_name(const struct elf *elf, const char *name); +struct symbol *find_global_symbol_by_demangled_name(const struct elf *elf, + const char *demangled_name); struct symbol *find_symbol_containing(const struct section *sec, unsigned long offset); int find_symbol_hole_containing(const struct section *sec, unsigned long offset); struct reloc *find_reloc_by_dest(const struct elf *elf, struct section *sec, unsigned long offset); diff --git a/tools/objtool/klp-diff.c b/tools/objtool/klp-diff.c index 57606bc3390a..cd82f674862a 100644 --- a/tools/objtool/klp-diff.c +++ b/tools/objtool/klp-diff.c @@ -453,6 +453,29 @@ static int correlate_symbols(struct elfs *e) continue; sym2 = find_global_symbol_by_name(e->patched, sym1->name); + if (!sym2) { + /* + * No full name match, try match demangled_name. + * This would match foo.llvm.123 and foo.llvm.456. + * + * Note that, in very rare cases, it is possible + * to have multiple foo.llvm.<hash> in the same + * kernel, e.g., foo.llvm.123 in the original + * kernel, and both foo.llvm.456 and foo.llvm.789 + * in the patched kernel. The correlation is not + * guaranteed to be correct in such cases. + * + * Show a warning to remind the user to double + * check the correlation. + */ + + sym2 = find_global_symbol_by_demangled_name(e->patched, + sym1->demangled_name); + if (sym2) { + WARN("correlate %s (origial) to %s (patched)", + sym1->name, sym2->name); + } + } if (sym2 && !sym2->twin) { sym1->twin = sym2; -- 2.47.3
