From c608fafd72c1f0a06f788ef0721cfcdf3704ca90 Mon Sep 17 00:00:00 2001 From: Song Liu Date: Mon, 24 Feb 2025 16:15:16 -0800 Subject: [PATCH] Fix sympos for gcc-14 When building a livepatch, we assume symbols from "readelf -s" is the same as the order observed in kallsyms. We calculate sympos of a symbol based on this order (readelf -s). However, with gcc-14, "readelf -s" may present the symbols in a different order. For example: With gcc 13: 32951: ffff8000802edf20 172 FUNC LOCAL DEFAULT 2 zero_user_segments.constprop.0 33497: ffff8000802fb798 236 FUNC LOCAL DEFAULT 2 zero_user_segments.constprop.0 47034: ffff80008044b250 172 FUNC LOCAL DEFAULT 2 zero_user_segments.constprop.0 51466: ffff8000804be260 236 FUNC LOCAL DEFAULT 2 zero_user_segments.constprop.0 51483: ffff8000804bf6a8 172 FUNC LOCAL DEFAULT 2 zero_user_segments.constprop.0 52287: ffff8000804cb098 172 FUNC LOCAL DEFAULT 2 zero_user_segments.constprop.0 54066: ffff800080518e38 172 FUNC LOCAL DEFAULT 2 zero_user_segments.constprop.0 58217: ffff800080575bb0 172 FUNC LOCAL DEFAULT 2 zero_user_segments.constprop.0 72912: ffff8000806c5dc0 172 FUNC LOCAL DEFAULT 2 zero_user_segments.constprop.0 73719: ffff8000806eccd0 172 FUNC LOCAL DEFAULT 2 zero_user_segments.constprop.0 With gcc 14: 9557: ffff800080312f28 236 FUNC LOCAL DEFAULT 2 zero_user_segments.constprop.0 16599: ffff8000806eb060 172 FUNC LOCAL DEFAULT 2 zero_user_segments.constprop.0 17305: ffff800080711d30 172 FUNC LOCAL DEFAULT 2 zero_user_segments.constprop.0 63960: ffff800080305540 172 FUNC LOCAL DEFAULT 2 zero_user_segments.constprop.0 74577: ffff800080466030 172 FUNC LOCAL DEFAULT 2 zero_user_segments.constprop.0 78568: ffff8000804dc3e0 172 FUNC LOCAL DEFAULT 2 zero_user_segments.constprop.0 79372: ffff8000804e81c0 172 FUNC LOCAL DEFAULT 2 zero_user_segments.constprop.0 81016: ffff800080537380 172 FUNC LOCAL DEFAULT 2 zero_user_segments.constprop.0 84685: ffff800080595428 172 FUNC LOCAL DEFAULT 2 zero_user_segments.constprop.0 Fix this by calculating sympos in another for_each_obj_symbol loop. Signed-off-by: Song Liu --- kpatch-build/lookup.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/kpatch-build/lookup.c b/kpatch-build/lookup.c index bd2b732de..565df688f 100644 --- a/kpatch-build/lookup.c +++ b/kpatch-build/lookup.c @@ -479,13 +479,10 @@ static bool lookup_local_symbol(struct lookup_table *table, struct object_symbol *sym; unsigned long sympos = 0; int i, in_file = 0; + bool found = false; memset(result, 0, sizeof(*result)); for_each_obj_symbol(i, sym, table) { - if (sym->bind == STB_LOCAL && !strcmp(sym->name, - lookup_sym->name)) - sympos++; - if (lookup_sym->lookup_table_file_sym == sym) { in_file = 1; continue; @@ -499,20 +496,35 @@ static bool lookup_local_symbol(struct lookup_table *table, if (sym->bind == STB_LOCAL && !strcmp(sym->name, lookup_sym->name)) { - if (result->objname) + if (found) ERROR("duplicate local symbol found for %s", lookup_sym->name); result->objname = table->objname; result->addr = sym->addr; result->size = sym->size; - result->sympos = sympos; result->global = false; result->exported = false; + found = true; } } + if (!found) + return false; - return !!result->objname; + /* + * The kernel calculates sympos based on the order of addresses. + * "readelf -s" does not guarantee the ordering of symbols. + * Therefore, it is safer to iterate the symbol table again to + * calcuate the actual sympos. + */ + for_each_obj_symbol(i, sym, table) { + if (sym->bind == STB_LOCAL && + !strcmp(sym->name, lookup_sym->name) && + sym->addr <= result->addr) + sympos++; + } + result->sympos = sympos; + return true; } static bool lookup_exported_symbol(struct lookup_table *table, char *name,