| Issue |
162610
|
| Summary |
LLD does not rewrite relocations during target-specific relaxation
|
| Labels |
lld
|
| Assignees |
|
| Reporter |
dominik-steenken
|
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):
```asm
.hidden foo
.comm foo,8,8
.text
.globl bar
.type bar, @function
bar:
movq foo@GOTPCREL(%rip), %rax
```
When 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`.
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs