While doing Linux kernel builds linked with lld, I've tracked down a difference that breaks relocation of the kernel image (e.g. under KASLR[1]). Some relocations are changed to ABS (weirdly, all are in .rodata section). Note the difference below in the resulting linked output. .L__const._start.instance becomes *ABS* only under lld: $ cat minimal.c struct minimal { void *pointer; int value; }; void _start(void) { struct minimal instance = { .value = 1, }; } $ llvm-build/x86/bin/clang -c minimal.c $ /usr/bin/ld.bfd --emit-relocs minimal.o -o minimal.bfd $ llvm-build/x86/bin/ld.lld --emit-relocs minimal.o -o minimal.lld $ objdump -Sdr minimal.bfd ... 00000000004000b0 <_start>: 4000b0: 55 push %rbp 4000b1: 48 89 e5 mov %rsp,%rbp 4000b4: 48 8b 04 25 d0 00 40 mov 0x4000d0,%rax 4000bb: 00 4000b8: R_X86_64_32S .rodata 4000bc: 48 89 45 f0 mov %rax,-0x10(%rbp) 4000c0: 48 8b 04 25 d8 00 40 mov 0x4000d8,%rax 4000c7: 00 4000c4: R_X86_64_32S .L__const._start.instance+0x8 4000c8: 48 89 45 f8 mov %rax,-0x8(%rbp) 4000cc: 5d pop %rbp 4000cd: c3 retq $ objdump -Sdr minimal.lld ... 0000000000201000 <_start>: 201000: 55 push %rbp 201001: 48 89 e5 mov %rsp,%rbp 201004: 48 8b 04 25 20 01 20 mov 0x200120,%rax 20100b: 00 201008: R_X86_64_32S .rodata 20100c: 48 89 45 f0 mov %rax,-0x10(%rbp) 201010: 48 8b 04 25 28 01 20 mov 0x200128,%rax 201017: 00 201014: R_X86_64_32S *ABS*+0x8 201018: 48 89 45 f8 mov %rax,-0x8(%rbp) 20101c: 5d pop %rbp 20101d: c3 retq I'm not sure where to start looking for solving this... Thanks! [1] https://github.com/ClangBuiltLinux/linux/issues/404
I just read through every lld runtime flag and just found "--discard-none". It seems the default is "--discard-local"? So perhaps this is NOT a bug?
It seems shouldKeepInSymtab has no knowledge of "DiscardPolicy::Default"? Or is "Default" supposed to mean the logic here with SHF_MERGE vs .L symbols? static bool shouldKeepInSymtab(SectionBase *Sec, StringRef SymName, const Symbol &B) { if (B.isSection()) return false; if (Config->Discard == DiscardPolicy::None) return true; // In ELF assembly .L symbols are normally discarded by the assembler. // If the assembler fails to do so, the linker discards them if // * --discard-locals is used. // * The symbol is in a SHF_MERGE section, which is normally the reason for // the assembler keeping the .L symbol. if (!SymName.startswith(".L") && !SymName.empty()) return true; if (Config->Discard == DiscardPolicy::Locals) return false; return !Sec || !(Sec->Flags & SHF_MERGE); }
Proposed Patch: https://reviews.llvm.org/D60306
That fix has landed.