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