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 <song@kernel.org>
This commit is contained in:
Song Liu 2025-02-24 16:15:16 -08:00
parent 305cdc994a
commit c608fafd72

View File

@ -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,