On Tue, Jun 30, 2026 at 02:40:42PM -0400, Joe Lawrence wrote:
> The root cause is that create_fake_symbols() skips the entire special
> section if any symbol exists at offset 0. But Clang places a .Ltmp*
> label at the start of .kcfi_traps, so no per-entry fake symbols are
> created and clone_special_sections() extracts nothing.
>
> static int create_fake_symbols(struct elf *elf)
> {
> ...
> /*
> * 2) Make symbols for sh_entsize, and simple arrays of pointers:
> */
> entsize:
> for_each_sec(elf, sec) {
> unsigned int entry_size;
> unsigned long offset;
>
> if (!is_special_section(sec) || find_symbol_by_offset(sec, 0))
> continue;
>
> $ llvm-readelf --wide --symbols klp-tmp/3-checksum-patched/vmlinux.o | \
> awk '$7 == 74993'
> 93266: 0000000000000000 0 NOTYPE LOCAL DEFAULT 74993 .Ltmp78
> 93544: 0000000000000000 0 SECTION LOCAL DEFAULT 74993 .kcfi_traps
>
>
> Possible fix: ignore .L* assembler-local labels at section offset 0
> using the existing is_local_label() helper.
>
> -->8-- -->8-- -->8-- -->8-- -->8-- -->8-- -->8-- -->8-- -->8-- -->8--
>
> diff --git a/tools/objtool/klp-diff.c b/tools/objtool/klp-diff.c
> index b9624bd9439b..4ba400926647 100644
> --- a/tools/objtool/klp-diff.c
> +++ b/tools/objtool/klp-diff.c
> @@ -1860,8 +1860,17 @@ static int create_fake_symbols(struct elf *elf)
> for_each_sec(elf, sec) {
> unsigned int entry_size;
> unsigned long offset;
> + struct symbol *sym_at_0;
>
> - if (!is_special_section(sec) || find_symbol_by_offset(sec, 0))
> + if (!is_special_section(sec))
> + continue;
> +
> + /*
> + * Clang may place assembler-local .L* labels at offset 0;
> + * they must not prevent per-entry fake symbol creation.
> + */
> + sym_at_0 = find_symbol_by_offset(sec, 0);
> + if (sym_at_0 && !is_local_label(sym_at_0))
> continue;
Thanks, I'll fix this with my other series of fixes in the next version.
find_symbol_by_offset() might not work because there can be multiple
symbols at offset 0. Instead we can just traverse the symbols in the
section, looking for sym->fake.
--
Josh