From c19c854b307424c745dd6de73eea8db099c79408 Mon Sep 17 00:00:00 2001 From: Wentong Tian Date: Thu, 22 Jan 2026 22:44:04 +0800 Subject: objtool: Use section/symbol type helpers Commit 25eac74b6bdb ("objtool: Add section/symbol type helpers") introduced several helper macros to improve code readability. Update the remaining open-coded checks in check.c, disas.c, elf.c, and klp-diff.c to use these new helpers. Signed-off-by: Wentong Tian Link: https://patch.msgid.link/20260122144404.40602-1-tianwentong2000@gmail.com Signed-off-by: Josh Poimboeuf --- tools/objtool/klp-diff.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'tools/objtool/klp-diff.c') diff --git a/tools/objtool/klp-diff.c b/tools/objtool/klp-diff.c index 9f1f4011eb9c..885775f6072e 100644 --- a/tools/objtool/klp-diff.c +++ b/tools/objtool/klp-diff.c @@ -271,7 +271,7 @@ static bool is_uncorrelated_static_local(struct symbol *sym) */ static bool is_clang_tmp_label(struct symbol *sym) { - return sym->type == STT_NOTYPE && + return is_notype_sym(sym) && is_text_sec(sym->sec) && strstarts(sym->name, ".Ltmp") && isdigit(sym->name[5]); @@ -480,7 +480,7 @@ static unsigned long find_sympos(struct elf *elf, struct symbol *sym) if (sym->bind != STB_LOCAL) return 0; - if (vmlinux && sym->type == STT_FUNC) { + if (vmlinux && is_func_sym(sym)) { /* * HACK: Unfortunately, symbol ordering can differ between * vmlinux.o and vmlinux due to the linker script emitting @@ -1046,8 +1046,8 @@ static int clone_reloc_klp(struct elfs *e, struct reloc *patched_reloc, sec->name, offset, patched_sym->name, \ addend >= 0 ? "+" : "-", labs(addend), \ sym_type(patched_sym), \ - patched_sym->type == STT_SECTION ? "" : " ", \ - patched_sym->type == STT_SECTION ? "" : sym_bind(patched_sym), \ + is_sec_sym(patched_sym) ? "" : " ", \ + is_sec_sym(patched_sym) ? "" : sym_bind(patched_sym), \ is_undef_sym(patched_sym) ? " UNDEF" : "", \ export ? " EXPORTED" : "", \ klp ? " KLP" : "") -- cgit v1.2.3 From a1cbaff2ea23645f0a94fdfa721aef202aebdf86 Mon Sep 17 00:00:00 2001 From: Song Liu Date: Thu, 5 Mar 2026 15:15:25 -0800 Subject: objtool/klp: Remove redundant strcmp() in correlate_symbols() find_global_symbol_by_name() already compares names of the two symbols, so there is no need to compare them again. Signed-off-by: Song Liu Link: https://patch.msgid.link/20260305231531.3847295-2-song@kernel.org Signed-off-by: Josh Poimboeuf --- tools/objtool/klp-diff.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools/objtool/klp-diff.c') diff --git a/tools/objtool/klp-diff.c b/tools/objtool/klp-diff.c index 885775f6072e..639bdd3ad5eb 100644 --- a/tools/objtool/klp-diff.c +++ b/tools/objtool/klp-diff.c @@ -454,7 +454,7 @@ static int correlate_symbols(struct elfs *e) sym2 = find_global_symbol_by_name(e->patched, sym1->name); - if (sym2 && !sym2->twin && !strcmp(sym1->name, sym2->name)) { + if (sym2 && !sym2->twin) { sym1->twin = sym2; sym2->twin = sym1; } -- cgit v1.2.3 From cdea5cadb0ca403b1929f8d29929c0eda0f715d6 Mon Sep 17 00:00:00 2001 From: Song Liu Date: Thu, 5 Mar 2026 15:15:30 -0800 Subject: 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. in the same kernel. Whenever there is ambiguity like this, fail the klp diff. Signed-off-by: Song Liu Link: https://patch.msgid.link/20260305231531.3847295-7-song@kernel.org Signed-off-by: Josh Poimboeuf --- tools/objtool/elf.c | 13 +++++++++ tools/objtool/include/objtool/elf.h | 3 ++ tools/objtool/klp-diff.c | 57 +++++++++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+) (limited to 'tools/objtool/klp-diff.c') diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c index feaec45a14a0..8122c5f5141c 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; } +void iterate_global_symbol_by_demangled_name(const struct elf *elf, + const char *demangled_name, + void (*process)(struct symbol *sym, void *data), + void *data) +{ + 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)) + process(sym, data); + } +} + 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..25573e5af76e 100644 --- a/tools/objtool/include/objtool/elf.h +++ b/tools/objtool/include/objtool/elf.h @@ -186,6 +186,9 @@ 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); +void iterate_global_symbol_by_demangled_name(const struct elf *elf, const char *demangled_name, + void (*process)(struct symbol *sym, void *data), + void *data); 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 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. 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; -- cgit v1.2.3 From 4b57e97be22fb8332d05ee1d0fe3c0dd43c828bf Mon Sep 17 00:00:00 2001 From: Song Liu Date: Thu, 5 Mar 2026 15:15:31 -0800 Subject: objtool/klp: Correlate locals to globals Allow correlating original locals to patched globals, and vice versa. This is needed when: 1. User adds/removes "static" for a function. 2. CONFIG_LTO_CLANG_THIN promotes local functions and objects to global and add .llvm. suffix. Signed-off-by: Song Liu Link: https://patch.msgid.link/20260305231531.3847295-8-song@kernel.org Signed-off-by: Josh Poimboeuf --- tools/objtool/klp-diff.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'tools/objtool/klp-diff.c') diff --git a/tools/objtool/klp-diff.c b/tools/objtool/klp-diff.c index 46afbf4a03b9..85281b3b021f 100644 --- a/tools/objtool/klp-diff.c +++ b/tools/objtool/klp-diff.c @@ -517,6 +517,36 @@ static int correlate_symbols(struct elfs *e) } } + /* Correlate original locals with patched globals */ + for_each_sym(e->orig, sym1) { + if (sym1->twin || dont_correlate(sym1) || !is_local_sym(sym1)) + continue; + + sym2 = find_global_symbol_by_name(e->patched, sym1->name); + if (!sym2 && find_global_symbol_by_demangled_name(e->patched, sym1, &sym2)) + return -1; + + if (sym2 && !sym2->twin) { + sym1->twin = sym2; + sym2->twin = sym1; + } + } + + /* Correlate original globals with patched locals */ + for_each_sym(e->patched, sym2) { + if (sym2->twin || dont_correlate(sym2) || !is_local_sym(sym2)) + continue; + + sym1 = find_global_symbol_by_name(e->orig, sym2->name); + if (!sym1 && find_global_symbol_by_demangled_name(e->orig, sym2, &sym1)) + return -1; + + if (sym1 && !sym1->twin) { + sym2->twin = sym1; + sym1->twin = sym2; + } + } + for_each_sym(e->orig, sym1) { if (sym1->twin || dont_correlate(sym1)) continue; -- cgit v1.2.3