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