Skip to content

Commit 7515480

Browse files
committed
[llvm][MC][ARM][Assembly] Emit relocs for LDRs
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 bdc0afc commit 7515480

File tree

7 files changed

+131
-10
lines changed

7 files changed

+131
-10
lines changed

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,10 @@ 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 | MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
80+
{"fixup_arm_pcrel_10_unscaled", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
8181
{"fixup_arm_pcrel_10", 0, 32, IsPCRelConstant},
8282
{"fixup_t2_pcrel_10", 0, 32,
8383
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: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
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: foo1
7+
@ ARM: R_ARM_LDRS_PC_G0
8+
@ ARM: foo2
9+
@ ARM: R_ARM_LDRS_PC_G0
10+
@ ARM: foo3
11+
12+
// Value is decimal at the moment but hex in other cases (things could change)
13+
@ ARM_ADDEND: r0, [pc, #-
14+
@ ARM_ADDEND 8]
15+
@ ARM_ADDEND: r0, [pc, #-
16+
@ ARM_ADDEND 8]
17+
@ ARM_ADDEND: r0, [pc, #-
18+
@ ARM_ADDEND 8]
19+
20+
.arm
21+
.section .text.bar, "ax"
22+
.balign 4
23+
.global bar
24+
.type bar, %function
25+
bar:
26+
ldrh r0, foo1
27+
ldrsb r0, foo2
28+
ldrsh r0, foo3
29+
bx lr
30+
31+
.section .data.foo, "a", %progbits
32+
.balign 4
33+
.global foo1
34+
.global foo2
35+
.global foo3
36+
foo1:
37+
foo2:
38+
foo3:
39+
.word 0x11223344, 0x55667788

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: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
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: foo1
10+
@ ARM: R_ARM_LDR_PC_G0
11+
@ ARM: foo2
12+
13+
@ ARM_ADDEND: r0, [pc, #-0x8]
14+
@ ARM_ADDEND: r0, [pc, #-0x8]
15+
@ ARM_ADDEND: r0, [pc, #-0x10]
16+
17+
@ THUMB: R_ARM_THM_PC12
18+
@ THUMB: foo1
19+
@ THUMB: R_ARM_THM_PC12
20+
@ THUMB: foo2
21+
22+
@ THUMB_ADDEND: r0, [pc, #-0x4]
23+
@ THUMB_ADDEND: r0, [pc, #-0x4]
24+
@ THUMB_ADDEND: r0, [pc, #-0xc]
25+
26+
.section .text.bar, "ax"
27+
.balign 4
28+
.global bar
29+
.type bar, %function
30+
bar:
31+
ldr r0, foo1
32+
ldrb r0, foo2
33+
ldr r0, foo3-8
34+
bx lr
35+
36+
.section .data.foo, "a", %progbits
37+
.balign 4
38+
.global foo1
39+
.global foo2
40+
.global foo3
41+
foo1:
42+
foo2:
43+
.word 0x11223344, 0x55667788
44+
foo3:
45+
.word 0x99aabbcc, 0xddeeff00
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
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: foo3
8+
@ THUMB: R_ARM_THM_PC12
9+
@ THUMB: foo4
10+
@ THUMB: R_ARM_THM_PC12
11+
@ THUMB: foo5
12+
13+
@ THUMB_ADDEND: r0, [pc, #-0x4]
14+
@ THUMB_ADDEND: r0, [pc, #-0x4]
15+
@ THUMB_ADDEND: r0, [pc, #-0x4]
16+
17+
.thumb
18+
.section .text.bar, "ax"
19+
.balign 4
20+
.global bar
21+
.type bar, %function
22+
bar:
23+
ldrh r0, foo3
24+
ldrsb r0, foo4
25+
ldrsh r0, foo5
26+
bx lr
27+
28+
.section .data.foo, "a", %progbits
29+
.balign 4
30+
.global foo3
31+
.global foo4
32+
.global foo5
33+
foo3:
34+
foo4:
35+
foo5:
36+
.word 0x11223344, 0x55667788

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)