<div dir="ltr">This seems like a bug in lld.<div><br></div><div>Here is the cause of the bug.</div><div><br></div><div>Symbol whose name begins with ".L" are local symbols. Usually such symbols are discarded by the assembler because relocations relative to local symbols can be replaced by ones that are relative to beginning of sections. But there's one case in which the assembler cannot do that. Local symbols in mergeable sections cannot be replaced, because mergeable sections are split by the linker and reassembled, so their offsets from beginning of sections are not computable at assemble-time.</div><div><br></div><div>The linker recognizes remaining ".L" symbols and discards them. lld implements that behavior, but it discards the symbols even when --emit-relocs is given. This is the cause of the bug.</div><div><br></div><div>We should keep ".L" symbols when --emit-relocs is given. Looks like that's what GNU linkers do as well.</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, Apr 5, 2019 at 5:21 AM Kees Cook via llvm-dev <<a href="mailto:llvm-dev@lists.llvm.org">llvm-dev@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hi,<br>
<br>
While doing Linux kernel builds linked with lld, I've tracked down a<br>
difference that breaks relocation of the kernel image (e.g. under<br>
KASLR[1]). Some relocations are changed to ABS (weirdly, all are in<br>
.rodata section). Note the difference below in the resulting linked<br>
output.<br>
.L__const._start.instance becomes *ABS* only under lld:<br>
<br>
$ cat minimal.c<br>
struct minimal {<br>
void *pointer;<br>
int value;<br>
};<br>
<br>
void _start(void)<br>
{<br>
struct minimal instance = {<br>
.value = 1,<br>
};<br>
}<br>
$ llvm-build/x86/bin/clang -c minimal.c<br>
$ /usr/bin/ld.bfd --emit-relocs minimal.o -o minimal.bfd<br>
$ llvm-build/x86/bin/ld.lld --emit-relocs minimal.o -o minimal.lld<br>
$ objdump -Sdr minimal.bfd<br>
...<br>
00000000004000b0 <_start>:<br>
4000b0: 55 push %rbp<br>
4000b1: 48 89 e5 mov %rsp,%rbp<br>
4000b4: 48 8b 04 25 d0 00 40 mov 0x4000d0,%rax<br>
4000bb: 00<br>
4000b8: R_X86_64_32S .rodata<br>
4000bc: 48 89 45 f0 mov %rax,-0x10(%rbp)<br>
4000c0: 48 8b 04 25 d8 00 40 mov 0x4000d8,%rax<br>
4000c7: 00<br>
4000c4: R_X86_64_32S .L__const._start.instance+0x8<br>
4000c8: 48 89 45 f8 mov %rax,-0x8(%rbp)<br>
4000cc: 5d pop %rbp<br>
4000cd: c3 retq<br>
<br>
$ objdump -Sdr minimal.lld<br>
...<br>
0000000000201000 <_start>:<br>
201000: 55 push %rbp<br>
201001: 48 89 e5 mov %rsp,%rbp<br>
201004: 48 8b 04 25 20 01 20 mov 0x200120,%rax<br>
20100b: 00<br>
201008: R_X86_64_32S .rodata<br>
20100c: 48 89 45 f0 mov %rax,-0x10(%rbp)<br>
201010: 48 8b 04 25 28 01 20 mov 0x200128,%rax<br>
201017: 00<br>
201014: R_X86_64_32S *ABS*+0x8<br>
201018: 48 89 45 f8 mov %rax,-0x8(%rbp)<br>
20101c: 5d pop %rbp<br>
20101d: c3 retq<br>
<br>
I'm not sure where to start looking for solving this...<br>
<br>
Thanks!<br>
<br>
-Kees<br>
<br>
[1] <a href="https://github.com/ClangBuiltLinux/linux/issues/404" rel="noreferrer" target="_blank">https://github.com/ClangBuiltLinux/linux/issues/404</a><br>
<br>
-- <br>
Kees Cook<br>
_______________________________________________<br>
LLVM Developers mailing list<br>
<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev</a><br>
</blockquote></div>