diff --git a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp index 17856452b7c..2f6a4497f46 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp +++ b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp @@ -83,7 +83,9 @@ const MCFixupKindInfo &ARMAsmBackend::getFixupKindInfo(MCFixupKind Kind) const { {"fixup_arm_condbl", 0, 24, MCFixupKindInfo::FKF_IsPCRel}, {"fixup_arm_blx", 0, 24, MCFixupKindInfo::FKF_IsPCRel}, {"fixup_arm_thumb_bl", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, - {"fixup_arm_thumb_blx", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, + {"fixup_arm_thumb_blx", 0, 32, + MCFixupKindInfo::FKF_IsPCRel | + MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, {"fixup_arm_thumb_cb", 0, 16, MCFixupKindInfo::FKF_IsPCRel}, {"fixup_arm_thumb_cp", 0, 8, MCFixupKindInfo::FKF_IsPCRel | @@ -131,7 +133,9 @@ const MCFixupKindInfo &ARMAsmBackend::getFixupKindInfo(MCFixupKind Kind) const { {"fixup_arm_condbl", 8, 24, MCFixupKindInfo::FKF_IsPCRel}, {"fixup_arm_blx", 8, 24, MCFixupKindInfo::FKF_IsPCRel}, {"fixup_arm_thumb_bl", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, - {"fixup_arm_thumb_blx", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, + {"fixup_arm_thumb_blx", 0, 32, + MCFixupKindInfo::FKF_IsPCRel | + MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, {"fixup_arm_thumb_cb", 0, 16, MCFixupKindInfo::FKF_IsPCRel}, {"fixup_arm_thumb_cp", 8, 8, MCFixupKindInfo::FKF_IsPCRel | @@ -535,7 +539,12 @@ unsigned ARMAsmBackend::adjustFixupValue(const MCFixup &Fixup, uint64_t Value, // // Note that the halfwords are stored high first, low second; so we need // to transpose the fixup value here to map properly. - uint32_t offset = (Value - 2) >> 2; + if (Ctx && Value % 4 != 0) { + Ctx->reportError(Fixup.getLoc(), "misaligned ARM call destination"); + return 0; + } + + uint32_t offset = (Value - 4) >> 2; if (const MCSymbolRefExpr *SRE = dyn_cast(Fixup.getValue())) if (SRE->getKind() == MCSymbolRefExpr::VK_TLSCALL) diff --git a/test/MC/ARM/aligned-blx.s b/test/MC/ARM/aligned-blx.s new file mode 100644 index 00000000000..562eaac0467 --- /dev/null +++ b/test/MC/ARM/aligned-blx.s @@ -0,0 +1,34 @@ +@ RUN: llvm-mc -triple thumbv7-apple-ios -filetype=obj %s -o %t +@ RUN: llvm-objdump -macho -d %t | FileCheck %s + + @ Size: 2 bytes + .thumb_func _f1 + .thumb + .globl _f1 +_f1: + bx lr + + @ A properly aligned ARM function + .globl _aligned + .p2align 2 + .arm +_aligned: + bx lr + + @ Align this Thumb function so we can predict the outcome of + @ "Align(PC, 4)" during blx operation. + .thumb_func _test + .thumb + .p2align 2 + .globl _test +_test: + blx _elsewhere + blx _aligned @ PC=0 (mod 4) + blx _aligned @ PC=0 (mod 4) + movs r0, r0 + blx _aligned @ PC=2 (mod 4) + +@ CHECK: blx _elsewhere +@ CHECK: ff f7 fa ef blx _aligned +@ CHECK: ff f7 f8 ef blx _aligned +@ CHECK: ff f7 f6 ef blx _aligned diff --git a/test/MC/ARM/misaligned-blx.s b/test/MC/ARM/misaligned-blx.s new file mode 100644 index 00000000000..b3cef027528 --- /dev/null +++ b/test/MC/ARM/misaligned-blx.s @@ -0,0 +1,40 @@ +@ RUN: not llvm-mc -triple thumbv7-apple-ios -filetype=obj %s -o /dev/null 2>&1 | FileCheck %s + @ Size: 2 bytes + .thumb_func _f1 + .thumb + .globl _f1 +_f1: + bx lr + + @ A misalgined ARM destination. + .arm + .globl _misaligned +_misaligned: + bx lr + + @ And a properly aligned one. + .globl _aligned + .p2align 2 + .arm +_aligned: + bx lr + + @ Align this Thumb function so we can predict the outcome of + @ "Align(PC, 4)" during blx operation. + .thumb_func _test + .thumb + .p2align 2 + .globl _test +_test: + blx _misaligned @ PC=0 (mod 4) + movs r0, r0 + blx _misaligned @ PC=2 (mod 4) + movs r0, r0 + blx _aligned @ PC=0 (mod 4) + movs r0, r0 + blx _aligned @ PC=2 (mod 4) + +@ CHECK: error: misaligned ARM call destination +@ CHECK: blx _misaligned +@ CHECK: error: misaligned ARM call destination +@ CHECK: blx _misaligned