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