From: George Guo <[email protected]> create_fake_symbols() takes each annotated entry's offset from the annotate relocation's addend alone. That works only when the relocation points at the special section's section symbol. GCC/GAS on LoongArch points it at the entry's local label instead, with a zero addend: every entry then gets offset 0, the "distance to the next annotation" size becomes 0, and the fallback sets the size to the rest of the section.
So every fake symbol starts at offset 0 and covers the whole special section. If any entry in the section belongs to a patched function, should_keep_special_sym() keeps such a symbol, and the output module gets the entire __bug_table (thousands of entries and klp relocations) instead of just the patched function's entries. Compute the offset as sym->offset + addend, which handles both the section symbol form (sym->offset == 0) and the local label form (addend == 0). Reported-by: Joe Lawrence <[email protected]> Signed-off-by: George Guo <[email protected]> --- tools/objtool/klp-diff.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tools/objtool/klp-diff.c b/tools/objtool/klp-diff.c index 05fd70e24326..0fa3ce324346 100644 --- a/tools/objtool/klp-diff.c +++ b/tools/objtool/klp-diff.c @@ -1863,7 +1863,12 @@ static int create_fake_symbols(struct elf *elf) if (annotype(elf, sec, reloc) != ANNOTYPE_DATA_SPECIAL) continue; - offset = reloc_addend(reloc); + /* + * The annotated location may be referenced via the section + * symbol plus addend, or via a local label (GCC/GAS on + * LoongArch): sym->offset + addend covers both forms. + */ + offset = reloc->sym->offset + reloc_addend(reloc); size = 0; next_reloc = reloc; @@ -1875,7 +1880,7 @@ static int create_fake_symbols(struct elf *elf) next_reloc->sym->sec != reloc->sym->sec) continue; - size = reloc_addend(next_reloc) - offset; + size = (next_reloc->sym->offset + reloc_addend(next_reloc)) - offset; break; } -- 2.25.1

