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