[JITLink] Add support for MachO/x86-64 UNSIGNED relocs with length=2.
authorLang Hames <lhames@gmail.com>
Sat, 3 Aug 2019 20:17:10 +0000 (20:17 +0000)
committerLang Hames <lhames@gmail.com>
Sat, 3 Aug 2019 20:17:10 +0000 (20:17 +0000)
MachO/x86-64 UNSIGNED relocs are almost always 64-bit (length=3), but UNSIGNED
relocs of length=2 are allowed if the target resides in the low 32-bits. This
patch adds support for such relocations in JITLink (previously they would have
triggered an unsupported relocation error).

llvm-svn: 367764

llvm/include/llvm/ExecutionEngine/JITLink/MachO_x86_64.h
llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp
llvm/test/ExecutionEngine/JITLink/X86/MachO_x86-64_relocations.s

index 1d5b586..00a7feb 100644 (file)
@@ -22,6 +22,7 @@ namespace MachO_x86_64_Edges {
 
 enum MachOX86RelocationKind : Edge::Kind {
   Branch32 = Edge::FirstRelocation,
+  Pointer32,
   Pointer64,
   Pointer64Anon,
   PCRel32,
index 6b2b392..52481f8 100644 (file)
@@ -40,8 +40,12 @@ private:
   getRelocationKind(const MachO::relocation_info &RI) {
     switch (RI.r_type) {
     case MachO::X86_64_RELOC_UNSIGNED:
-      if (!RI.r_pcrel && RI.r_length == 3)
-        return RI.r_extern ? Pointer64 : Pointer64Anon;
+      if (!RI.r_pcrel) {
+        if (RI.r_length == 3)
+          return RI.r_extern ? Pointer64 : Pointer64Anon;
+        else if (RI.r_extern && RI.r_length == 2)
+          return Pointer32;
+      }
       break;
     case MachO::X86_64_RELOC_SIGNED:
       if (RI.r_pcrel && RI.r_length == 2)
@@ -260,6 +264,13 @@ private:
             return TargetAtomOrErr.takeError();
           Addend = *(const ulittle32_t *)FixupContent;
           break;
+        case Pointer32:
+          if (auto TargetAtomOrErr = findAtomBySymbolIndex(RI))
+            TargetAtom = &*TargetAtomOrErr;
+          else
+            return TargetAtomOrErr.takeError();
+          Addend = *(const ulittle32_t *)FixupContent;
+          break;
         case Pointer64:
           if (auto TargetAtomOrErr = findAtomBySymbolIndex(RI))
             TargetAtom = &*TargetAtomOrErr;
@@ -526,6 +537,13 @@ private:
         *(little64_t *)FixupPtr = Value;
       break;
     }
+    case Pointer32: {
+      uint64_t Value = E.getTarget().getAddress() + E.getAddend();
+      if (Value > std::numeric_limits<uint32_t>::max())
+        return targetOutOfRangeError(A, E);
+      *(ulittle32_t *)FixupPtr = Value;
+      break;
+    }
     default:
       llvm_unreachable("Unrecognized edge kind");
     }
@@ -565,6 +583,8 @@ StringRef getMachOX86RelocationKindName(Edge::Kind R) {
   switch (R) {
   case Branch32:
     return "Branch32";
+  case Pointer32:
+    return "Pointer32";
   case Pointer64:
     return "Pointer64";
   case Pointer64Anon:
index 1958ae1..0fb1285 100644 (file)
@@ -154,22 +154,31 @@ named_data:
 named_data_alt_entry:
         .quad   0
 
-# Check X86_64_RELOC_UNSIGNED / extern handling by putting the address of a
-# local named function in a pointer variable.
+# Check X86_64_RELOC_UNSIGNED / quad / extern handling by putting the address of
+# a local named function into a quad symbol.
 #
-# jitlink-check: *{8}named_func_addr = named_func
-        .globl  named_func_addr
+# jitlink-check: *{8}named_func_addr_quad = named_func
+        .globl  named_func_addr_quad
         .p2align  3
-named_func_addr:
+named_func_addr_quad:
         .quad   named_func
 
-# Check X86_64_RELOC_UNSIGNED / non-extern handling by putting the address of a
-# local anonymous function in a pointer variable.
+# Check X86_64_RELOC_UNSIGNED / long / extern handling by putting the address of
+# an external function (defined to reside in the low 4Gb) into a long symbol.
 #
-# jitlink-check: *{8}anon_func_addr = section_addr(macho_reloc.o, __text)
-        .globl  anon_func_addr
+# jitlink-check: *{8}named_func_addr_long = external_func
+        .globl  named_func_addr_long
+        .p2align  2
+named_func_addr_long:
+        .long   external_func
+
+# Check X86_64_RELOC_UNSIGNED / quad / non-extern handling by putting the
+# address of a local anonymous function into a quad symbol.
+#
+# jitlink-check: *{8}anon_func_addr_quad = section_addr(macho_reloc.o, __text)
+        .globl  anon_func_addr_quad
         .p2align  3
-anon_func_addr:
+anon_func_addr_quad:
         .quad   Lanon_func
 
 # X86_64_RELOC_SUBTRACTOR Quad/Long in named storage with anonymous minuend