Skip to content

Commit 0182334

Browse files
authored
[ARM] [Windows] Error out on branch relocations that require a symbol offset (#101906)
This adds the same kind of verification for ARM, as was added for AArch64 in 1e7f592. This allows catching issues at assembly time, instead of having the linker misinterpret the relocations (as the linker ignores the symbol offset). This verifies that the issue fixed by 8dd065d really is fixed, and points out explicitly if the same issue appears elsewhere. Note that the parameter Value in the adjustFixupValue function is offset by 4 from the value that is stored as immediate in the instructions, so we compare with 4, when we want to make sure that the written immediate will be zero.
1 parent 735edd9 commit 0182334

File tree

2 files changed

+62
-0
lines changed

2 files changed

+62
-0
lines changed

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

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -587,6 +587,14 @@ unsigned ARMAsmBackend::adjustFixupValue(const MCAssembler &Asm,
587587
return 0;
588588
return 0xffffff & ((Value - 8) >> 2);
589589
case ARM::fixup_t2_uncondbranch: {
590+
if (STI->getTargetTriple().isOSBinFormatCOFF() && !IsResolved &&
591+
Value != 4) {
592+
// MSVC link.exe and lld do not support this relocation type
593+
// with a non-zero offset. ("Value" is offset by 4 at this point.)
594+
Ctx.reportError(Fixup.getLoc(),
595+
"cannot perform a PC-relative fixup with a non-zero "
596+
"symbol offset");
597+
}
590598
Value = Value - 4;
591599
if (!isInt<25>(Value)) {
592600
Ctx.reportError(Fixup.getLoc(), "Relocation out of range");
@@ -637,6 +645,14 @@ unsigned ARMAsmBackend::adjustFixupValue(const MCAssembler &Asm,
637645
Ctx.reportError(Fixup.getLoc(), "Relocation out of range");
638646
return 0;
639647
}
648+
if (STI->getTargetTriple().isOSBinFormatCOFF() && !IsResolved &&
649+
Value != 4) {
650+
// MSVC link.exe and lld do not support this relocation type
651+
// with a non-zero offset. ("Value" is offset by 4 at this point.)
652+
Ctx.reportError(Fixup.getLoc(),
653+
"cannot perform a PC-relative fixup with a non-zero "
654+
"symbol offset");
655+
}
640656

641657
// The value doesn't encode the low bit (always zero) and is offset by
642658
// four. The 32-bit immediate value is encoded as
@@ -666,6 +682,14 @@ unsigned ARMAsmBackend::adjustFixupValue(const MCAssembler &Asm,
666682
Endian == llvm::endianness::little);
667683
}
668684
case ARM::fixup_arm_thumb_blx: {
685+
if (STI->getTargetTriple().isOSBinFormatCOFF() && !IsResolved &&
686+
Value != 4) {
687+
// MSVC link.exe and lld do not support this relocation type
688+
// with a non-zero offset. ("Value" is offset by 4 at this point.)
689+
Ctx.reportError(Fixup.getLoc(),
690+
"cannot perform a PC-relative fixup with a non-zero "
691+
"symbol offset");
692+
}
669693
// The value doesn't encode the low two bits (always zero) and is offset by
670694
// four (see fixup_arm_thumb_cp). The 32-bit immediate value is encoded as
671695
// imm32 = SignExtend(S:I1:I2:imm10H:imm10L:00)

llvm/test/MC/ARM/Windows/branch-reloc-offset.s

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// RUN: llvm-mc -triple thumbv7-windows-gnu -filetype obj %s -o - | llvm-objdump -D -r - | FileCheck %s
2+
// RUN: not llvm-mc -triple thumbv7-windows-gnu -filetype obj --defsym ERR=1 %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR
23

34
.text
45
main:
@@ -55,3 +56,40 @@ main:
5556
// CHECK: e: bf00 nop
5657
// CHECK: 00000010 <.Lother_target>:
5758
// CHECK: 10: 4770 bx lr
59+
60+
.ifdef ERR
61+
.section "other2", "xr"
62+
err:
63+
nop
64+
65+
// Test errors, if referencing a symbol with an offset
66+
67+
b .Lerr_target+4
68+
// ERR: [[#@LINE-1]]:5: error: cannot perform a PC-relative fixup with a non-zero symbol offset
69+
bl .Lerr_target+4
70+
// ERR: [[#@LINE-1]]:5: error: cannot perform a PC-relative fixup with a non-zero symbol offset
71+
blx .Lerr_target+4
72+
// ERR: [[#@LINE-1]]:5: error: cannot perform a PC-relative fixup with a non-zero symbol offset
73+
74+
// Test errors, if referencing a private label which lacks .def/.scl/.type/.endef, in another
75+
// section, without an offset. Such symbols are omitted from the output symbol table, so the
76+
// relocation can't reference them. Such relocations usually are made towards the base of the
77+
// section plus an offset, but such an offset is not supported with this relocation.
78+
79+
b .Lerr_target2
80+
// ERR: [[#@LINE-1]]:5: error: cannot perform a PC-relative fixup with a non-zero symbol offset
81+
82+
.def .Lerr_target
83+
.scl 3
84+
.type 32
85+
.endef
86+
.Lerr_target:
87+
nop
88+
nop
89+
bx lr
90+
91+
.section "other3", "xr"
92+
nop
93+
.Lerr_target2:
94+
bx lr
95+
.endif

0 commit comments

Comments
 (0)