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 "Targets/RuntimeDyldMachOAArch64.h" 16 #include "Targets/RuntimeDyldMachOARM.h" 17 #include "Targets/RuntimeDyldMachOI386.h" 18 #include "Targets/RuntimeDyldMachOX86_64.h" 19 #include "llvm/ADT/STLExtras.h" 20 #include "llvm/ADT/StringRef.h" 21 22 using namespace llvm; 23 using namespace llvm::object; 24 25 #define DEBUG_TYPE "dyld" 26 27 namespace { 28 29 class LoadedMachOObjectInfo 30 : public RuntimeDyld::LoadedObjectInfoHelper<LoadedMachOObjectInfo> { 31 public: 32 LoadedMachOObjectInfo(RuntimeDyldImpl &RTDyld, unsigned BeginIdx, 33 unsigned EndIdx) 34 : LoadedObjectInfoHelper(RTDyld, BeginIdx, EndIdx) {} 35 36 OwningBinary<ObjectFile> 37 getObjectForDebug(const ObjectFile &Obj) const override { 38 return OwningBinary<ObjectFile>(); 39 } 40 }; 41 42 } 43 44 namespace llvm { 45 46 int64_t RuntimeDyldMachO::memcpyAddend(const RelocationEntry &RE) const { 47 unsigned NumBytes = 1 << RE.Size; 48 uint8_t *Src = Sections[RE.SectionID].Address + RE.Offset; 49 50 return static_cast<int64_t>(readBytesUnaligned(Src, NumBytes)); 51 } 52 53 RelocationValueRef RuntimeDyldMachO::getRelocationValueRef( 54 const ObjectFile &BaseTObj, const relocation_iterator &RI, 55 const RelocationEntry &RE, ObjSectionToIDMap &ObjSectionToID) { 56 57 const MachOObjectFile &Obj = 58 static_cast<const MachOObjectFile &>(BaseTObj); 59 MachO::any_relocation_info RelInfo = 60 Obj.getRelocation(RI->getRawDataRefImpl()); 61 RelocationValueRef Value; 62 63 bool IsExternal = Obj.getPlainRelocationExternal(RelInfo); 64 if (IsExternal) { 65 symbol_iterator Symbol = RI->getSymbol(); 66 ErrorOr<StringRef> TargetNameOrErr = Symbol->getName(); 67 if (std::error_code EC = TargetNameOrErr.getError()) 68 report_fatal_error(EC.message()); 69 StringRef TargetName = *TargetNameOrErr; 70 RTDyldSymbolTable::const_iterator SI = 71 GlobalSymbolTable.find(TargetName.data()); 72 if (SI != GlobalSymbolTable.end()) { 73 const auto &SymInfo = SI->second; 74 Value.SectionID = SymInfo.getSectionID(); 75 Value.Offset = SymInfo.getOffset() + RE.Addend; 76 } else { 77 Value.SymbolName = TargetName.data(); 78 Value.Offset = RE.Addend; 79 } 80 } else { 81 SectionRef Sec = Obj.getAnyRelocationSection(RelInfo); 82 bool IsCode = Sec.isText(); 83 Value.SectionID = findOrEmitSection(Obj, Sec, IsCode, ObjSectionToID); 84 uint64_t Addr = Sec.getAddress(); 85 Value.Offset = RE.Addend - Addr; 86 } 87 88 return Value; 89 } 90 91 void RuntimeDyldMachO::makeValueAddendPCRel(RelocationValueRef &Value, 92 const relocation_iterator &RI, 93 unsigned OffsetToNextPC) { 94 auto &O = *cast<MachOObjectFile>(RI->getObject()); 95 section_iterator SecI = O.getRelocationRelocatedSection(RI); 96 Value.Offset += RI->getOffset() + OffsetToNextPC + SecI->getAddress(); 97 } 98 99 void RuntimeDyldMachO::dumpRelocationToResolve(const RelocationEntry &RE, 100 uint64_t Value) const { 101 const SectionEntry &Section = Sections[RE.SectionID]; 102 uint8_t *LocalAddress = Section.Address + RE.Offset; 103 uint64_t FinalAddress = Section.LoadAddress + RE.Offset; 104 105 dbgs() << "resolveRelocation Section: " << RE.SectionID 106 << " LocalAddress: " << format("%p", LocalAddress) 107 << " FinalAddress: " << format("0x%016" PRIx64, FinalAddress) 108 << " Value: " << format("0x%016" PRIx64, Value) << " Addend: " << RE.Addend 109 << " isPCRel: " << RE.IsPCRel << " MachoType: " << RE.RelType 110 << " Size: " << (1 << RE.Size) << "\n"; 111 } 112 113 section_iterator 114 RuntimeDyldMachO::getSectionByAddress(const MachOObjectFile &Obj, 115 uint64_t Addr) { 116 section_iterator SI = Obj.section_begin(); 117 section_iterator SE = Obj.section_end(); 118 119 for (; SI != SE; ++SI) { 120 uint64_t SAddr = SI->getAddress(); 121 uint64_t SSize = SI->getSize(); 122 if ((Addr >= SAddr) && (Addr < SAddr + SSize)) 123 return SI; 124 } 125 126 return SE; 127 } 128 129 130 // Populate __pointers section. 131 void RuntimeDyldMachO::populateIndirectSymbolPointersSection( 132 const MachOObjectFile &Obj, 133 const SectionRef &PTSection, 134 unsigned PTSectionID) { 135 assert(!Obj.is64Bit() && 136 "Pointer table section not supported in 64-bit MachO."); 137 138 MachO::dysymtab_command DySymTabCmd = Obj.getDysymtabLoadCommand(); 139 MachO::section Sec32 = Obj.getSection(PTSection.getRawDataRefImpl()); 140 uint32_t PTSectionSize = Sec32.size; 141 unsigned FirstIndirectSymbol = Sec32.reserved1; 142 const unsigned PTEntrySize = 4; 143 unsigned NumPTEntries = PTSectionSize / PTEntrySize; 144 unsigned PTEntryOffset = 0; 145 146 assert((PTSectionSize % PTEntrySize) == 0 && 147 "Pointers section does not contain a whole number of stubs?"); 148 149 DEBUG(dbgs() << "Populating pointer table section " 150 << Sections[PTSectionID].Name 151 << ", Section ID " << PTSectionID << ", " 152 << NumPTEntries << " entries, " << PTEntrySize 153 << " bytes each:\n"); 154 155 for (unsigned i = 0; i < NumPTEntries; ++i) { 156 unsigned SymbolIndex = 157 Obj.getIndirectSymbolTableEntry(DySymTabCmd, FirstIndirectSymbol + i); 158 symbol_iterator SI = Obj.getSymbolByIndex(SymbolIndex); 159 ErrorOr<StringRef> IndirectSymbolNameOrErr = SI->getName(); 160 if (std::error_code EC = IndirectSymbolNameOrErr.getError()) 161 report_fatal_error(EC.message()); 162 StringRef IndirectSymbolName = *IndirectSymbolNameOrErr; 163 DEBUG(dbgs() << " " << IndirectSymbolName << ": index " << SymbolIndex 164 << ", PT offset: " << PTEntryOffset << "\n"); 165 RelocationEntry RE(PTSectionID, PTEntryOffset, 166 MachO::GENERIC_RELOC_VANILLA, 0, false, 2); 167 addRelocationForSymbol(RE, IndirectSymbolName); 168 PTEntryOffset += PTEntrySize; 169 } 170 } 171 172 bool RuntimeDyldMachO::isCompatibleFile(const object::ObjectFile &Obj) const { 173 return Obj.isMachO(); 174 } 175 176 template <typename Impl> 177 void RuntimeDyldMachOCRTPBase<Impl>::finalizeLoad(const ObjectFile &Obj, 178 ObjSectionToIDMap &SectionMap) { 179 unsigned EHFrameSID = RTDYLD_INVALID_SECTION_ID; 180 unsigned TextSID = RTDYLD_INVALID_SECTION_ID; 181 unsigned ExceptTabSID = RTDYLD_INVALID_SECTION_ID; 182 183 for (const auto &Section : Obj.sections()) { 184 StringRef Name; 185 Section.getName(Name); 186 187 // Force emission of the __text, __eh_frame, and __gcc_except_tab sections 188 // if they're present. Otherwise call down to the impl to handle other 189 // sections that have already been emitted. 190 if (Name == "__text") 191 TextSID = findOrEmitSection(Obj, Section, true, SectionMap); 192 else if (Name == "__eh_frame") 193 EHFrameSID = findOrEmitSection(Obj, Section, false, SectionMap); 194 else if (Name == "__gcc_except_tab") 195 ExceptTabSID = findOrEmitSection(Obj, Section, true, SectionMap); 196 else { 197 auto I = SectionMap.find(Section); 198 if (I != SectionMap.end()) 199 impl().finalizeSection(Obj, I->second, Section); 200 } 201 } 202 UnregisteredEHFrameSections.push_back( 203 EHFrameRelatedSections(EHFrameSID, TextSID, ExceptTabSID)); 204 } 205 206 template <typename Impl> 207 unsigned char *RuntimeDyldMachOCRTPBase<Impl>::processFDE(unsigned char *P, 208 int64_t DeltaForText, 209 int64_t DeltaForEH) { 210 typedef typename Impl::TargetPtrT TargetPtrT; 211 212 DEBUG(dbgs() << "Processing FDE: Delta for text: " << DeltaForText 213 << ", Delta for EH: " << DeltaForEH << "\n"); 214 uint32_t Length = readBytesUnaligned(P, 4); 215 P += 4; 216 unsigned char *Ret = P + Length; 217 uint32_t Offset = readBytesUnaligned(P, 4); 218 if (Offset == 0) // is a CIE 219 return Ret; 220 221 P += 4; 222 TargetPtrT FDELocation = readBytesUnaligned(P, sizeof(TargetPtrT)); 223 TargetPtrT NewLocation = FDELocation - DeltaForText; 224 writeBytesUnaligned(NewLocation, P, sizeof(TargetPtrT)); 225 226 P += sizeof(TargetPtrT); 227 228 // Skip the FDE address range 229 P += sizeof(TargetPtrT); 230 231 uint8_t Augmentationsize = *P; 232 P += 1; 233 if (Augmentationsize != 0) { 234 TargetPtrT LSDA = readBytesUnaligned(P, sizeof(TargetPtrT)); 235 TargetPtrT NewLSDA = LSDA - DeltaForEH; 236 writeBytesUnaligned(NewLSDA, P, sizeof(TargetPtrT)); 237 } 238 239 return Ret; 240 } 241 242 static int64_t computeDelta(SectionEntry *A, SectionEntry *B) { 243 int64_t ObjDistance = 244 static_cast<int64_t>(A->ObjAddress) - static_cast<int64_t>(B->ObjAddress); 245 int64_t MemDistance = A->LoadAddress - B->LoadAddress; 246 return ObjDistance - MemDistance; 247 } 248 249 template <typename Impl> 250 void RuntimeDyldMachOCRTPBase<Impl>::registerEHFrames() { 251 252 for (int i = 0, e = UnregisteredEHFrameSections.size(); i != e; ++i) { 253 EHFrameRelatedSections &SectionInfo = UnregisteredEHFrameSections[i]; 254 if (SectionInfo.EHFrameSID == RTDYLD_INVALID_SECTION_ID || 255 SectionInfo.TextSID == RTDYLD_INVALID_SECTION_ID) 256 continue; 257 SectionEntry *Text = &Sections[SectionInfo.TextSID]; 258 SectionEntry *EHFrame = &Sections[SectionInfo.EHFrameSID]; 259 SectionEntry *ExceptTab = nullptr; 260 if (SectionInfo.ExceptTabSID != RTDYLD_INVALID_SECTION_ID) 261 ExceptTab = &Sections[SectionInfo.ExceptTabSID]; 262 263 int64_t DeltaForText = computeDelta(Text, EHFrame); 264 int64_t DeltaForEH = 0; 265 if (ExceptTab) 266 DeltaForEH = computeDelta(ExceptTab, EHFrame); 267 268 unsigned char *P = EHFrame->Address; 269 unsigned char *End = P + EHFrame->Size; 270 do { 271 P = processFDE(P, DeltaForText, DeltaForEH); 272 } while (P != End); 273 274 MemMgr.registerEHFrames(EHFrame->Address, EHFrame->LoadAddress, 275 EHFrame->Size); 276 } 277 UnregisteredEHFrameSections.clear(); 278 } 279 280 std::unique_ptr<RuntimeDyldMachO> 281 RuntimeDyldMachO::create(Triple::ArchType Arch, 282 RuntimeDyld::MemoryManager &MemMgr, 283 RuntimeDyld::SymbolResolver &Resolver) { 284 switch (Arch) { 285 default: 286 llvm_unreachable("Unsupported target for RuntimeDyldMachO."); 287 break; 288 case Triple::arm: 289 return make_unique<RuntimeDyldMachOARM>(MemMgr, Resolver); 290 case Triple::aarch64: 291 return make_unique<RuntimeDyldMachOAArch64>(MemMgr, Resolver); 292 case Triple::x86: 293 return make_unique<RuntimeDyldMachOI386>(MemMgr, Resolver); 294 case Triple::x86_64: 295 return make_unique<RuntimeDyldMachOX86_64>(MemMgr, Resolver); 296 } 297 } 298 299 std::unique_ptr<RuntimeDyld::LoadedObjectInfo> 300 RuntimeDyldMachO::loadObject(const object::ObjectFile &O) { 301 unsigned SectionStartIdx, SectionEndIdx; 302 std::tie(SectionStartIdx, SectionEndIdx) = loadObjectImpl(O); 303 return llvm::make_unique<LoadedMachOObjectInfo>(*this, SectionStartIdx, 304 SectionEndIdx); 305 } 306 307 } // end namespace llvm 308