- Notifications
You must be signed in to change notification settings - Fork 15.1k
Description
When performing target-specific relaxation, lld might change instructions in such a way that the original relocations associated with them are no longer correct. If those relocations are resolved during the linking and not emitted, this is not a problem. When combined with --emit-relocs though, the original, no longer applicable relocations are emitted, rather than the relocation that might apply to the transformed code. This is true at least for X86 and SystemZ targets. The ld linker does apply the relaxation transformation to the relocation as well, which should be the correct approach, I think, since --emit-relocs is meant to allow postprocessing tools to use the relocations for further optimizations / analysis, which might fail if the relocations are incorrect.
Example Code (X86):
.hidden foo .comm foo,8,8 .text .globl bar .type bar, @function bar: movq foo@GOTPCREL(%rip), %raxWhen assembled and linked with --emit-relocs, once with --no-relax and once without --no-relax, this demonstrates that the relaxation applies to the instruction only (mov -> lea), and not the relocation:
$ as --64 -o relcheck_x86-64.o relcheck_x86-64.s $ ld.lld -melf_x86_64 -shared --emit-relocs -o relcheck_x86-64_lld_relax relcheck_x86-64.o $ objdump -dr relcheck_x86-64_lld_relax | grep -E '^\s+[0-9a-f]+:' 126d: 48 8d 05 8c 20 00 00 lea 0x208c(%rip),%rax # 3300 <foo> 1270: R_X86_64_REX_GOTPCRELX foo-0x4 $ ld.lld -melf_x86_64 -shared --emit-relocs --no-relax -o relcheck_x86-64_lld_no-relax relcheck_x86-64.o $ objdump -dr relcheck_x86-64_lld_no-relax | grep -E '^\s+[0-9a-f]+:' 1288: 48 8b 05 b1 10 00 00 mov 0x10b1(%rip),%rax # 2340 <_DYNAMIC+0xb0> 128b: R_X86_64_REX_GOTPCRELX foo-0x4 When this same process is performed with ld, the relocation is transformed as well:
$ as --64 -o relcheck_x86-64.o relcheck_x86-64.s $ ld -melf_x86_64 -shared --emit-relocs -o relcheck_x86-64_relax relcheck_x86-64.o $ ld -melf_x86_64 -shared --emit-relocs --no-relax -o relcheck_x86-64_no-relax relcheck_x86-64.o $ objdump -dr relcheck_x86-64_relax | grep -E '^\s+[0-9a-f]+:' 1c8: 48 8d 05 31 2e 00 00 lea 0x2e31(%rip),%rax # 3000 <foo> 1cb: R_X86_64_PC32 foo-0x4 $ objdump -dr relcheck_x86-64_no-relax | grep -E '^\s+[0-9a-f]+:' 1c8: 48 8b 05 11 2e 00 00 mov 0x2e11(%rip),%rax # 2fe0 <.got> 1cb: R_X86_64_REX_GOTPCRELX foo-0x4 This same behavior seems to be present at least on s390x as well. This was tested with ld version 2.44-6.fc42, and ld.lld version 20.1.8.