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