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

Reply via email to