[PATCH 1/1] objtool/klp: fix symbol ordering for data symbols
Joe Lawrence <[email protected]> Fri, 10 Jul 2026 11:30:42 -0400
| Newsgroups | org.kernel.vger.live-patching |
|---|---|
| Message-ID | <[email protected]> |
The find_sympos() function calculates a sympos (symbol position) used by livepatch to disambiguate duplicate symbol names. At runtime, kallsyms iterates symbols sorted by address, so sympos must reflect that order. For function symbols, there's already a workaround that counts .text.unlikely symbols before other .text symbols, matching the linker script's section ordering. Data symbols suffer the same problem: the linker script places sections in this order: .data..ro_after_init (lowest address) .data* sections .bss* sections (highest address) However, vmlinux.o's symbol table is ordered by object file link order (kernel/ before fs/, etc.), which can differ from the final address order. Extend the existing section ordering workaround to handle data symbols, counting .data..ro_after_init first, then other .data, then .bss. Reported-by: Ben Procknow <[email protected]> Fixes: dd590d4d57eb ("objtool/klp: Introduce klp diff subcommand for diffing object files") Signed-off-by: Joe Lawrence <[email protected]> --- tools/objtool/klp-diff.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/tools/objtool/klp-diff.c b/tools/objtool/klp-diff.c index c2c4e4968bc2..1c6f9f6d7565 100644 --- a/tools/objtool/klp-diff.c +++ b/tools/objtool/klp-diff.c @@ -509,6 +509,46 @@ static unsigned long find_sympos(struct elf *elf, struct symbol *sym) has_dup = true; } } + } else if (vmlinux && is_object_sym(sym)) { + /* + * HACK: Similarly, data symbol ordering can differ between + * vmlinux.o and vmlinux. The linker script places sections: + * .data..ro_after_init (lowest address) + * .data* sections + * .bss* sections (highest address) + * Count in that order. + */ + for_each_sym(elf, s) { + if (strstarts(s->sec->name, ".data..ro_after_init") && + !strcmp(s->name, sym->name)) { + nr_matches++; + if (s == sym) + sympos = nr_matches; + else + has_dup = true; + } + } + for_each_sym(elf, s) { + if (!strstarts(s->sec->name, ".data..ro_after_init") && + !strstarts(s->sec->name, ".bss") && + !strcmp(s->name, sym->name)) { + nr_matches++; + if (s == sym) + sympos = nr_matches; + else + has_dup = true; + } + } + for_each_sym(elf, s) { + if (strstarts(s->sec->name, ".bss") && + !strcmp(s->name, sym->name)) { + nr_matches++; + if (s == sym) + sympos = nr_matches; + else + has_dup = true; + } + } } else { for_each_sym(elf, s) { if (!strcmp(s->name, sym->name)) { -- 2.54.0