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