1e0934bee3a4f40731169bc42b15a39ce39978175Jim Grosbach//===-- RuntimeDyldMachO.cpp - Run-time dynamic linker for MC-JIT -*- C++ -*-=// 2cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev// 3cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev// The LLVM Compiler Infrastructure 4cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev// 5cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev// This file is distributed under the University of Illinois Open Source 6cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev// License. See LICENSE.TXT for details. 7cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev// 8cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev//===----------------------------------------------------------------------===// 9cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev// 10cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev// Implementation of the MC-JIT runtime dynamic linker. 11cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev// 12cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev//===----------------------------------------------------------------------===// 13cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev 14cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev#define DEBUG_TYPE "dyld" 15d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "RuntimeDyldMachO.h" 16cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev#include "llvm/ADT/OwningPtr.h" 17cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev#include "llvm/ADT/STLExtras.h" 18d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/ADT/StringRef.h" 19cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshevusing namespace llvm; 20cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshevusing namespace llvm::object; 21cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev 22cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshevnamespace llvm { 23cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev 24a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindolastatic unsigned char *processFDE(unsigned char *P, intptr_t DeltaForText, intptr_t DeltaForEH) { 25a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola uint32_t Length = *((uint32_t*)P); 26a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola P += 4; 27a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola unsigned char *Ret = P + Length; 28a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola uint32_t Offset = *((uint32_t*)P); 29a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola if (Offset == 0) // is a CIE 30a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola return Ret; 31a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola 32a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola P += 4; 33a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola intptr_t FDELocation = *((intptr_t*)P); 34a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola intptr_t NewLocation = FDELocation - DeltaForText; 35a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola *((intptr_t*)P) = NewLocation; 36a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola P += sizeof(intptr_t); 37a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola 38a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola // Skip the FDE address range 39a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola P += sizeof(intptr_t); 40a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola 41a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola uint8_t Augmentationsize = *P; 42a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola P += 1; 43a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola if (Augmentationsize != 0) { 44a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola intptr_t LSDA = *((intptr_t*)P); 45a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola intptr_t NewLSDA = LSDA - DeltaForEH; 46a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola *((intptr_t*)P) = NewLSDA; 47a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola } 48a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola 49a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola return Ret; 50a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola} 51a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola 52a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindolastatic intptr_t computeDelta(SectionEntry *A, SectionEntry *B) { 53a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola intptr_t ObjDistance = A->ObjAddress - B->ObjAddress; 54a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola intptr_t MemDistance = A->LoadAddress - B->LoadAddress; 55a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola return ObjDistance - MemDistance; 56a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola} 57a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola 58a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael EspindolaStringRef RuntimeDyldMachO::getEHFrameSection() { 59a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola SectionEntry *Text = NULL; 60a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola SectionEntry *EHFrame = NULL; 61a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola SectionEntry *ExceptTab = NULL; 62a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola for (int i = 0, e = Sections.size(); i != e; ++i) { 63a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola if (Sections[i].Name == "__eh_frame") 64a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola EHFrame = &Sections[i]; 65a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola else if (Sections[i].Name == "__text") 66a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola Text = &Sections[i]; 67a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola else if (Sections[i].Name == "__gcc_except_tab") 68a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola ExceptTab = &Sections[i]; 69a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola } 70a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola if (Text == NULL || EHFrame == NULL) 71a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola return StringRef(); 72a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola 73a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola intptr_t DeltaForText = computeDelta(Text, EHFrame); 74a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola intptr_t DeltaForEH = 0; 75a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola if (ExceptTab) 76a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola DeltaForEH = computeDelta(ExceptTab, EHFrame); 77a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola 78a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola unsigned char *P = EHFrame->Address; 79a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola unsigned char *End = P + EHFrame->Size; 80a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola do { 81a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola P = processFDE(P, DeltaForText, DeltaForEH); 82a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola } while(P != End); 83a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola 84a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola return StringRef((char*)EHFrame->Address, EHFrame->Size); 85a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola} 86a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola 8787b5017139e9d8ac9b046b3284a9cc68c76185d6Rafael Espindolavoid RuntimeDyldMachO::resolveRelocation(const RelocationEntry &RE, 8887b5017139e9d8ac9b046b3284a9cc68c76185d6Rafael Espindola uint64_t Value) { 8987b5017139e9d8ac9b046b3284a9cc68c76185d6Rafael Espindola const SectionEntry &Section = Sections[RE.SectionID]; 9087b5017139e9d8ac9b046b3284a9cc68c76185d6Rafael Espindola return resolveRelocation(Section, RE.Offset, Value, RE.RelType, RE.Addend, 9187b5017139e9d8ac9b046b3284a9cc68c76185d6Rafael Espindola RE.IsPCRel, RE.Size); 9287b5017139e9d8ac9b046b3284a9cc68c76185d6Rafael Espindola} 9387b5017139e9d8ac9b046b3284a9cc68c76185d6Rafael Espindola 94a307a1cf859f4a523951ac887d094039547adeb5Andrew Kaylorvoid RuntimeDyldMachO::resolveRelocation(const SectionEntry &Section, 95a307a1cf859f4a523951ac887d094039547adeb5Andrew Kaylor uint64_t Offset, 960e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev uint64_t Value, 970e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev uint32_t Type, 9887b5017139e9d8ac9b046b3284a9cc68c76185d6Rafael Espindola int64_t Addend, 9987b5017139e9d8ac9b046b3284a9cc68c76185d6Rafael Espindola bool isPCRel, 10087b5017139e9d8ac9b046b3284a9cc68c76185d6Rafael Espindola unsigned LogSize) { 101a307a1cf859f4a523951ac887d094039547adeb5Andrew Kaylor uint8_t *LocalAddress = Section.Address + Offset; 102a307a1cf859f4a523951ac887d094039547adeb5Andrew Kaylor uint64_t FinalAddress = Section.LoadAddress + Offset; 10387b5017139e9d8ac9b046b3284a9cc68c76185d6Rafael Espindola unsigned MachoType = Type; 10487b5017139e9d8ac9b046b3284a9cc68c76185d6Rafael Espindola unsigned Size = 1 << LogSize; 1050e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev 1066d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky DEBUG(dbgs() << "resolveRelocation LocalAddress: " 1076d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky << format("%p", LocalAddress) 1080e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev << " FinalAddress: " << format("%p", FinalAddress) 1090e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev << " Value: " << format("%p", Value) 1100e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev << " Addend: " << Addend 1110e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev << " isPCRel: " << isPCRel 1120e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev << " MachoType: " << MachoType 1130e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev << " Size: " << Size 1140e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev << "\n"); 1150e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev 116cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev // This just dispatches to the proper target specific routine. 1170e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev switch (Arch) { 118858143816d43e58b17bfd11cb1b57afbd7f0f893Craig Topper default: llvm_unreachable("Unsupported CPU type!"); 1190e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev case Triple::x86_64: 1200e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev resolveX86_64Relocation(LocalAddress, 1210e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev FinalAddress, 1220e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev (uintptr_t)Value, 1230e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev isPCRel, 1240e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev MachoType, 1250e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev Size, 1260e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev Addend); 1270e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev break; 1280e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev case Triple::x86: 1290e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev resolveI386Relocation(LocalAddress, 1306d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky FinalAddress, 1316d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky (uintptr_t)Value, 1326d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky isPCRel, 133ba9ba9f9bcb8e627ff9cc4bd11904db21762e5a2Jim Grosbach MachoType, 1346d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky Size, 1356d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky Addend); 1360e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev break; 1370e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev case Triple::arm: // Fall through. 1380e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev case Triple::thumb: 1390e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev resolveARMRelocation(LocalAddress, 1400e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev FinalAddress, 1410e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev (uintptr_t)Value, 1420e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev isPCRel, 1430e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev MachoType, 1440e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev Size, 1450e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev Addend); 1460e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev break; 147cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev } 148cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev} 149cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev 1506d15e8717767af9a6a20c6ea456119c15c77dd00Eli Benderskybool RuntimeDyldMachO::resolveI386Relocation(uint8_t *LocalAddress, 1516d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky uint64_t FinalAddress, 1526d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky uint64_t Value, 1536d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky bool isPCRel, 1546d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky unsigned Type, 1556d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky unsigned Size, 1566d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky int64_t Addend) { 157b38aae442f0e3ce11a6231455b180bfc66ab5d3eSean Callanan if (isPCRel) 158b38aae442f0e3ce11a6231455b180bfc66ab5d3eSean Callanan Value -= FinalAddress + 4; // see resolveX86_64Relocation 159b38aae442f0e3ce11a6231455b180bfc66ab5d3eSean Callanan 160b38aae442f0e3ce11a6231455b180bfc66ab5d3eSean Callanan switch (Type) { 161b38aae442f0e3ce11a6231455b180bfc66ab5d3eSean Callanan default: 162b38aae442f0e3ce11a6231455b180bfc66ab5d3eSean Callanan llvm_unreachable("Invalid relocation type!"); 163b38aae442f0e3ce11a6231455b180bfc66ab5d3eSean Callanan case macho::RIT_Vanilla: { 164b38aae442f0e3ce11a6231455b180bfc66ab5d3eSean Callanan uint8_t *p = LocalAddress; 165b38aae442f0e3ce11a6231455b180bfc66ab5d3eSean Callanan uint64_t ValueToWrite = Value + Addend; 166b38aae442f0e3ce11a6231455b180bfc66ab5d3eSean Callanan for (unsigned i = 0; i < Size; ++i) { 167b38aae442f0e3ce11a6231455b180bfc66ab5d3eSean Callanan *p++ = (uint8_t)(ValueToWrite & 0xff); 168b38aae442f0e3ce11a6231455b180bfc66ab5d3eSean Callanan ValueToWrite >>= 8; 169b38aae442f0e3ce11a6231455b180bfc66ab5d3eSean Callanan } 1706f6f17197259edbb82cc9b0d800fe0e3cb8e201cJim Grosbach return false; 171b38aae442f0e3ce11a6231455b180bfc66ab5d3eSean Callanan } 172b38aae442f0e3ce11a6231455b180bfc66ab5d3eSean Callanan case macho::RIT_Difference: 173b38aae442f0e3ce11a6231455b180bfc66ab5d3eSean Callanan case macho::RIT_Generic_LocalDifference: 174b38aae442f0e3ce11a6231455b180bfc66ab5d3eSean Callanan case macho::RIT_Generic_PreboundLazyPointer: 175b38aae442f0e3ce11a6231455b180bfc66ab5d3eSean Callanan return Error("Relocation type not implemented yet!"); 176b38aae442f0e3ce11a6231455b180bfc66ab5d3eSean Callanan } 177b38aae442f0e3ce11a6231455b180bfc66ab5d3eSean Callanan} 178b38aae442f0e3ce11a6231455b180bfc66ab5d3eSean Callanan 1796d15e8717767af9a6a20c6ea456119c15c77dd00Eli Benderskybool RuntimeDyldMachO::resolveX86_64Relocation(uint8_t *LocalAddress, 1806d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky uint64_t FinalAddress, 1816d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky uint64_t Value, 1826d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky bool isPCRel, 1836d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky unsigned Type, 1846d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky unsigned Size, 1856d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky int64_t Addend) { 186cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev // If the relocation is PC-relative, the value to be encoded is the 187cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev // pointer difference. 188cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev if (isPCRel) 189cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev // FIXME: It seems this value needs to be adjusted by 4 for an effective PC 190cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev // address. Is that expected? Only for branches, perhaps? 19161dfa77fce2b6b6261e43334aec060129eac5c6cSean Callanan Value -= FinalAddress + 4; 192cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev 193cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev switch(Type) { 194cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev default: 195cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev llvm_unreachable("Invalid relocation type!"); 196652ca2fe0c8bd406222d064937adc28b281d7b89Jim Grosbach case macho::RIT_X86_64_Signed1: 197652ca2fe0c8bd406222d064937adc28b281d7b89Jim Grosbach case macho::RIT_X86_64_Signed2: 198652ca2fe0c8bd406222d064937adc28b281d7b89Jim Grosbach case macho::RIT_X86_64_Signed4: 199652ca2fe0c8bd406222d064937adc28b281d7b89Jim Grosbach case macho::RIT_X86_64_Signed: 200cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev case macho::RIT_X86_64_Unsigned: 201cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev case macho::RIT_X86_64_Branch: { 202652ca2fe0c8bd406222d064937adc28b281d7b89Jim Grosbach Value += Addend; 203cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev // Mask in the target value a byte at a time (we don't have an alignment 204cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev // guarantee for the target address, so this is safest). 20561dfa77fce2b6b6261e43334aec060129eac5c6cSean Callanan uint8_t *p = (uint8_t*)LocalAddress; 206cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev for (unsigned i = 0; i < Size; ++i) { 207cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev *p++ = (uint8_t)Value; 208cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev Value >>= 8; 209cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev } 210cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev return false; 211cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev } 212cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev case macho::RIT_X86_64_GOTLoad: 213cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev case macho::RIT_X86_64_GOT: 214cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev case macho::RIT_X86_64_Subtractor: 215cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev case macho::RIT_X86_64_TLV: 216cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev return Error("Relocation type not implemented yet!"); 217cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev } 218cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev} 219cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev 2206d15e8717767af9a6a20c6ea456119c15c77dd00Eli Benderskybool RuntimeDyldMachO::resolveARMRelocation(uint8_t *LocalAddress, 2216d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky uint64_t FinalAddress, 2226d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky uint64_t Value, 2236d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky bool isPCRel, 2246d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky unsigned Type, 2256d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky unsigned Size, 2266d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky int64_t Addend) { 227cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev // If the relocation is PC-relative, the value to be encoded is the 228cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev // pointer difference. 229cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev if (isPCRel) { 23061dfa77fce2b6b6261e43334aec060129eac5c6cSean Callanan Value -= FinalAddress; 231cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev // ARM PCRel relocations have an effective-PC offset of two instructions 232cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev // (four bytes in Thumb mode, 8 bytes in ARM mode). 233cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev // FIXME: For now, assume ARM mode. 234cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev Value -= 8; 235cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev } 236cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev 237cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev switch(Type) { 238cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev default: 239cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev llvm_unreachable("Invalid relocation type!"); 240cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev case macho::RIT_Vanilla: { 241cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev // Mask in the target value a byte at a time (we don't have an alignment 242cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev // guarantee for the target address, so this is safest). 24361dfa77fce2b6b6261e43334aec060129eac5c6cSean Callanan uint8_t *p = (uint8_t*)LocalAddress; 244cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev for (unsigned i = 0; i < Size; ++i) { 245cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev *p++ = (uint8_t)Value; 246cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev Value >>= 8; 247cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev } 248cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev break; 249cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev } 250cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev case macho::RIT_ARM_Branch24Bit: { 251cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev // Mask the value into the target address. We know instructions are 252cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev // 32-bit aligned, so we can do it all at once. 25361dfa77fce2b6b6261e43334aec060129eac5c6cSean Callanan uint32_t *p = (uint32_t*)LocalAddress; 254cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev // The low two bits of the value are not encoded. 255cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev Value >>= 2; 256cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev // Mask the value to 24 bits. 257cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev Value &= 0xffffff; 258cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev // FIXME: If the destination is a Thumb function (and the instruction 259cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev // is a non-predicated BL instruction), we need to change it to a BLX 260cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev // instruction instead. 261cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev 262cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev // Insert the value into the instruction. 263cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev *p = (*p & ~0xffffff) | Value; 264cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev break; 265cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev } 266cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev case macho::RIT_ARM_ThumbBranch22Bit: 267cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev case macho::RIT_ARM_ThumbBranch32Bit: 268cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev case macho::RIT_ARM_Half: 269cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev case macho::RIT_ARM_HalfDifference: 270cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev case macho::RIT_Pair: 271cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev case macho::RIT_Difference: 272cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev case macho::RIT_ARM_LocalDifference: 273cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev case macho::RIT_ARM_PreboundLazyPointer: 274cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev return Error("Relocation type not implemented yet!"); 275cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev } 276cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev return false; 277cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev} 278cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev 279efa91f6475f6e96552986104ab4857db46185a2aRafael Espindolavoid RuntimeDyldMachO::processRelocationRef(unsigned SectionID, 280ca0e73610056110e9a175c14dd82d6d616fd830fRafael Espindola RelocationRef RelI, 281689ff9c00f4f3dcf3491778bcdbda79e19e2285dPreston Gurd ObjectImage &Obj, 2820e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev ObjSectionToIDMap &ObjSectionToID, 283d98c9e918c9750d965c1efe9efcc9e13feacbe13Eli Bendersky const SymbolTableMap &Symbols, 2840e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev StubMap &Stubs) { 285efa91f6475f6e96552986104ab4857db46185a2aRafael Espindola const ObjectFile *OF = Obj.getObjectFile(); 286efa91f6475f6e96552986104ab4857db46185a2aRafael Espindola const MachOObjectFile *MachO = static_cast<const MachOObjectFile*>(OF); 287ca0e73610056110e9a175c14dd82d6d616fd830fRafael Espindola macho::RelocationEntry RE = MachO->getRelocation(RelI.getRawDataRefImpl()); 2880e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev 289efa91f6475f6e96552986104ab4857db46185a2aRafael Espindola uint32_t RelType = MachO->getAnyRelocationType(RE); 2900e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev RelocationValueRef Value; 291efa91f6475f6e96552986104ab4857db46185a2aRafael Espindola SectionEntry &Section = Sections[SectionID]; 2920e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev 293efa91f6475f6e96552986104ab4857db46185a2aRafael Espindola bool isExtern = MachO->getPlainRelocationExternal(RE); 29487b5017139e9d8ac9b046b3284a9cc68c76185d6Rafael Espindola bool IsPCRel = MachO->getAnyRelocationPCRel(RE); 29587b5017139e9d8ac9b046b3284a9cc68c76185d6Rafael Espindola unsigned Size = MachO->getAnyRelocationLength(RE); 2968e6e02a41bd21f8e919e812dbd7aa9ed5474bdbfRafael Espindola uint64_t Offset; 2978e6e02a41bd21f8e919e812dbd7aa9ed5474bdbfRafael Espindola RelI.getOffset(Offset); 298e87dadc44b1544c35e13cf48dfe167109929a944Rafael Espindola uint8_t *LocalAddress = Section.Address + Offset; 299e87dadc44b1544c35e13cf48dfe167109929a944Rafael Espindola unsigned NumBytes = 1 << Size; 300e87dadc44b1544c35e13cf48dfe167109929a944Rafael Espindola uint64_t Addend = 0; 301e87dadc44b1544c35e13cf48dfe167109929a944Rafael Espindola memcpy(&Addend, LocalAddress, NumBytes); 3028e6e02a41bd21f8e919e812dbd7aa9ed5474bdbfRafael Espindola 303e87dadc44b1544c35e13cf48dfe167109929a944Rafael Espindola if (isExtern) { 304c201e6eaf165c83f0092c43b371e509fa8eaf4ccEli Bendersky // Obtain the symbol name which is referenced in the relocation 3056c1202c459ffa6d693ad92fa84e43902bc780bcaRafael Espindola symbol_iterator Symbol = RelI.getSymbol(); 3060e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev StringRef TargetName; 3076c1202c459ffa6d693ad92fa84e43902bc780bcaRafael Espindola Symbol->getName(TargetName); 308c201e6eaf165c83f0092c43b371e509fa8eaf4ccEli Bendersky // First search for the symbol in the local symbol table 309d98c9e918c9750d965c1efe9efcc9e13feacbe13Eli Bendersky SymbolTableMap::const_iterator lsi = Symbols.find(TargetName.data()); 3100e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev if (lsi != Symbols.end()) { 3110e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev Value.SectionID = lsi->second.first; 3128e6e02a41bd21f8e919e812dbd7aa9ed5474bdbfRafael Espindola Value.Addend = lsi->second.second + Addend; 3130e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev } else { 314c201e6eaf165c83f0092c43b371e509fa8eaf4ccEli Bendersky // Search for the symbol in the global symbol table 315d98c9e918c9750d965c1efe9efcc9e13feacbe13Eli Bendersky SymbolTableMap::const_iterator gsi = GlobalSymbolTable.find(TargetName.data()); 316d98c9e918c9750d965c1efe9efcc9e13feacbe13Eli Bendersky if (gsi != GlobalSymbolTable.end()) { 3170e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev Value.SectionID = gsi->second.first; 3188e6e02a41bd21f8e919e812dbd7aa9ed5474bdbfRafael Espindola Value.Addend = gsi->second.second + Addend; 3198e6e02a41bd21f8e919e812dbd7aa9ed5474bdbfRafael Espindola } else { 3200e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev Value.SymbolName = TargetName.data(); 3218e6e02a41bd21f8e919e812dbd7aa9ed5474bdbfRafael Espindola Value.Addend = Addend; 3228e6e02a41bd21f8e919e812dbd7aa9ed5474bdbfRafael Espindola } 323cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev } 3240e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev } else { 325e87dadc44b1544c35e13cf48dfe167109929a944Rafael Espindola SectionRef Sec = MachO->getRelocationSection(RE); 326e87dadc44b1544c35e13cf48dfe167109929a944Rafael Espindola Value.SectionID = findOrEmitSection(Obj, Sec, true, ObjSectionToID); 327e87dadc44b1544c35e13cf48dfe167109929a944Rafael Espindola uint64_t Addr; 328e87dadc44b1544c35e13cf48dfe167109929a944Rafael Espindola Sec.getAddress(Addr); 329e87dadc44b1544c35e13cf48dfe167109929a944Rafael Espindola Value.Addend = Addend - Addr; 330288967dfac246c8e35dc4f85afb667e74d1d26a8Bill Wendling } 331288967dfac246c8e35dc4f85afb667e74d1d26a8Bill Wendling 332a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola if (Arch == Triple::x86_64 && RelType == macho::RIT_X86_64_GOT) { 333a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola assert(IsPCRel); 334a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola assert(Size == 2); 335a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola StubMap::const_iterator i = Stubs.find(Value); 336a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola uint8_t *Addr; 337a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola if (i != Stubs.end()) { 338a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola Addr = Section.Address + i->second; 339a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola } else { 340a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola Stubs[Value] = Section.StubOffset; 341a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola uint8_t *GOTEntry = Section.Address + Section.StubOffset; 342a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola RelocationEntry RE(SectionID, Section.StubOffset, 343a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola macho::RIT_X86_64_Unsigned, Value.Addend - 4, false, 344a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola 3); 345a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola if (Value.SymbolName) 346a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola addRelocationForSymbol(RE, Value.SymbolName); 347a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola else 348a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola addRelocationForSection(RE, Value.SectionID); 349a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola Section.StubOffset += 8; 350a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola Addr = GOTEntry; 351a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola } 352a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola resolveRelocation(Section, Offset, (uint64_t)Addr, 353a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola macho::RIT_X86_64_Unsigned, 4, true, 2); 354a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola } else if (Arch == Triple::arm && 355a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola (RelType & 0xf) == macho::RIT_ARM_Branch24Bit) { 3560e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev // This is an ARM branch relocation, need to use a stub function. 3570e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev 3580e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev // Look up for existing stub. 3590e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev StubMap::const_iterator i = Stubs.find(Value); 3600e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev if (i != Stubs.end()) 361efa91f6475f6e96552986104ab4857db46185a2aRafael Espindola resolveRelocation(Section, Offset, 3620e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev (uint64_t)Section.Address + i->second, 36387b5017139e9d8ac9b046b3284a9cc68c76185d6Rafael Espindola RelType, 0, IsPCRel, Size); 3640e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev else { 3650e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev // Create a new stub function. 3660e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev Stubs[Value] = Section.StubOffset; 3670e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev uint8_t *StubTargetAddr = createStubFunction(Section.Address + 3680e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev Section.StubOffset); 369efa91f6475f6e96552986104ab4857db46185a2aRafael Espindola RelocationEntry RE(SectionID, StubTargetAddr - Section.Address, 370c201e6eaf165c83f0092c43b371e509fa8eaf4ccEli Bendersky macho::RIT_Vanilla, Value.Addend); 371c201e6eaf165c83f0092c43b371e509fa8eaf4ccEli Bendersky if (Value.SymbolName) 372c201e6eaf165c83f0092c43b371e509fa8eaf4ccEli Bendersky addRelocationForSymbol(RE, Value.SymbolName); 373c201e6eaf165c83f0092c43b371e509fa8eaf4ccEli Bendersky else 374c201e6eaf165c83f0092c43b371e509fa8eaf4ccEli Bendersky addRelocationForSection(RE, Value.SectionID); 375efa91f6475f6e96552986104ab4857db46185a2aRafael Espindola resolveRelocation(Section, Offset, 3760e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev (uint64_t)Section.Address + Section.StubOffset, 37787b5017139e9d8ac9b046b3284a9cc68c76185d6Rafael Espindola RelType, 0, IsPCRel, Size); 3780e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev Section.StubOffset += getMaxStubSize(); 3790e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev } 380c201e6eaf165c83f0092c43b371e509fa8eaf4ccEli Bendersky } else { 38187b5017139e9d8ac9b046b3284a9cc68c76185d6Rafael Espindola RelocationEntry RE(SectionID, Offset, RelType, Value.Addend, 38287b5017139e9d8ac9b046b3284a9cc68c76185d6Rafael Espindola IsPCRel, Size); 383c201e6eaf165c83f0092c43b371e509fa8eaf4ccEli Bendersky if (Value.SymbolName) 384c201e6eaf165c83f0092c43b371e509fa8eaf4ccEli Bendersky addRelocationForSymbol(RE, Value.SymbolName); 385c201e6eaf165c83f0092c43b371e509fa8eaf4ccEli Bendersky else 386c201e6eaf165c83f0092c43b371e509fa8eaf4ccEli Bendersky addRelocationForSection(RE, Value.SectionID); 387c201e6eaf165c83f0092c43b371e509fa8eaf4ccEli Bendersky } 388cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev} 389cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev 390cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev 3916d15e8717767af9a6a20c6ea456119c15c77dd00Eli Benderskybool RuntimeDyldMachO::isCompatibleFormat( 3923f23cef24fc9200def464bd4bce820678b5715deAndrew Kaylor const ObjectBuffer *InputBuffer) const { 3933f23cef24fc9200def464bd4bce820678b5715deAndrew Kaylor if (InputBuffer->getBufferSize() < 4) 3943f23cef24fc9200def464bd4bce820678b5715deAndrew Kaylor return false; 3953f23cef24fc9200def464bd4bce820678b5715deAndrew Kaylor StringRef Magic(InputBuffer->getBufferStart(), 4); 396cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev if (Magic == "\xFE\xED\xFA\xCE") return true; 397cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev if (Magic == "\xCE\xFA\xED\xFE") return true; 398cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev if (Magic == "\xFE\xED\xFA\xCF") return true; 399cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev if (Magic == "\xCF\xFA\xED\xFE") return true; 400cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev return false; 401cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev} 402cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev 403cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev} // end namespace llvm 404