]> granicus.if.org Git - llvm/commitdiff
[AArch64] Force relocations for all ADRP instructions
authorMartin Storsjo <martin@martin.st>
Wed, 19 Jul 2017 20:14:32 +0000 (20:14 +0000)
committerMartin Storsjo <martin@martin.st>
Wed, 19 Jul 2017 20:14:32 +0000 (20:14 +0000)
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

lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp
test/MC/AArch64/coff-relocations.s
test/MC/AArch64/macho-adrp-missing-reloc.s [new file with mode: 0644]
test/MC/AArch64/macho-adrp-page.s [new file with mode: 0644]

index 2bd0cbf9f7c6a44692513929db1b54a76d0f88da..0243e75e44c6ae9ae00f127ffbefecd6e2f476a9 100644 (file)
@@ -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 {
index 221ecfd4cd41fe283b12a537e40e3747ceb939de..10c2dbfcb5354a9ae1c529b8be14529d523f72fa 100644 (file)
@@ -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 (file)
index 0000000..f94ca20
--- /dev/null
@@ -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 (file)
index 0000000..b9afc5c
--- /dev/null
@@ -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