[MCJIT] Fix the ARM BR24 relocation in RuntimeDyldMachO.

We now (1) correctly decode the branch immediate, (2) modify the immediate to
corretly treat it as PC-rel, and (3) properly populate the stub entry.
Previously we had been doing each of these wrong.

<rdar://problem/17750739>

llvm-svn: 214285
diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h b/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h
index 1de9942..dadde76 100644
--- a/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h
+++ b/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h
@@ -18,6 +18,9 @@
 
 class RuntimeDyldMachOARM
     : public RuntimeDyldMachOCRTPBase<RuntimeDyldMachOARM> {
+private:
+  typedef RuntimeDyldMachOCRTPBase<RuntimeDyldMachOARM> ParentT;
+
 public:
   RuntimeDyldMachOARM(RTDyldMemoryManager *MM) : RuntimeDyldMachOCRTPBase(MM) {}
 
@@ -25,6 +28,21 @@
 
   unsigned getStubAlignment() override { return 4; }
 
+  int64_t decodeAddend(uint8_t *LocalAddress, unsigned NumBytes,
+                       MachO::RelocationInfoType RelType) const {
+    switch (RelType) {
+      default:
+        return ParentT::decodeAddend(LocalAddress, NumBytes, RelType);
+      case MachO::ARM_RELOC_BR24: {
+        uint32_t Temp;
+        memcpy(&Temp, LocalAddress, 4);
+        Temp &= 0x00ffffff; // Mask out the opcode.
+        // Now we've got the shifted immediate, shift by 2, sign extend and ret.
+        return SignExtend32<26>(Temp << 2);
+      }
+    }
+  }
+
   relocation_iterator
   processRelocationRef(unsigned SectionID, relocation_iterator RelI,
                        ObjectImage &ObjImg, ObjSectionToIDMap &ObjSectionToID,
@@ -41,9 +59,8 @@
     RelocationValueRef Value(
         getRelocationValueRef(ObjImg, RelI, RE, ObjSectionToID, Symbols));
 
-    bool IsExtern = Obj.getPlainRelocationExternal(RelInfo);
-    if (!IsExtern && RE.IsPCRel)
-      makeValueAddendPCRel(Value, ObjImg, RelI);
+    if (RE.IsPCRel)
+      makeValueAddendPCRel(Value, ObjImg, RelI, 8);
 
     if ((RE.RelType & 0xf) == MachO::ARM_RELOC_BR24)
       processBranchRelocation(RE, Value, Stubs);
@@ -134,7 +151,8 @@
       uint8_t *StubTargetAddr =
           createStubFunction(Section.Address + Section.StubOffset);
       RelocationEntry StubRE(RE.SectionID, StubTargetAddr - Section.Address,
-                             MachO::GENERIC_RELOC_VANILLA, Value.Addend);
+                             MachO::GENERIC_RELOC_VANILLA, Value.Addend, false,
+                             2);
       if (Value.SymbolName)
         addRelocationForSymbol(StubRE, Value.SymbolName);
       else
@@ -142,7 +160,7 @@
       Addr = Section.Address + Section.StubOffset;
       Section.StubOffset += getMaxStubSize();
     }
-    RelocationEntry TargetRE(Value.SectionID, RE.Offset, RE.RelType, 0,
+    RelocationEntry TargetRE(RE.SectionID, RE.Offset, RE.RelType, 0,
                              RE.IsPCRel, RE.Size);
     resolveRelocation(TargetRE, (uint64_t)Addr);
   }