Skip to content

Commit bbc5d9f

Browse files
authored
[llvm][MC][ARM][Assembly] Emit relocations for LDRs (#72873)
It's possible (though inadvisable) to use LDR and refer to labels in different sections. In the Arm state, the assembler resolves the LDR instruction without emitting a relocation. That's incorrect because the assembler cannot make any assumptions about the relative position of the sections and the compiler output is therefore wrong. This patch ensures relocations are generated for all `LDR <Rt...>, label` instructions in the Arm state (little endian). This is not necessary when the label is in the same section but the relocation is now generated regardless. Instructions that now generate relocations have been removed from the pcrel-global.s test. Fortunately, LLD already implements the generated relocations and can fix LDR instructions when the symbol is in a different section, or report an error if the offset is too large for the immediate field in the particular LDR's encoding. The patch to address this problem for big endian targets will follow, as well as a fix for ADR that exhibits a similar behavior.
1 parent 385304e commit bbc5d9f

File tree

7 files changed

+141
-10
lines changed

7 files changed

+141
-10
lines changed

llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,11 @@ const MCFixupKindInfo &ARMAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
7474
// ARMFixupKinds.h.
7575
//
7676
// Name Offset (bits) Size (bits) Flags
77-
{"fixup_arm_ldst_pcrel_12", 0, 32, IsPCRelConstant},
77+
{"fixup_arm_ldst_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
7878
{"fixup_t2_ldst_pcrel_12", 0, 32,
79-
IsPCRelConstant | MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
80-
{"fixup_arm_pcrel_10_unscaled", 0, 32, IsPCRelConstant},
79+
MCFixupKindInfo::FKF_IsPCRel |
80+
MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
81+
{"fixup_arm_pcrel_10_unscaled", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
8182
{"fixup_arm_pcrel_10", 0, 32, IsPCRelConstant},
8283
{"fixup_t2_pcrel_10", 0, 32,
8384
MCFixupKindInfo::FKF_IsPCRel |

llvm/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,12 @@ unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target,
158158
default:
159159
return ELF::R_ARM_THM_CALL;
160160
}
161+
case ARM::fixup_arm_ldst_pcrel_12:
162+
return ELF::R_ARM_LDR_PC_G0;
163+
case ARM::fixup_arm_pcrel_10_unscaled:
164+
return ELF::R_ARM_LDRS_PC_G0;
165+
case ARM::fixup_t2_ldst_pcrel_12:
166+
return ELF::R_ARM_THM_PC12;
161167
case ARM::fixup_bf_target:
162168
return ELF::R_ARM_THM_BF16;
163169
case ARM::fixup_bfc_target:
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
@ RUN: llvm-mc -filetype=obj -triple=armv7 %s -o %t
2+
@ RUN: llvm-readelf -r %t | FileCheck %s --check-prefix=ARM
3+
@ RUN: llvm-objdump -d --triple=armv7 %t | FileCheck %s --check-prefix=ARM_ADDEND
4+
5+
@ ARM: R_ARM_LDRS_PC_G0
6+
@ ARM: R_ARM_LDRS_PC_G0
7+
@ ARM: R_ARM_LDRS_PC_G0
8+
@ ARM: R_ARM_LDRS_PC_G0
9+
@ ARM: R_ARM_LDRS_PC_G0
10+
@ ARM: R_ARM_LDRS_PC_G0
11+
12+
// The value format is decimal in these specific cases, but it's hex for other
13+
// ldr instructions. These checks are valid for both formats.
14+
15+
@ ARM_ADDEND: r0, [pc, #-{{(0x)?}}8]
16+
@ ARM_ADDEND: r0, [pc, #-{{(0x)?}}8]
17+
@ ARM_ADDEND: r0, [pc, #-{{(0x)?}}8]
18+
@ ARM_ADDEND: r0, [pc, #-{{16|0x10}}]
19+
@ ARM_ADDEND: r0, [pc, #-{{16|0x10}}]
20+
@ ARM_ADDEND: r0, [pc]
21+
22+
.arm
23+
.section .text.bar, "ax"
24+
.balign 4
25+
.global bar
26+
.type bar, %function
27+
bar:
28+
ldrh r0, foo
29+
ldrsb r0, foo
30+
ldrsh r0, foo
31+
ldrh r0, just_after-8
32+
ldrsb r0, just_after-8
33+
ldrsh r0, foo+8
34+
bx lr
35+
36+
.section .data.foo, "a", %progbits
37+
.balign 4
38+
.global foo
39+
foo:
40+
.word 0x11223344, 0x55667788
41+
just_after:
42+
.word 0x9900aabb, 0xccddeeff

llvm/test/MC/ARM/pcrel-global.s

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,18 @@
99
@ DISASM-LABEL: <bar>:
1010
@ DISASM-NEXT: adr.w r0, #-4
1111
@ DISASM-NEXT: adr.w r0, #-8
12-
@ DISASM-NEXT: ldr.w pc, [pc, #-0xc] @ 0x10 <bar>
13-
@ DISASM-NEXT: ldr r0, [pc, #0x0] @ 0x20 <bar+0x10>
12+
@ DISASM-NEXT: ldr r0, [pc, #0x0] @ 0x14 <bar+0xc>
1413
@ DISASM-NEXT: add r0, pc
15-
@ DISASM-NEXT: .word 0xffffffef
14+
@ DISASM-NEXT: .word 0xfffffff3
1615
@@ GNU assembler creates an R_ARM_REL32 referencing bar.
1716
@ DISASM-NOT: {{.}}
1817

1918
.syntax unified
2019

2120
.globl foo
2221
foo:
23-
ldrd r0, r1, foo @ arm_pcrel_10_unscaled
2422
vldr d0, foo @ arm_pcrel_10
2523
adr r2, foo @ arm_adr_pcrel_12
26-
ldr r0, foo @ arm_ldst_pcrel_12
2724

2825
.thumb
2926
.thumb_func
@@ -32,7 +29,6 @@ ldr r0, foo @ arm_ldst_pcrel_12
3229
bar:
3330
adr r0, bar @ thumb_adr_pcrel_10
3431
adr.w r0, bar @ t2_adr_pcrel_12
35-
ldr.w pc, bar @ t2_ldst_pcrel_12
3632

3733
ldr r0, .LCPI
3834
.LPC0_1:

llvm/test/MC/ARM/pcrel-ldr-relocs.s

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
@ RUN: llvm-mc -filetype=obj -triple=armv7 %s -o %t
2+
@ RUN: llvm-readelf -r %t | FileCheck %s --check-prefix=ARM
3+
@ RUN: llvm-objdump -d --triple=armv7 %t | FileCheck %s --check-prefix=ARM_ADDEND
4+
@ RUN: llvm-mc -filetype=obj -triple=thumbv7 %s -o %t
5+
@ RUN: llvm-readelf -r %t | FileCheck %s --check-prefix=THUMB
6+
@ RUN: llvm-objdump -d --triple=thumbv7 %t | FileCheck %s --check-prefix=THUMB_ADDEND
7+
8+
@ ARM: R_ARM_LDR_PC_G0
9+
@ ARM: R_ARM_LDR_PC_G0
10+
@ ARM: R_ARM_LDR_PC_G0
11+
@ ARM: R_ARM_LDR_PC_G0
12+
13+
@ ARM_ADDEND: r0, [pc, #-0x8]
14+
@ ARM_ADDEND: r0, [pc, #-0x8]
15+
@ ARM_ADDEND: r0, [pc, #-0x10]
16+
@ ARM_ADDEND: r0, [pc]
17+
18+
@ THUMB: R_ARM_THM_PC12
19+
@ THUMB: R_ARM_THM_PC12
20+
@ THUMB: R_ARM_THM_PC12
21+
@ THUMB: R_ARM_THM_PC12
22+
23+
@ THUMB_ADDEND: r0, [pc, #-0x4]
24+
@ THUMB_ADDEND: r0, [pc, #-0x4]
25+
@ THUMB_ADDEND: r0, [pc, #-0xc]
26+
@ THUMB_ADDEND: r0, [pc, #0x4]
27+
28+
.section .text.bar, "ax"
29+
.balign 4
30+
.global bar
31+
.type bar, %function
32+
bar:
33+
ldr r0, foo1
34+
ldrb r0, foo1
35+
ldr r0, foo2-8
36+
ldrb r0, foo1+8
37+
bx lr
38+
39+
.section .data.foo, "a", %progbits
40+
.balign 4
41+
.global foo1
42+
.global foo2
43+
foo1:
44+
.word 0x11223344, 0x55667788
45+
foo2:
46+
.word 0x99aabbcc, 0xddeeff00
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
@ RUN: llvm-mc -filetype=obj -triple=thumbv7 %s -o %t
2+
@ RUN: llvm-readelf -r %t | FileCheck %s --check-prefix=THUMB
3+
@ RUN: llvm-objdump -d --triple=thumbv7 %t | FileCheck %s --check-prefix=THUMB_ADDEND
4+
5+
@ All the ldr variants produce a relocation
6+
@ THUMB: R_ARM_THM_PC12
7+
@ THUMB: R_ARM_THM_PC12
8+
@ THUMB: R_ARM_THM_PC12
9+
@ THUMB: R_ARM_THM_PC12
10+
@ THUMB: R_ARM_THM_PC12
11+
@ THUMB: R_ARM_THM_PC12
12+
13+
@ THUMB_ADDEND: r0, [pc, #-0x4]
14+
@ THUMB_ADDEND: r0, [pc, #-0x4]
15+
@ THUMB_ADDEND: r0, [pc, #-0x4]
16+
@ THUMB_ADDEND: r0, [pc, #0x4]
17+
@ THUMB_ADDEND: r0, [pc, #-0xc]
18+
@ THUMB_ADDEND: r0, [pc, #0x4]
19+
20+
.thumb
21+
.section .text.bar, "ax"
22+
.balign 4
23+
.global bar
24+
.type bar, %function
25+
bar:
26+
ldrh r0, foo1
27+
ldrsb r0, foo1
28+
ldrsh r0, foo1
29+
ldrh r0, foo1+8
30+
ldrsb r0, foo2-8
31+
ldrsh r0, foo1+8
32+
bx lr
33+
34+
.section .data.foo, "a", %progbits
35+
.balign 4
36+
.global foo1
37+
.global foo2
38+
foo1:
39+
.word 0x11223344, 0x55667788
40+
foo2:
41+
.word 0x9900aabb, 0xccddeeff

llvm/test/MC/ARM/thumb1-relax-ldrlit.s

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
@ RUN: not llvm-mc -triple thumbv6m-none-macho -filetype=obj -o /dev/null %s 2>&1 | FileCheck --check-prefix=CHECK-ERROR %s
22
@ RUN: not llvm-mc -triple thumbv7m-none-macho -filetype=obj -o /dev/null %s 2>&1 | FileCheck --check-prefix=CHECK-ERROR %s
3-
@ RUN: not llvm-mc -triple thumbv7m-none-eabi -filetype=obj -o /dev/null %s 2>&1 | FileCheck --check-prefix=CHECK-ERROR %s
43

54
.global func1
65
_func1:

0 commit comments

Comments
 (0)