[MCJIT] More endianness fixes for RuntimeDyldMachO.
[oota-llvm.git] / lib / ExecutionEngine / RuntimeDyld / RuntimeDyldMachO.cpp
index ba7c7cb92404d36e22b91e37c1619e99b1409598..9e4d3ac82afb3d21cd86cf60a244d572fc580b34 100644 (file)
@@ -27,10 +27,23 @@ using namespace llvm::object;
 
 namespace llvm {
 
-int64_t RuntimeDyldMachO::decodeAddend(uint8_t *LocalAddress, unsigned NumBytes,
-                                       uint32_t RelType) const {
+int64_t RuntimeDyldMachO::memcpyAddend(const RelocationEntry &RE) const {
+  const SectionEntry &Section = Sections[RE.SectionID];
+  unsigned NumBytes = 1 << RE.Size;
   int64_t Addend = 0;
-  memcpy(&Addend, LocalAddress, NumBytes);
+  uint8_t *LocalAddress = Section.Address + RE.Offset;
+  uint8_t *Dst = reinterpret_cast<uint8_t*>(&Addend);
+
+  if (IsTargetLittleEndian == sys::IsLittleEndianHost) {
+    if (!sys::IsLittleEndianHost)
+      Dst += sizeof(Addend) - NumBytes;
+    memcpy(Dst, LocalAddress, NumBytes);
+  } else {
+    Dst += NumBytes - 1;
+    for (unsigned i = 0; i < NumBytes; ++i)
+      *Dst-- = *LocalAddress++;
+  }
+
   return Addend;
 }
 
@@ -79,7 +92,8 @@ RelocationValueRef RuntimeDyldMachO::getRelocationValueRef(
 
 void RuntimeDyldMachO::makeValueAddendPCRel(RelocationValueRef &Value,
                                             ObjectImage &ObjImg,
-                                            const relocation_iterator &RI) {
+                                            const relocation_iterator &RI,
+                                            unsigned OffsetToNextPC) {
   const MachOObjectFile &Obj =
       static_cast<const MachOObjectFile &>(*ObjImg.getObjectFile());
   MachO::any_relocation_info RelInfo =
@@ -89,8 +103,7 @@ void RuntimeDyldMachO::makeValueAddendPCRel(RelocationValueRef &Value,
   if (IsPCRel) {
     uint64_t RelocAddr = 0;
     RI->getAddress(RelocAddr);
-    unsigned RelocSize = Obj.getAnyRelocationLength(RelInfo);
-    Value.Addend += RelocAddr + (1ULL << RelocSize);
+    Value.Addend += RelocAddr + OffsetToNextPC;
   }
 }
 
@@ -102,17 +115,26 @@ void RuntimeDyldMachO::dumpRelocationToResolve(const RelocationEntry &RE,
 
   dbgs() << "resolveRelocation Section: " << RE.SectionID
          << " LocalAddress: " << format("%p", LocalAddress)
-         << " FinalAddress: " << format("%p", FinalAddress)
-         << " Value: " << format("%p", Value) << " Addend: " << RE.Addend
+         << " FinalAddress: " << format("0x%x", FinalAddress)
+         << " Value: " << format("0x%x", Value) << " Addend: " << RE.Addend
          << " isPCRel: " << RE.IsPCRel << " MachoType: " << RE.RelType
          << " Size: " << (1 << RE.Size) << "\n";
 }
 
-bool RuntimeDyldMachO::writeBytesUnaligned(uint8_t *Addr, uint64_t Value,
+bool RuntimeDyldMachO::writeBytesUnaligned(uint8_t *Dst, uint64_t Value,
                                            unsigned Size) {
-  for (unsigned i = 0; i < Size; ++i) {
-    *Addr++ = (uint8_t)Value;
-    Value >>= 8;
+
+  uint8_t *Src = reinterpret_cast<uint8_t*>(&Value);
+  // If host and target endianness match use memcpy, otherwise copy in reverse
+  // order.
+  if (IsTargetLittleEndian == sys::IsLittleEndianHost) {
+    if (!sys::IsLittleEndianHost)
+      Src += sizeof(Value) - Size;
+    memcpy(Dst, Src, Size);
+  } else {
+    Src += Size - 1;
+    for (unsigned i = 0; i < Size; ++i)
+      *Dst++ = *Src--;
   }
 
   return false;
@@ -214,7 +236,7 @@ llvm::RuntimeDyldMachO::create(Triple::ArchType Arch, RTDyldMemoryManager *MM) {
     llvm_unreachable("Unsupported target for RuntimeDyldMachO.");
     break;
   case Triple::arm: return make_unique<RuntimeDyldMachOARM>(MM);
-  case Triple::arm64: return make_unique<RuntimeDyldMachOAArch64>(MM);
+  case Triple::aarch64: return make_unique<RuntimeDyldMachOAArch64>(MM);
   case Triple::x86: return make_unique<RuntimeDyldMachOI386>(MM);
   case Triple::x86_64: return make_unique<RuntimeDyldMachOX86_64>(MM);
   }