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