LLVM API Documentation
00001 //===---- RuntimeDyldMachOI386.h ---- MachO/I386 specific code. ---*- 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 #ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOI386_H 00011 #define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOI386_H 00012 00013 #include "../RuntimeDyldMachO.h" 00014 00015 #define DEBUG_TYPE "dyld" 00016 00017 namespace llvm { 00018 00019 class RuntimeDyldMachOI386 00020 : public RuntimeDyldMachOCRTPBase<RuntimeDyldMachOI386> { 00021 public: 00022 00023 typedef uint32_t TargetPtrT; 00024 00025 RuntimeDyldMachOI386(RTDyldMemoryManager *MM) 00026 : RuntimeDyldMachOCRTPBase(MM) {} 00027 00028 unsigned getMaxStubSize() override { return 0; } 00029 00030 unsigned getStubAlignment() override { return 1; } 00031 00032 relocation_iterator 00033 processRelocationRef(unsigned SectionID, relocation_iterator RelI, 00034 ObjectImage &ObjImg, ObjSectionToIDMap &ObjSectionToID, 00035 const SymbolTableMap &Symbols, StubMap &Stubs) override { 00036 const MachOObjectFile &Obj = 00037 static_cast<const MachOObjectFile &>(*ObjImg.getObjectFile()); 00038 MachO::any_relocation_info RelInfo = 00039 Obj.getRelocation(RelI->getRawDataRefImpl()); 00040 uint32_t RelType = Obj.getAnyRelocationType(RelInfo); 00041 00042 if (Obj.isRelocationScattered(RelInfo)) { 00043 if (RelType == MachO::GENERIC_RELOC_SECTDIFF || 00044 RelType == MachO::GENERIC_RELOC_LOCAL_SECTDIFF) 00045 return processSECTDIFFRelocation(SectionID, RelI, ObjImg, 00046 ObjSectionToID); 00047 else if (RelType == MachO::GENERIC_RELOC_VANILLA) 00048 return processI386ScatteredVANILLA(SectionID, RelI, ObjImg, 00049 ObjSectionToID); 00050 llvm_unreachable("Unhandled scattered relocation."); 00051 } 00052 00053 RelocationEntry RE(getRelocationEntry(SectionID, ObjImg, RelI)); 00054 RE.Addend = memcpyAddend(RE); 00055 RelocationValueRef Value( 00056 getRelocationValueRef(ObjImg, RelI, RE, ObjSectionToID, Symbols)); 00057 00058 // Addends for external, PC-rel relocations on i386 point back to the zero 00059 // offset. Calculate the final offset from the relocation target instead. 00060 // This allows us to use the same logic for both external and internal 00061 // relocations in resolveI386RelocationRef. 00062 // bool IsExtern = Obj.getPlainRelocationExternal(RelInfo); 00063 // if (IsExtern && RE.IsPCRel) { 00064 // uint64_t RelocAddr = 0; 00065 // RelI->getAddress(RelocAddr); 00066 // Value.Addend += RelocAddr + 4; 00067 // } 00068 if (RE.IsPCRel) 00069 makeValueAddendPCRel(Value, ObjImg, RelI, 1 << RE.Size); 00070 00071 RE.Addend = Value.Offset; 00072 00073 if (Value.SymbolName) 00074 addRelocationForSymbol(RE, Value.SymbolName); 00075 else 00076 addRelocationForSection(RE, Value.SectionID); 00077 00078 return ++RelI; 00079 } 00080 00081 void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override { 00082 DEBUG(dumpRelocationToResolve(RE, Value)); 00083 00084 const SectionEntry &Section = Sections[RE.SectionID]; 00085 uint8_t *LocalAddress = Section.Address + RE.Offset; 00086 00087 if (RE.IsPCRel) { 00088 uint64_t FinalAddress = Section.LoadAddress + RE.Offset; 00089 Value -= FinalAddress + 4; // see MachOX86_64::resolveRelocation. 00090 } 00091 00092 switch (RE.RelType) { 00093 default: 00094 llvm_unreachable("Invalid relocation type!"); 00095 case MachO::GENERIC_RELOC_VANILLA: 00096 writeBytesUnaligned(Value + RE.Addend, LocalAddress, 1 << RE.Size); 00097 break; 00098 case MachO::GENERIC_RELOC_SECTDIFF: 00099 case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: { 00100 uint64_t SectionABase = Sections[RE.Sections.SectionA].LoadAddress; 00101 uint64_t SectionBBase = Sections[RE.Sections.SectionB].LoadAddress; 00102 assert((Value == SectionABase || Value == SectionBBase) && 00103 "Unexpected SECTDIFF relocation value."); 00104 Value = SectionABase - SectionBBase + RE.Addend; 00105 writeBytesUnaligned(Value, LocalAddress, 1 << RE.Size); 00106 break; 00107 } 00108 case MachO::GENERIC_RELOC_PB_LA_PTR: 00109 Error("Relocation type not implemented yet!"); 00110 } 00111 } 00112 00113 void finalizeSection(ObjectImage &ObjImg, unsigned SectionID, 00114 const SectionRef &Section) { 00115 StringRef Name; 00116 Section.getName(Name); 00117 00118 if (Name == "__jump_table") 00119 populateJumpTable(cast<MachOObjectFile>(*ObjImg.getObjectFile()), Section, 00120 SectionID); 00121 else if (Name == "__pointers") 00122 populateIndirectSymbolPointersSection( 00123 cast<MachOObjectFile>(*ObjImg.getObjectFile()), 00124 Section, SectionID); 00125 } 00126 00127 private: 00128 relocation_iterator 00129 processSECTDIFFRelocation(unsigned SectionID, relocation_iterator RelI, 00130 ObjectImage &Obj, 00131 ObjSectionToIDMap &ObjSectionToID) { 00132 const MachOObjectFile *MachO = 00133 static_cast<const MachOObjectFile *>(Obj.getObjectFile()); 00134 MachO::any_relocation_info RE = 00135 MachO->getRelocation(RelI->getRawDataRefImpl()); 00136 00137 SectionEntry &Section = Sections[SectionID]; 00138 uint32_t RelocType = MachO->getAnyRelocationType(RE); 00139 bool IsPCRel = MachO->getAnyRelocationPCRel(RE); 00140 unsigned Size = MachO->getAnyRelocationLength(RE); 00141 uint64_t Offset; 00142 RelI->getOffset(Offset); 00143 uint8_t *LocalAddress = Section.Address + Offset; 00144 unsigned NumBytes = 1 << Size; 00145 int64_t Addend = 0; 00146 memcpy(&Addend, LocalAddress, NumBytes); 00147 00148 ++RelI; 00149 MachO::any_relocation_info RE2 = 00150 MachO->getRelocation(RelI->getRawDataRefImpl()); 00151 00152 uint32_t AddrA = MachO->getScatteredRelocationValue(RE); 00153 section_iterator SAI = getSectionByAddress(*MachO, AddrA); 00154 assert(SAI != MachO->section_end() && "Can't find section for address A"); 00155 uint64_t SectionABase; 00156 SAI->getAddress(SectionABase); 00157 uint64_t SectionAOffset = AddrA - SectionABase; 00158 SectionRef SectionA = *SAI; 00159 bool IsCode; 00160 SectionA.isText(IsCode); 00161 uint32_t SectionAID = 00162 findOrEmitSection(Obj, SectionA, IsCode, ObjSectionToID); 00163 00164 uint32_t AddrB = MachO->getScatteredRelocationValue(RE2); 00165 section_iterator SBI = getSectionByAddress(*MachO, AddrB); 00166 assert(SBI != MachO->section_end() && "Can't find section for address B"); 00167 uint64_t SectionBBase; 00168 SBI->getAddress(SectionBBase); 00169 uint64_t SectionBOffset = AddrB - SectionBBase; 00170 SectionRef SectionB = *SBI; 00171 uint32_t SectionBID = 00172 findOrEmitSection(Obj, SectionB, IsCode, ObjSectionToID); 00173 00174 if (Addend != AddrA - AddrB) 00175 Error("Unexpected SECTDIFF relocation addend."); 00176 00177 DEBUG(dbgs() << "Found SECTDIFF: AddrA: " << AddrA << ", AddrB: " << AddrB 00178 << ", Addend: " << Addend << ", SectionA ID: " << SectionAID 00179 << ", SectionAOffset: " << SectionAOffset 00180 << ", SectionB ID: " << SectionBID 00181 << ", SectionBOffset: " << SectionBOffset << "\n"); 00182 RelocationEntry R(SectionID, Offset, RelocType, 0, SectionAID, 00183 SectionAOffset, SectionBID, SectionBOffset, IsPCRel, 00184 Size); 00185 00186 addRelocationForSection(R, SectionAID); 00187 addRelocationForSection(R, SectionBID); 00188 00189 return ++RelI; 00190 } 00191 00192 relocation_iterator processI386ScatteredVANILLA( 00193 unsigned SectionID, relocation_iterator RelI, ObjectImage &Obj, 00194 RuntimeDyldMachO::ObjSectionToIDMap &ObjSectionToID) { 00195 const MachOObjectFile *MachO = 00196 static_cast<const MachOObjectFile *>(Obj.getObjectFile()); 00197 MachO::any_relocation_info RE = 00198 MachO->getRelocation(RelI->getRawDataRefImpl()); 00199 00200 SectionEntry &Section = Sections[SectionID]; 00201 uint32_t RelocType = MachO->getAnyRelocationType(RE); 00202 bool IsPCRel = MachO->getAnyRelocationPCRel(RE); 00203 unsigned Size = MachO->getAnyRelocationLength(RE); 00204 uint64_t Offset; 00205 RelI->getOffset(Offset); 00206 uint8_t *LocalAddress = Section.Address + Offset; 00207 unsigned NumBytes = 1 << Size; 00208 int64_t Addend = 0; 00209 memcpy(&Addend, LocalAddress, NumBytes); 00210 00211 unsigned SymbolBaseAddr = MachO->getScatteredRelocationValue(RE); 00212 section_iterator TargetSI = getSectionByAddress(*MachO, SymbolBaseAddr); 00213 assert(TargetSI != MachO->section_end() && "Can't find section for symbol"); 00214 uint64_t SectionBaseAddr; 00215 TargetSI->getAddress(SectionBaseAddr); 00216 SectionRef TargetSection = *TargetSI; 00217 bool IsCode; 00218 TargetSection.isText(IsCode); 00219 uint32_t TargetSectionID = 00220 findOrEmitSection(Obj, TargetSection, IsCode, ObjSectionToID); 00221 00222 Addend -= SectionBaseAddr; 00223 RelocationEntry R(SectionID, Offset, RelocType, Addend, IsPCRel, Size); 00224 00225 addRelocationForSection(R, TargetSectionID); 00226 00227 return ++RelI; 00228 } 00229 00230 // Populate stubs in __jump_table section. 00231 void populateJumpTable(MachOObjectFile &Obj, const SectionRef &JTSection, 00232 unsigned JTSectionID) { 00233 assert(!Obj.is64Bit() && 00234 "__jump_table section not supported in 64-bit MachO."); 00235 00236 MachO::dysymtab_command DySymTabCmd = Obj.getDysymtabLoadCommand(); 00237 MachO::section Sec32 = Obj.getSection(JTSection.getRawDataRefImpl()); 00238 uint32_t JTSectionSize = Sec32.size; 00239 unsigned FirstIndirectSymbol = Sec32.reserved1; 00240 unsigned JTEntrySize = Sec32.reserved2; 00241 unsigned NumJTEntries = JTSectionSize / JTEntrySize; 00242 uint8_t *JTSectionAddr = getSectionAddress(JTSectionID); 00243 unsigned JTEntryOffset = 0; 00244 00245 assert((JTSectionSize % JTEntrySize) == 0 && 00246 "Jump-table section does not contain a whole number of stubs?"); 00247 00248 for (unsigned i = 0; i < NumJTEntries; ++i) { 00249 unsigned SymbolIndex = 00250 Obj.getIndirectSymbolTableEntry(DySymTabCmd, FirstIndirectSymbol + i); 00251 symbol_iterator SI = Obj.getSymbolByIndex(SymbolIndex); 00252 StringRef IndirectSymbolName; 00253 SI->getName(IndirectSymbolName); 00254 uint8_t *JTEntryAddr = JTSectionAddr + JTEntryOffset; 00255 createStubFunction(JTEntryAddr); 00256 RelocationEntry RE(JTSectionID, JTEntryOffset + 1, 00257 MachO::GENERIC_RELOC_VANILLA, 0, true, 2); 00258 addRelocationForSymbol(RE, IndirectSymbolName); 00259 JTEntryOffset += JTEntrySize; 00260 } 00261 } 00262 00263 }; 00264 } 00265 00266 #undef DEBUG_TYPE 00267 00268 #endif