diff options
| author | Song Liu <song@kernel.org> | 2026-03-05 15:15:30 -0800 |
|---|---|---|
| committer | Josh Poimboeuf <jpoimboe@kernel.org> | 2026-03-06 08:08:33 -0800 |
| commit | cdea5cadb0ca403b1929f8d29929c0eda0f715d6 (patch) | |
| tree | 0395cd61a0fa60afe7b5941032a1fa7319695ab2 /tools/objtool/klp-diff.c | |
| parent | 020b71dcafeeececb78d9ee9e5a2e68e8e05e922 (diff) | |
| download | linux-next-cdea5cadb0ca403b1929f8d29929c0eda0f715d6.tar.gz linux-next-cdea5cadb0ca403b1929f8d29929c0eda0f715d6.zip | |
objtool/klp: Match symbols based on demangled_name for global variables
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. Whenever there is ambiguity like this, fail the klp diff.
Signed-off-by: Song Liu <song@kernel.org>
Link: https://patch.msgid.link/20260305231531.3847295-7-song@kernel.org
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
Diffstat (limited to 'tools/objtool/klp-diff.c')
| -rw-r--r-- | tools/objtool/klp-diff.c | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/tools/objtool/klp-diff.c b/tools/objtool/klp-diff.c index 639bdd3ad5eb..46afbf4a03b9 100644 --- a/tools/objtool/klp-diff.c +++ b/tools/objtool/klp-diff.c @@ -355,6 +355,46 @@ static bool dont_correlate(struct symbol *sym) strstarts(sym->name, "__initcall__"); } +struct process_demangled_name_data { + struct symbol *ret; + int count; +}; + +static void process_demangled_name(struct symbol *sym, void *d) +{ + struct process_demangled_name_data *data = d; + + if (sym->twin) + return; + + data->count++; + data->ret = sym; +} + +/* + * When there is no full name match, try match demangled_name. This would + * match original foo.llvm.123 to patched foo.llvm.456. + * + * Note that, in very rare cases, it is possible to have multiple + * foo.llvm.<hash> in the same kernel. When this happens, report error and + * fail the diff. + */ +static int find_global_symbol_by_demangled_name(struct elf *elf, struct symbol *sym, + struct symbol **out_sym) +{ + struct process_demangled_name_data data = {}; + + iterate_global_symbol_by_demangled_name(elf, sym->demangled_name, + process_demangled_name, + &data); + if (data.count > 1) { + ERROR("Multiple (%d) correlation candidates for %s", data.count, sym->name); + return -1; + } + *out_sym = data.ret; + return 0; +} + /* * For each symbol in the original kernel, find its corresponding "twin" in the * patched kernel. @@ -453,6 +493,23 @@ static int correlate_symbols(struct elfs *e) continue; sym2 = find_global_symbol_by_name(e->patched, sym1->name); + if (sym2 && !sym2->twin) { + sym1->twin = sym2; + sym2->twin = sym1; + } + } + + /* + * Correlate globals with demangled_name. + * A separate loop is needed because we want to finish all the + * full name correlations first. + */ + for_each_sym(e->orig, sym1) { + if (sym1->bind == STB_LOCAL || sym1->twin) + continue; + + if (find_global_symbol_by_demangled_name(e->patched, sym1, &sym2)) + return -1; if (sym2 && !sym2->twin) { sym1->twin = sym2; |
