1 //===-- RuntimeDyldMachO.cpp - Run-time dynamic linker for MC-JIT -*- C++ -*-=// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // Implementation of the MC-JIT runtime dynamic linker. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "RuntimeDyldMachO.h" 15 #include "llvm/ADT/STLExtras.h" 16 #include "llvm/ADT/StringRef.h" 17 18 #include "Targets/RuntimeDyldMachOARM.h" 19 #include "Targets/RuntimeDyldMachOAArch64.h" 20 #include "Targets/RuntimeDyldMachOI386.h" 21 #include "Targets/RuntimeDyldMachOX86_64.h" 22 23 using namespace llvm; 24 using namespace llvm::object; 25 26 #define DEBUG_TYPE "dyld" 27 28 namespace llvm { 29 30 uint64_t RuntimeDyldMachO::decodeAddend(uint8_t *LocalAddress, unsigned NumBytes, 31 uint32_t RelType) const { 32 uint64_t Addend = 0; 33 memcpy(&Addend, LocalAddress, NumBytes); 34 return Addend; 35 } 36 37 RelocationValueRef RuntimeDyldMachO::getRelocationValueRef( 38 ObjectImage &ObjImg, const relocation_iterator &RI, 39 const RelocationEntry &RE, ObjSectionToIDMap &ObjSectionToID, 40 const SymbolTableMap &Symbols) { 41 42 const MachOObjectFile &Obj = 43 static_cast<const MachOObjectFile &>(*ObjImg.getObjectFile()); 44 MachO::any_relocation_info RelInfo = 45 Obj.getRelocation(RI->getRawDataRefImpl()); 46 RelocationValueRef Value; 47 48 bool IsExternal = Obj.getPlainRelocationExternal(RelInfo); 49 if (IsExternal) { 50 symbol_iterator Symbol = RI->getSymbol(); 51 StringRef TargetName; 52 Symbol->getName(TargetName); 53 SymbolTableMap::const_iterator SI = Symbols.find(TargetName.data()); 54 if (SI != Symbols.end()) { 55 Value.SectionID = SI->second.first; 56 Value.Addend = SI->second.second + RE.Addend; 57 } else { 58 SI = GlobalSymbolTable.find(TargetName.data()); 59 if (SI != GlobalSymbolTable.end()) { 60 Value.SectionID = SI->second.first; 61 Value.Addend = SI->second.second + RE.Addend; 62 } else { 63 Value.SymbolName = TargetName.data(); 64 Value.Addend = RE.Addend; 65 } 66 } 67 } else { 68 SectionRef Sec = Obj.getRelocationSection(RelInfo); 69 bool IsCode = false; 70 Sec.isText(IsCode); 71 Value.SectionID = findOrEmitSection(ObjImg, Sec, IsCode, ObjSectionToID); 72 uint64_t Addr; 73 Sec.getAddress(Addr); 74 Value.Addend = RE.Addend - Addr; 75 } 76 77 return Value; 78 } 79 80 void RuntimeDyldMachO::makeValueAddendPCRel(RelocationValueRef &Value, 81 ObjectImage &ObjImg, 82 const relocation_iterator &RI) { 83 const MachOObjectFile &Obj = 84 static_cast<const MachOObjectFile &>(*ObjImg.getObjectFile()); 85 MachO::any_relocation_info RelInfo = 86 Obj.getRelocation(RI->getRawDataRefImpl()); 87 88 bool IsPCRel = Obj.getAnyRelocationPCRel(RelInfo); 89 if (IsPCRel) { 90 uint64_t RelocAddr = 0; 91 RI->getAddress(RelocAddr); 92 unsigned RelocSize = Obj.getAnyRelocationLength(RelInfo); 93 Value.Addend += RelocAddr + (1ULL << RelocSize); 94 } 95 } 96 97 void RuntimeDyldMachO::dumpRelocationToResolve(const RelocationEntry &RE, 98 uint64_t Value) const { 99 const SectionEntry &Section = Sections[RE.SectionID]; 100 uint8_t *LocalAddress = Section.Address + RE.Offset; 101 uint64_t FinalAddress = Section.LoadAddress + RE.Offset; 102 103 dbgs() << "resolveRelocation Section: " << RE.SectionID 104 << " LocalAddress: " << format("%p", LocalAddress) 105 << " FinalAddress: " << format("%p", FinalAddress) 106 << " Value: " << format("%p", Value) << " Addend: " << RE.Addend 107 << " isPCRel: " << RE.IsPCRel << " MachoType: " << RE.RelType 108 << " Size: " << (1 << RE.Size) << "\n"; 109 } 110 111 bool RuntimeDyldMachO::writeBytesUnaligned(uint8_t *Addr, uint64_t Value, 112 unsigned Size) { 113 for (unsigned i = 0; i < Size; ++i) { 114 *Addr++ = (uint8_t)Value; 115 Value >>= 8; 116 } 117 118 return false; 119 } 120 121 bool 122 RuntimeDyldMachO::isCompatibleFormat(const ObjectBuffer *InputBuffer) const { 123 if (InputBuffer->getBufferSize() < 4) 124 return false; 125 StringRef Magic(InputBuffer->getBufferStart(), 4); 126 if (Magic == "\xFE\xED\xFA\xCE") 127 return true; 128 if (Magic == "\xCE\xFA\xED\xFE") 129 return true; 130 if (Magic == "\xFE\xED\xFA\xCF") 131 return true; 132 if (Magic == "\xCF\xFA\xED\xFE") 133 return true; 134 return false; 135 } 136 137 bool RuntimeDyldMachO::isCompatibleFile(const object::ObjectFile *Obj) const { 138 return Obj->isMachO(); 139 } 140 141 static unsigned char *processFDE(unsigned char *P, intptr_t DeltaForText, 142 intptr_t DeltaForEH) { 143 DEBUG(dbgs() << "Processing FDE: Delta for text: " << DeltaForText 144 << ", Delta for EH: " << DeltaForEH << "\n"); 145 uint32_t Length = *((uint32_t *)P); 146 P += 4; 147 unsigned char *Ret = P + Length; 148 uint32_t Offset = *((uint32_t *)P); 149 if (Offset == 0) // is a CIE 150 return Ret; 151 152 P += 4; 153 intptr_t FDELocation = *((intptr_t *)P); 154 intptr_t NewLocation = FDELocation - DeltaForText; 155 *((intptr_t *)P) = NewLocation; 156 P += sizeof(intptr_t); 157 158 // Skip the FDE address range 159 P += sizeof(intptr_t); 160 161 uint8_t Augmentationsize = *P; 162 P += 1; 163 if (Augmentationsize != 0) { 164 intptr_t LSDA = *((intptr_t *)P); 165 intptr_t NewLSDA = LSDA - DeltaForEH; 166 *((intptr_t *)P) = NewLSDA; 167 } 168 169 return Ret; 170 } 171 172 static intptr_t computeDelta(SectionEntry *A, SectionEntry *B) { 173 intptr_t ObjDistance = A->ObjAddress - B->ObjAddress; 174 intptr_t MemDistance = A->LoadAddress - B->LoadAddress; 175 return ObjDistance - MemDistance; 176 } 177 178 void RuntimeDyldMachO::registerEHFrames() { 179 180 if (!MemMgr) 181 return; 182 for (int i = 0, e = UnregisteredEHFrameSections.size(); i != e; ++i) { 183 EHFrameRelatedSections &SectionInfo = UnregisteredEHFrameSections[i]; 184 if (SectionInfo.EHFrameSID == RTDYLD_INVALID_SECTION_ID || 185 SectionInfo.TextSID == RTDYLD_INVALID_SECTION_ID) 186 continue; 187 SectionEntry *Text = &Sections[SectionInfo.TextSID]; 188 SectionEntry *EHFrame = &Sections[SectionInfo.EHFrameSID]; 189 SectionEntry *ExceptTab = nullptr; 190 if (SectionInfo.ExceptTabSID != RTDYLD_INVALID_SECTION_ID) 191 ExceptTab = &Sections[SectionInfo.ExceptTabSID]; 192 193 intptr_t DeltaForText = computeDelta(Text, EHFrame); 194 intptr_t DeltaForEH = 0; 195 if (ExceptTab) 196 DeltaForEH = computeDelta(ExceptTab, EHFrame); 197 198 unsigned char *P = EHFrame->Address; 199 unsigned char *End = P + EHFrame->Size; 200 do { 201 P = processFDE(P, DeltaForText, DeltaForEH); 202 } while (P != End); 203 204 MemMgr->registerEHFrames(EHFrame->Address, EHFrame->LoadAddress, 205 EHFrame->Size); 206 } 207 UnregisteredEHFrameSections.clear(); 208 } 209 210 std::unique_ptr<RuntimeDyldMachO> 211 llvm::RuntimeDyldMachO::create(Triple::ArchType Arch, RTDyldMemoryManager *MM) { 212 switch (Arch) { 213 default: 214 llvm_unreachable("Unsupported target for RuntimeDyldMachO."); 215 break; 216 case Triple::arm: return make_unique<RuntimeDyldMachOARM>(MM); 217 case Triple::arm64: return make_unique<RuntimeDyldMachOAArch64>(MM); 218 case Triple::x86: return make_unique<RuntimeDyldMachOI386>(MM); 219 case Triple::x86_64: return make_unique<RuntimeDyldMachOX86_64>(MM); 220 } 221 } 222 223 } // end namespace llvm 224