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 &ObjImg, 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 ObjSectionToIDMap::iterator i, e; 187 188 for (i = SectionMap.begin(), e = SectionMap.end(); i != e; ++i) { 189 const SectionRef &Section = i->first; 190 StringRef Name; 191 Section.getName(Name); 192 if (Name == "__eh_frame") 193 EHFrameSID = i->second; 194 else if (Name == "__text") 195 TextSID = i->second; 196 else if (Name == "__gcc_except_tab") 197 ExceptTabSID = i->second; 198 else 199 impl().finalizeSection(ObjImg, i->second, Section); 200 } 201 UnregisteredEHFrameSections.push_back( 202 EHFrameRelatedSections(EHFrameSID, TextSID, ExceptTabSID)); 203 } 204 205 template <typename Impl> 206 unsigned char *RuntimeDyldMachOCRTPBase<Impl>::processFDE(unsigned char *P, 207 int64_t DeltaForText, 208 int64_t DeltaForEH) { 209 typedef typename Impl::TargetPtrT TargetPtrT; 210 211 DEBUG(dbgs() << "Processing FDE: Delta for text: " << DeltaForText 212 << ", Delta for EH: " << DeltaForEH << "\n"); 213 uint32_t Length = readBytesUnaligned(P, 4); 214 P += 4; 215 unsigned char *Ret = P + Length; 216 uint32_t Offset = readBytesUnaligned(P, 4); 217 if (Offset == 0) // is a CIE 218 return Ret; 219 220 P += 4; 221 TargetPtrT FDELocation = readBytesUnaligned(P, sizeof(TargetPtrT)); 222 TargetPtrT NewLocation = FDELocation - DeltaForText; 223 writeBytesUnaligned(NewLocation, P, sizeof(TargetPtrT)); 224 225 P += sizeof(TargetPtrT); 226 227 // Skip the FDE address range 228 P += sizeof(TargetPtrT); 229 230 uint8_t Augmentationsize = *P; 231 P += 1; 232 if (Augmentationsize != 0) { 233 TargetPtrT LSDA = readBytesUnaligned(P, sizeof(TargetPtrT)); 234 TargetPtrT NewLSDA = LSDA - DeltaForEH; 235 writeBytesUnaligned(NewLSDA, P, sizeof(TargetPtrT)); 236 } 237 238 return Ret; 239 } 240 241 static int64_t computeDelta(SectionEntry *A, SectionEntry *B) { 242 int64_t ObjDistance = A->ObjAddress - B->ObjAddress; 243 int64_t MemDistance = A->LoadAddress - B->LoadAddress; 244 return ObjDistance - MemDistance; 245 } 246 247 template <typename Impl> 248 void RuntimeDyldMachOCRTPBase<Impl>::registerEHFrames() { 249 250 if (!MemMgr) 251 return; 252 for (int i = 0, e = UnregisteredEHFrameSections.size(); i != e; ++i) { 253 EHFrameRelatedSections &SectionInfo = UnregisteredEHFrameSections[i]; 254 if (SectionInfo.EHFrameSID == RTDYLD_INVALID_SECTION_ID || 255 SectionInfo.TextSID == RTDYLD_INVALID_SECTION_ID) 256 continue; 257 SectionEntry *Text = &Sections[SectionInfo.TextSID]; 258 SectionEntry *EHFrame = &Sections[SectionInfo.EHFrameSID]; 259 SectionEntry *ExceptTab = nullptr; 260 if (SectionInfo.ExceptTabSID != RTDYLD_INVALID_SECTION_ID) 261 ExceptTab = &Sections[SectionInfo.ExceptTabSID]; 262 263 int64_t DeltaForText = computeDelta(Text, EHFrame); 264 int64_t DeltaForEH = 0; 265 if (ExceptTab) 266 DeltaForEH = computeDelta(ExceptTab, EHFrame); 267 268 unsigned char *P = EHFrame->Address; 269 unsigned char *End = P + EHFrame->Size; 270 do { 271 P = processFDE(P, DeltaForText, DeltaForEH); 272 } while (P != End); 273 274 MemMgr->registerEHFrames(EHFrame->Address, EHFrame->LoadAddress, 275 EHFrame->Size); 276 } 277 UnregisteredEHFrameSections.clear(); 278 } 279 280 std::unique_ptr<RuntimeDyldMachO> 281 RuntimeDyldMachO::create(Triple::ArchType Arch, RTDyldMemoryManager *MM) { 282 switch (Arch) { 283 default: 284 llvm_unreachable("Unsupported target for RuntimeDyldMachO."); 285 break; 286 case Triple::arm: return make_unique<RuntimeDyldMachOARM>(MM); 287 case Triple::aarch64: return make_unique<RuntimeDyldMachOAArch64>(MM); 288 case Triple::x86: return make_unique<RuntimeDyldMachOI386>(MM); 289 case Triple::x86_64: return make_unique<RuntimeDyldMachOX86_64>(MM); 290 } 291 } 292 293 std::unique_ptr<RuntimeDyld::LoadedObjectInfo> 294 RuntimeDyldMachO::loadObject(const object::ObjectFile &O) { 295 unsigned SectionStartIdx, SectionEndIdx; 296 std::tie(SectionStartIdx, SectionEndIdx) = loadObjectImpl(O); 297 return llvm::make_unique<LoadedMachOObjectInfo>(*this, SectionStartIdx, 298 SectionEndIdx); 299 } 300 301 } // end namespace llvm 302