mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-30 11:03:07 -04:00
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: dd590d4d57 ("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>
This commit is contained in:
@@ -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))
|
||||
|
||||
Reference in New Issue
Block a user