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