From: Martin Storsjo Date: Wed, 19 Jul 2017 20:14:32 +0000 (+0000) Subject: [AArch64] Force relocations for all ADRP instructions X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0051096059ac72c809d6439f589795d086047720;p=llvm [AArch64] Force relocations for all ADRP instructions This generalizes an existing fix from ELF to MachO and COFF. Test that an ADRP to a local symbol whose offset is known at assembly time still produces relocations, both for MachO and COFF. Test that an ADRP without a @page modifier on MachO fails (previously it didn't). Differential Revision: https://reviews.llvm.org/D35544 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@308518 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp b/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp index 2bd0cbf9f7c..0243e75e44c 100644 --- a/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp +++ b/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp @@ -88,6 +88,9 @@ public: unsigned getPointerSize() const { return 8; } unsigned getFixupKindContainereSizeInBytes(unsigned Kind) const; + + bool shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup, + const MCValue &Target) override; }; } // end anonymous namespace @@ -338,6 +341,26 @@ bool AArch64AsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const { return true; } +bool AArch64AsmBackend::shouldForceRelocation(const MCAssembler &Asm, + const MCFixup &Fixup, + const MCValue &Target) { + // The ADRP instruction adds some multiple of 0x1000 to the current PC & + // ~0xfff. This means that the required offset to reach a symbol can vary by + // up to one step depending on where the ADRP is in memory. For example: + // + // ADRP x0, there + // there: + // + // If the ADRP occurs at address 0xffc then "there" will be at 0x1000 and + // we'll need that as an offset. At any other address "there" will be in the + // same page as the ADRP and the instruction should encode 0x0. Assuming the + // section isn't 0x1000-aligned, we therefore need to delegate this decision + // to the linker -- a relocation! + if ((uint32_t)Fixup.getKind() == AArch64::fixup_aarch64_pcrel_adrp_imm21) + return true; + return false; +} + namespace { namespace CU { @@ -544,31 +567,8 @@ public: MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const override { return createAArch64ELFObjectWriter(OS, OSABI, IsLittleEndian, IsILP32); } - - bool shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup, - const MCValue &Target) override; }; -bool ELFAArch64AsmBackend::shouldForceRelocation(const MCAssembler &Asm, - const MCFixup &Fixup, - const MCValue &Target) { - // The ADRP instruction adds some multiple of 0x1000 to the current PC & - // ~0xfff. This means that the required offset to reach a symbol can vary by - // up to one step depending on where the ADRP is in memory. For example: - // - // ADRP x0, there - // there: - // - // If the ADRP occurs at address 0xffc then "there" will be at 0x1000 and - // we'll need that as an offset. At any other address "there" will be in the - // same page as the ADRP and the instruction should encode 0x0. Assuming the - // section isn't 0x1000-aligned, we therefore need to delegate this decision - // to the linker -- a relocation! - if ((uint32_t)Fixup.getKind() == AArch64::fixup_aarch64_pcrel_adrp_imm21) - return true; - return false; -} - } namespace { diff --git a/test/MC/AArch64/coff-relocations.s b/test/MC/AArch64/coff-relocations.s index 221ecfd4cd4..10c2dbfcb53 100644 --- a/test/MC/AArch64/coff-relocations.s +++ b/test/MC/AArch64/coff-relocations.s @@ -26,6 +26,10 @@ add x0, x0, :lo12:foo ; IMAGE_REL_ARM64_PAGEOFFSET_12L ldr x0, [x0, :lo12:foo] +; IMAGE_REL_ARM64_PAGEBASE_REL21, even if the symbol offset is known +adrp x0, bar +bar: + ; IMAGE_REL_ARM64_SECREL .secrel32 .Linfo_bar .Linfo_bar: @@ -33,7 +37,6 @@ ldr x0, [x0, :lo12:foo] ; IMAGE_REL_ARM64_SECTION .secidx func - ; CHECK: Format: COFF-ARM64 ; CHECK: Arch: aarch64 ; CHECK: AddressSize: 64bit @@ -46,7 +49,8 @@ ldr x0, [x0, :lo12:foo] ; CHECK: 0x18 IMAGE_REL_ARM64_PAGEBASE_REL21 foo ; CHECK: 0x1C IMAGE_REL_ARM64_PAGEOFFSET_12A foo ; CHECK: 0x20 IMAGE_REL_ARM64_PAGEOFFSET_12L foo -; CHECK: 0x24 IMAGE_REL_ARM64_SECREL .text -; CHECK: 0x28 IMAGE_REL_ARM64_SECTION func +; CHECK: 0x24 IMAGE_REL_ARM64_PAGEBASE_REL21 bar +; CHECK: 0x28 IMAGE_REL_ARM64_SECREL .text +; CHECK: 0x2C IMAGE_REL_ARM64_SECTION func ; CHECK: } ; CHECK: ] diff --git a/test/MC/AArch64/macho-adrp-missing-reloc.s b/test/MC/AArch64/macho-adrp-missing-reloc.s new file mode 100644 index 00000000000..f94ca2094d3 --- /dev/null +++ b/test/MC/AArch64/macho-adrp-missing-reloc.s @@ -0,0 +1,6 @@ +; RUN: not llvm-mc < %s -triple arm64-apple-darwin -filetype=obj -o - 2>&1 | FileCheck %s + +; CHECK: error: ADR/ADRP relocations must be GOT relative + adrp x3, Lbar +Lbar: + ret diff --git a/test/MC/AArch64/macho-adrp-page.s b/test/MC/AArch64/macho-adrp-page.s new file mode 100644 index 00000000000..b9afc5c1a3f --- /dev/null +++ b/test/MC/AArch64/macho-adrp-page.s @@ -0,0 +1,6 @@ +; RUN: llvm-mc < %s -triple arm64-apple-darwin -filetype=obj -o - | llvm-readobj -r - | FileCheck %s + + adrp x3, Lbar@page +; CHECK: ARM64_RELOC_PAGE21 +Lbar: + ret