diff options
| author | Josh Poimboeuf <jpoimboe@kernel.org> | 2026-08-07 14:37:47 -0700 |
|---|---|---|
| committer | Josh Poimboeuf <jpoimboe@kernel.org> | 2026-08-11 15:04:57 -0700 |
| commit | 1ea786097cd79522b76cbd41beeb8f84ef3a76f4 (patch) | |
| tree | 4cc70991a9deb9a94ce7431352ff562442d79d9a /tools/objtool | |
| parent | 3a83d9cd3d0e66c0ef99ce84f972ed26f50c990f (diff) | |
objtool/klp: Fix size of empty special section entries
create_fake_symbols() sizes each ANNOTATE_DATA_SPECIAL entry from the
offset of the next annotation, falling back to the end of the section
for the last entry. But the last entry is detected by a zero size,
which also happens for an *empty* entry: ALTERNATIVE(oldinstr, "", ft)
still annotates its zero-length replacement, at the same offset as the
next entry's annotation.
So every empty replacement gets a fake symbol spanning the entire rest
of .altinstr_replacement. That's harmless today only because
find_symbol_containing() picks the smaller of two overlapping symbols.
Track whether a next annotation was found rather than inferring it from
the size. A zero-length fake symbol is fine: find_symbol_containing()
skips those, so the properly sized symbol at the same offset still wins.
Fixes: dd590d4d57eb ("objtool/klp: Introduce klp diff subcommand for diffing object files")
Acked-by: Song Liu <song@kernel.org>
Acked-by: Joe Lawrence <joe.lawrence@redhat.com>
Link: https://patch.msgid.link/913e691c5009397df832c7c9a18cd5cf71b42737.1786138493.git.jpoimboe@kernel.org
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
Diffstat (limited to 'tools/objtool')
| -rw-r--r-- | tools/objtool/klp-diff.c | 13 |
1 files changed, 11 insertions, 2 deletions
diff --git a/tools/objtool/klp-diff.c b/tools/objtool/klp-diff.c index c5284d275207..b4220e12a8e2 100644 --- a/tools/objtool/klp-diff.c +++ b/tools/objtool/klp-diff.c @@ -1628,13 +1628,17 @@ static int create_fake_symbols(struct elf *elf) for_each_reloc(sec->rsec, reloc) { unsigned long offset, size; struct reloc *next_reloc; + bool last = true; if (annotype(elf, sec, reloc) != ANNOTYPE_DATA_SPECIAL) continue; offset = reloc_addend(reloc); - size = 0; + /* + * Find the start of the next entry so the fake symbol size can + * be calculated. + */ next_reloc = reloc; for_each_reloc_continue(sec->rsec, next_reloc) { if (annotype(elf, sec, next_reloc) != ANNOTYPE_DATA_SPECIAL || @@ -1642,10 +1646,15 @@ static int create_fake_symbols(struct elf *elf) continue; size = reloc_addend(next_reloc) - offset; + last = false; break; } - if (!size) + /* + * If no next entry found, this is the last entry, so its size + * is from the current offset to the end of the section. + */ + if (last) size = sec_size(reloc->sym->sec) - offset; if (create_fake_symbol(elf, reloc->sym->sec, offset, size)) |
