LLVM API Documentation
00001 //===-- RuntimeDyldMachO.cpp - Run-time dynamic linker for MC-JIT -*- C++ -*-=// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // Implementation of the MC-JIT runtime dynamic linker. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #include "RuntimeDyldMachO.h" 00015 #include "llvm/ADT/STLExtras.h" 00016 #include "llvm/ADT/StringRef.h" 00017 00018 #include "Targets/RuntimeDyldMachOARM.h" 00019 #include "Targets/RuntimeDyldMachOAArch64.h" 00020 #include "Targets/RuntimeDyldMachOI386.h" 00021 #include "Targets/RuntimeDyldMachOX86_64.h" 00022 00023 using namespace llvm; 00024 using namespace llvm::object; 00025 00026 #define DEBUG_TYPE "dyld" 00027 00028 namespace llvm { 00029 00030 int64_t RuntimeDyldMachO::memcpyAddend(const RelocationEntry &RE) const { 00031 unsigned NumBytes = 1 << RE.Size; 00032 uint8_t *Src = Sections[RE.SectionID].Address + RE.Offset; 00033 00034 return static_cast<int64_t>(readBytesUnaligned(Src, NumBytes)); 00035 } 00036 00037 RelocationValueRef RuntimeDyldMachO::getRelocationValueRef( 00038 ObjectImage &ObjImg, const relocation_iterator &RI, 00039 const RelocationEntry &RE, ObjSectionToIDMap &ObjSectionToID, 00040 const SymbolTableMap &Symbols) { 00041 00042 const MachOObjectFile &Obj = 00043 static_cast<const MachOObjectFile &>(*ObjImg.getObjectFile()); 00044 MachO::any_relocation_info RelInfo = 00045 Obj.getRelocation(RI->getRawDataRefImpl()); 00046 RelocationValueRef Value; 00047 00048 bool IsExternal = Obj.getPlainRelocationExternal(RelInfo); 00049 if (IsExternal) { 00050 symbol_iterator Symbol = RI->getSymbol(); 00051 StringRef TargetName; 00052 Symbol->getName(TargetName); 00053 SymbolTableMap::const_iterator SI = Symbols.find(TargetName.data()); 00054 if (SI != Symbols.end()) { 00055 Value.SectionID = SI->second.first; 00056 Value.Offset = SI->second.second + RE.Addend; 00057 } else { 00058 SI = GlobalSymbolTable.find(TargetName.data()); 00059 if (SI != GlobalSymbolTable.end()) { 00060 Value.SectionID = SI->second.first; 00061 Value.Offset = SI->second.second + RE.Addend; 00062 } else { 00063 Value.SymbolName = TargetName.data(); 00064 Value.Offset = RE.Addend; 00065 } 00066 } 00067 } else { 00068 SectionRef Sec = Obj.getRelocationSection(RelInfo); 00069 bool IsCode = false; 00070 Sec.isText(IsCode); 00071 Value.SectionID = findOrEmitSection(ObjImg, Sec, IsCode, ObjSectionToID); 00072 uint64_t Addr; 00073 Sec.getAddress(Addr); 00074 Value.Offset = RE.Addend - Addr; 00075 } 00076 00077 return Value; 00078 } 00079 00080 void RuntimeDyldMachO::makeValueAddendPCRel(RelocationValueRef &Value, 00081 ObjectImage &ObjImg, 00082 const relocation_iterator &RI, 00083 unsigned OffsetToNextPC) { 00084 const MachOObjectFile &Obj = 00085 static_cast<const MachOObjectFile &>(*ObjImg.getObjectFile()); 00086 MachO::any_relocation_info RelInfo = 00087 Obj.getRelocation(RI->getRawDataRefImpl()); 00088 00089 bool IsPCRel = Obj.getAnyRelocationPCRel(RelInfo); 00090 if (IsPCRel) { 00091 uint64_t RelocAddr = 0; 00092 RI->getAddress(RelocAddr); 00093 Value.Offset += RelocAddr + OffsetToNextPC; 00094 } 00095 } 00096 00097 void RuntimeDyldMachO::dumpRelocationToResolve(const RelocationEntry &RE, 00098 uint64_t Value) const { 00099 const SectionEntry &Section = Sections[RE.SectionID]; 00100 uint8_t *LocalAddress = Section.Address + RE.Offset; 00101 uint64_t FinalAddress = Section.LoadAddress + RE.Offset; 00102 00103 dbgs() << "resolveRelocation Section: " << RE.SectionID 00104 << " LocalAddress: " << format("%p", LocalAddress) 00105 << " FinalAddress: " << format("0x%016" PRIx64, FinalAddress) 00106 << " Value: " << format("0x%016" PRIx64, Value) << " Addend: " << RE.Addend 00107 << " isPCRel: " << RE.IsPCRel << " MachoType: " << RE.RelType 00108 << " Size: " << (1 << RE.Size) << "\n"; 00109 } 00110 00111 section_iterator 00112 RuntimeDyldMachO::getSectionByAddress(const MachOObjectFile &Obj, 00113 uint64_t Addr) { 00114 section_iterator SI = Obj.section_begin(); 00115 section_iterator SE = Obj.section_end(); 00116 00117 for (; SI != SE; ++SI) { 00118 uint64_t SAddr, SSize; 00119 SI->getAddress(SAddr); 00120 SI->getSize(SSize); 00121 if ((Addr >= SAddr) && (Addr < SAddr + SSize)) 00122 return SI; 00123 } 00124 00125 return SE; 00126 } 00127 00128 00129 // Populate __pointers section. 00130 void RuntimeDyldMachO::populateIndirectSymbolPointersSection( 00131 MachOObjectFile &Obj, 00132 const SectionRef &PTSection, 00133 unsigned PTSectionID) { 00134 assert(!Obj.is64Bit() && 00135 "Pointer table section not supported in 64-bit MachO."); 00136 00137 MachO::dysymtab_command DySymTabCmd = Obj.getDysymtabLoadCommand(); 00138 MachO::section Sec32 = Obj.getSection(PTSection.getRawDataRefImpl()); 00139 uint32_t PTSectionSize = Sec32.size; 00140 unsigned FirstIndirectSymbol = Sec32.reserved1; 00141 const unsigned PTEntrySize = 4; 00142 unsigned NumPTEntries = PTSectionSize / PTEntrySize; 00143 unsigned PTEntryOffset = 0; 00144 00145 assert((PTSectionSize % PTEntrySize) == 0 && 00146 "Pointers section does not contain a whole number of stubs?"); 00147 00148 DEBUG(dbgs() << "Populating pointer table section " 00149 << Sections[PTSectionID].Name 00150 << ", Section ID " << PTSectionID << ", " 00151 << NumPTEntries << " entries, " << PTEntrySize 00152 << " bytes each:\n"); 00153 00154 for (unsigned i = 0; i < NumPTEntries; ++i) { 00155 unsigned SymbolIndex = 00156 Obj.getIndirectSymbolTableEntry(DySymTabCmd, FirstIndirectSymbol + i); 00157 symbol_iterator SI = Obj.getSymbolByIndex(SymbolIndex); 00158 StringRef IndirectSymbolName; 00159 SI->getName(IndirectSymbolName); 00160 DEBUG(dbgs() << " " << IndirectSymbolName << ": index " << SymbolIndex 00161 << ", PT offset: " << PTEntryOffset << "\n"); 00162 RelocationEntry RE(PTSectionID, PTEntryOffset, 00163 MachO::GENERIC_RELOC_VANILLA, 0, false, 2); 00164 addRelocationForSymbol(RE, IndirectSymbolName); 00165 PTEntryOffset += PTEntrySize; 00166 } 00167 } 00168 00169 bool 00170 RuntimeDyldMachO::isCompatibleFormat(const ObjectBuffer *InputBuffer) const { 00171 if (InputBuffer->getBufferSize() < 4) 00172 return false; 00173 StringRef Magic(InputBuffer->getBufferStart(), 4); 00174 if (Magic == "\xFE\xED\xFA\xCE") 00175 return true; 00176 if (Magic == "\xCE\xFA\xED\xFE") 00177 return true; 00178 if (Magic == "\xFE\xED\xFA\xCF") 00179 return true; 00180 if (Magic == "\xCF\xFA\xED\xFE") 00181 return true; 00182 return false; 00183 } 00184 00185 bool RuntimeDyldMachO::isCompatibleFile(const object::ObjectFile *Obj) const { 00186 return Obj->isMachO(); 00187 } 00188 00189 template <typename Impl> 00190 void RuntimeDyldMachOCRTPBase<Impl>::finalizeLoad(ObjectImage &ObjImg, 00191 ObjSectionToIDMap &SectionMap) { 00192 unsigned EHFrameSID = RTDYLD_INVALID_SECTION_ID; 00193 unsigned TextSID = RTDYLD_INVALID_SECTION_ID; 00194 unsigned ExceptTabSID = RTDYLD_INVALID_SECTION_ID; 00195 ObjSectionToIDMap::iterator i, e; 00196 00197 for (i = SectionMap.begin(), e = SectionMap.end(); i != e; ++i) { 00198 const SectionRef &Section = i->first; 00199 StringRef Name; 00200 Section.getName(Name); 00201 if (Name == "__eh_frame") 00202 EHFrameSID = i->second; 00203 else if (Name == "__text") 00204 TextSID = i->second; 00205 else if (Name == "__gcc_except_tab") 00206 ExceptTabSID = i->second; 00207 else 00208 impl().finalizeSection(ObjImg, i->second, Section); 00209 } 00210 UnregisteredEHFrameSections.push_back( 00211 EHFrameRelatedSections(EHFrameSID, TextSID, ExceptTabSID)); 00212 } 00213 00214 template <typename Impl> 00215 unsigned char *RuntimeDyldMachOCRTPBase<Impl>::processFDE(unsigned char *P, 00216 int64_t DeltaForText, 00217 int64_t DeltaForEH) { 00218 typedef typename Impl::TargetPtrT TargetPtrT; 00219 00220 DEBUG(dbgs() << "Processing FDE: Delta for text: " << DeltaForText 00221 << ", Delta for EH: " << DeltaForEH << "\n"); 00222 uint32_t Length = *((uint32_t *)P); 00223 P += 4; 00224 unsigned char *Ret = P + Length; 00225 uint32_t Offset = *((uint32_t *)P); 00226 if (Offset == 0) // is a CIE 00227 return Ret; 00228 00229 P += 4; 00230 TargetPtrT FDELocation = *((TargetPtrT*)P); 00231 TargetPtrT NewLocation = FDELocation - DeltaForText; 00232 *((TargetPtrT*)P) = NewLocation; 00233 P += sizeof(TargetPtrT); 00234 00235 // Skip the FDE address range 00236 P += sizeof(TargetPtrT); 00237 00238 uint8_t Augmentationsize = *P; 00239 P += 1; 00240 if (Augmentationsize != 0) { 00241 TargetPtrT LSDA = *((TargetPtrT *)P); 00242 TargetPtrT NewLSDA = LSDA - DeltaForEH; 00243 *((TargetPtrT *)P) = NewLSDA; 00244 } 00245 00246 return Ret; 00247 } 00248 00249 static int64_t computeDelta(SectionEntry *A, SectionEntry *B) { 00250 int64_t ObjDistance = A->ObjAddress - B->ObjAddress; 00251 int64_t MemDistance = A->LoadAddress - B->LoadAddress; 00252 return ObjDistance - MemDistance; 00253 } 00254 00255 template <typename Impl> 00256 void RuntimeDyldMachOCRTPBase<Impl>::registerEHFrames() { 00257 00258 if (!MemMgr) 00259 return; 00260 for (int i = 0, e = UnregisteredEHFrameSections.size(); i != e; ++i) { 00261 EHFrameRelatedSections &SectionInfo = UnregisteredEHFrameSections[i]; 00262 if (SectionInfo.EHFrameSID == RTDYLD_INVALID_SECTION_ID || 00263 SectionInfo.TextSID == RTDYLD_INVALID_SECTION_ID) 00264 continue; 00265 SectionEntry *Text = &Sections[SectionInfo.TextSID]; 00266 SectionEntry *EHFrame = &Sections[SectionInfo.EHFrameSID]; 00267 SectionEntry *ExceptTab = nullptr; 00268 if (SectionInfo.ExceptTabSID != RTDYLD_INVALID_SECTION_ID) 00269 ExceptTab = &Sections[SectionInfo.ExceptTabSID]; 00270 00271 int64_t DeltaForText = computeDelta(Text, EHFrame); 00272 int64_t DeltaForEH = 0; 00273 if (ExceptTab) 00274 DeltaForEH = computeDelta(ExceptTab, EHFrame); 00275 00276 unsigned char *P = EHFrame->Address; 00277 unsigned char *End = P + EHFrame->Size; 00278 do { 00279 P = processFDE(P, DeltaForText, DeltaForEH); 00280 } while (P != End); 00281 00282 MemMgr->registerEHFrames(EHFrame->Address, EHFrame->LoadAddress, 00283 EHFrame->Size); 00284 } 00285 UnregisteredEHFrameSections.clear(); 00286 } 00287 00288 std::unique_ptr<RuntimeDyldMachO> 00289 llvm::RuntimeDyldMachO::create(Triple::ArchType Arch, RTDyldMemoryManager *MM) { 00290 switch (Arch) { 00291 default: 00292 llvm_unreachable("Unsupported target for RuntimeDyldMachO."); 00293 break; 00294 case Triple::arm: return make_unique<RuntimeDyldMachOARM>(MM); 00295 case Triple::aarch64: return make_unique<RuntimeDyldMachOAArch64>(MM); 00296 case Triple::x86: return make_unique<RuntimeDyldMachOI386>(MM); 00297 case Triple::x86_64: return make_unique<RuntimeDyldMachOX86_64>(MM); 00298 } 00299 } 00300 00301 } // end namespace llvm