Thread (3 messages) 3 messages, 2 authors, 1d ago
WARM1d

[PATCH 1/1] objtool/klp: fix symbol ordering for data symbols

From: Joe Lawrence <joe.lawrence@redhat.com>
Date: 2026-07-10 15:30:54
Subsystem: objtool, the rest · Maintainers: Josh Poimboeuf, Peter Zijlstra, Linus Torvalds

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 <redacted>
Fixes: dd590d4d57eb ("objtool/klp: Introduce klp diff subcommand for diffing object files")
Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
---
 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
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help