Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

objtool: Check local label in read_unwind_hints()

When update the latest upstream gcc and binutils, it generates some
objtool warnings on LoongArch, like this:

arch/loongarch/kernel/entry.o: warning: objtool: ret_from_fork+0x0: unreachable instruction

We can see that the reloc sym name is local label instead of section
in relocation section '.rela.discard.unwind_hints', in this case, the
reloc sym type is STT_NOTYPE instead of STT_SECTION. Let us check it
to not return -1, then use reloc->sym->offset instead of reloc addend
which is 0 to find the corresponding instruction.

Here are some detailed info:
[fedora@linux 6.8.test]$ gcc --version
gcc (GCC) 14.0.1 20240129 (experimental)
[fedora@linux 6.8.test]$ as --version
GNU assembler (GNU Binutils) 2.42.50.20240129
[fedora@linux 6.8.test]$ readelf -r arch/loongarch/kernel/entry.o | grep -A 3 "rela.discard.unwind_hints"
Relocation section '.rela.discard.unwind_hints' at offset 0x3a8 contains 7 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000000000 000a00000063 R_LARCH_32_PCREL 0000000000000000 .Lhere_1 + 0
00000000000c 000b00000063 R_LARCH_32_PCREL 00000000000000a8 .Lhere_50 + 0

Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>

authored by

Tiezhu Yang and committed by
Huacai Chen
e91c5e4c d5ab2bc3

+11 -1
+11 -1
tools/objtool/check.c
··· 2227 2227 struct unwind_hint *hint; 2228 2228 struct instruction *insn; 2229 2229 struct reloc *reloc; 2230 + unsigned long offset; 2230 2231 int i; 2231 2232 2232 2233 sec = find_section_by_name(file->elf, ".discard.unwind_hints"); ··· 2255 2254 return -1; 2256 2255 } 2257 2256 2258 - insn = find_insn(file, reloc->sym->sec, reloc_addend(reloc)); 2257 + if (reloc->sym->type == STT_SECTION) { 2258 + offset = reloc_addend(reloc); 2259 + } else if (reloc->sym->local_label) { 2260 + offset = reloc->sym->offset; 2261 + } else { 2262 + WARN("unexpected relocation symbol type in %s", sec->rsec->name); 2263 + return -1; 2264 + } 2265 + 2266 + insn = find_insn(file, reloc->sym->sec, offset); 2259 2267 if (!insn) { 2260 2268 WARN("can't find insn for unwind_hints[%d]", i); 2261 2269 return -1;