1 //===---- RuntimeDyldMachOI386.h ---- MachO/I386 specific code. ---*- 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 #ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOI386_H 11 #define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOI386_H 12 13 #include "../RuntimeDyldMachO.h" 14 #include <string> 15 16 #define DEBUG_TYPE "dyld" 17 18 namespace llvm { 19 20 class RuntimeDyldMachOI386 21 : public RuntimeDyldMachOCRTPBase<RuntimeDyldMachOI386> { 22 public: 23 24 typedef uint32_t TargetPtrT; 25 RuntimeDyldMachOI386(RuntimeDyld::MemoryManager & MM,RuntimeDyld::SymbolResolver & Resolver)26 RuntimeDyldMachOI386(RuntimeDyld::MemoryManager &MM, 27 RuntimeDyld::SymbolResolver &Resolver) 28 : RuntimeDyldMachOCRTPBase(MM, Resolver) {} 29 getMaxStubSize()30 unsigned getMaxStubSize() override { return 0; } 31 getStubAlignment()32 unsigned getStubAlignment() override { return 1; } 33 34 Expected<relocation_iterator> processRelocationRef(unsigned SectionID,relocation_iterator RelI,const ObjectFile & BaseObjT,ObjSectionToIDMap & ObjSectionToID,StubMap & Stubs)35 processRelocationRef(unsigned SectionID, relocation_iterator RelI, 36 const ObjectFile &BaseObjT, 37 ObjSectionToIDMap &ObjSectionToID, 38 StubMap &Stubs) override { 39 const MachOObjectFile &Obj = 40 static_cast<const MachOObjectFile &>(BaseObjT); 41 MachO::any_relocation_info RelInfo = 42 Obj.getRelocation(RelI->getRawDataRefImpl()); 43 uint32_t RelType = Obj.getAnyRelocationType(RelInfo); 44 45 if (Obj.isRelocationScattered(RelInfo)) { 46 if (RelType == MachO::GENERIC_RELOC_SECTDIFF || 47 RelType == MachO::GENERIC_RELOC_LOCAL_SECTDIFF) 48 return processSECTDIFFRelocation(SectionID, RelI, Obj, 49 ObjSectionToID); 50 else if (RelType == MachO::GENERIC_RELOC_VANILLA) 51 return processScatteredVANILLA(SectionID, RelI, Obj, ObjSectionToID); 52 return make_error<RuntimeDyldError>(("Unhandled I386 scattered relocation " 53 "type: " + Twine(RelType)).str()); 54 } 55 56 switch (RelType) { 57 UNIMPLEMENTED_RELOC(MachO::GENERIC_RELOC_PAIR); 58 UNIMPLEMENTED_RELOC(MachO::GENERIC_RELOC_PB_LA_PTR); 59 UNIMPLEMENTED_RELOC(MachO::GENERIC_RELOC_TLV); 60 default: 61 if (RelType > MachO::GENERIC_RELOC_TLV) 62 return make_error<RuntimeDyldError>(("MachO I386 relocation type " + 63 Twine(RelType) + 64 " is out of range").str()); 65 break; 66 } 67 68 RelocationEntry RE(getRelocationEntry(SectionID, Obj, RelI)); 69 RE.Addend = memcpyAddend(RE); 70 RelocationValueRef Value; 71 if (auto ValueOrErr = getRelocationValueRef(Obj, RelI, RE, ObjSectionToID)) 72 Value = *ValueOrErr; 73 else 74 return ValueOrErr.takeError(); 75 76 // Addends for external, PC-rel relocations on i386 point back to the zero 77 // offset. Calculate the final offset from the relocation target instead. 78 // This allows us to use the same logic for both external and internal 79 // relocations in resolveI386RelocationRef. 80 // bool IsExtern = Obj.getPlainRelocationExternal(RelInfo); 81 // if (IsExtern && RE.IsPCRel) { 82 // uint64_t RelocAddr = 0; 83 // RelI->getAddress(RelocAddr); 84 // Value.Addend += RelocAddr + 4; 85 // } 86 if (RE.IsPCRel) 87 makeValueAddendPCRel(Value, RelI, 1 << RE.Size); 88 89 RE.Addend = Value.Offset; 90 91 if (Value.SymbolName) 92 addRelocationForSymbol(RE, Value.SymbolName); 93 else 94 addRelocationForSection(RE, Value.SectionID); 95 96 return ++RelI; 97 } 98 resolveRelocation(const RelocationEntry & RE,uint64_t Value)99 void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override { 100 DEBUG(dumpRelocationToResolve(RE, Value)); 101 102 const SectionEntry &Section = Sections[RE.SectionID]; 103 uint8_t *LocalAddress = Section.getAddressWithOffset(RE.Offset); 104 105 if (RE.IsPCRel) { 106 uint64_t FinalAddress = Section.getLoadAddressWithOffset(RE.Offset); 107 Value -= FinalAddress + 4; // see MachOX86_64::resolveRelocation. 108 } 109 110 switch (RE.RelType) { 111 case MachO::GENERIC_RELOC_VANILLA: 112 writeBytesUnaligned(Value + RE.Addend, LocalAddress, 1 << RE.Size); 113 break; 114 case MachO::GENERIC_RELOC_SECTDIFF: 115 case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: { 116 uint64_t SectionABase = Sections[RE.Sections.SectionA].getLoadAddress(); 117 uint64_t SectionBBase = Sections[RE.Sections.SectionB].getLoadAddress(); 118 assert((Value == SectionABase || Value == SectionBBase) && 119 "Unexpected SECTDIFF relocation value."); 120 Value = SectionABase - SectionBBase + RE.Addend; 121 writeBytesUnaligned(Value, LocalAddress, 1 << RE.Size); 122 break; 123 } 124 default: 125 llvm_unreachable("Invalid relocation type!"); 126 } 127 } 128 finalizeSection(const ObjectFile & Obj,unsigned SectionID,const SectionRef & Section)129 Error finalizeSection(const ObjectFile &Obj, unsigned SectionID, 130 const SectionRef &Section) { 131 StringRef Name; 132 Section.getName(Name); 133 134 if (Name == "__jump_table") 135 return populateJumpTable(cast<MachOObjectFile>(Obj), Section, SectionID); 136 else if (Name == "__pointers") 137 return populateIndirectSymbolPointersSection(cast<MachOObjectFile>(Obj), 138 Section, SectionID); 139 return Error::success(); 140 } 141 142 private: 143 Expected<relocation_iterator> processSECTDIFFRelocation(unsigned SectionID,relocation_iterator RelI,const ObjectFile & BaseObjT,ObjSectionToIDMap & ObjSectionToID)144 processSECTDIFFRelocation(unsigned SectionID, relocation_iterator RelI, 145 const ObjectFile &BaseObjT, 146 ObjSectionToIDMap &ObjSectionToID) { 147 const MachOObjectFile &Obj = 148 static_cast<const MachOObjectFile&>(BaseObjT); 149 MachO::any_relocation_info RE = 150 Obj.getRelocation(RelI->getRawDataRefImpl()); 151 152 SectionEntry &Section = Sections[SectionID]; 153 uint32_t RelocType = Obj.getAnyRelocationType(RE); 154 bool IsPCRel = Obj.getAnyRelocationPCRel(RE); 155 unsigned Size = Obj.getAnyRelocationLength(RE); 156 uint64_t Offset = RelI->getOffset(); 157 uint8_t *LocalAddress = Section.getAddressWithOffset(Offset); 158 unsigned NumBytes = 1 << Size; 159 uint64_t Addend = readBytesUnaligned(LocalAddress, NumBytes); 160 161 ++RelI; 162 MachO::any_relocation_info RE2 = 163 Obj.getRelocation(RelI->getRawDataRefImpl()); 164 165 uint32_t AddrA = Obj.getScatteredRelocationValue(RE); 166 section_iterator SAI = getSectionByAddress(Obj, AddrA); 167 assert(SAI != Obj.section_end() && "Can't find section for address A"); 168 uint64_t SectionABase = SAI->getAddress(); 169 uint64_t SectionAOffset = AddrA - SectionABase; 170 SectionRef SectionA = *SAI; 171 bool IsCode = SectionA.isText(); 172 uint32_t SectionAID = ~0U; 173 if (auto SectionAIDOrErr = 174 findOrEmitSection(Obj, SectionA, IsCode, ObjSectionToID)) 175 SectionAID = *SectionAIDOrErr; 176 else 177 return SectionAIDOrErr.takeError(); 178 179 uint32_t AddrB = Obj.getScatteredRelocationValue(RE2); 180 section_iterator SBI = getSectionByAddress(Obj, AddrB); 181 assert(SBI != Obj.section_end() && "Can't find section for address B"); 182 uint64_t SectionBBase = SBI->getAddress(); 183 uint64_t SectionBOffset = AddrB - SectionBBase; 184 SectionRef SectionB = *SBI; 185 uint32_t SectionBID = ~0U; 186 if (auto SectionBIDOrErr = 187 findOrEmitSection(Obj, SectionB, IsCode, ObjSectionToID)) 188 SectionBID = *SectionBIDOrErr; 189 else 190 return SectionBIDOrErr.takeError(); 191 192 // Compute the addend 'C' from the original expression 'A - B + C'. 193 Addend -= AddrA - AddrB; 194 195 DEBUG(dbgs() << "Found SECTDIFF: AddrA: " << AddrA << ", AddrB: " << AddrB 196 << ", Addend: " << Addend << ", SectionA ID: " << SectionAID 197 << ", SectionAOffset: " << SectionAOffset 198 << ", SectionB ID: " << SectionBID 199 << ", SectionBOffset: " << SectionBOffset << "\n"); 200 RelocationEntry R(SectionID, Offset, RelocType, Addend, SectionAID, 201 SectionAOffset, SectionBID, SectionBOffset, 202 IsPCRel, Size); 203 204 addRelocationForSection(R, SectionAID); 205 206 return ++RelI; 207 } 208 209 // Populate stubs in __jump_table section. populateJumpTable(const MachOObjectFile & Obj,const SectionRef & JTSection,unsigned JTSectionID)210 Error populateJumpTable(const MachOObjectFile &Obj, 211 const SectionRef &JTSection, 212 unsigned JTSectionID) { 213 MachO::dysymtab_command DySymTabCmd = Obj.getDysymtabLoadCommand(); 214 MachO::section Sec32 = Obj.getSection(JTSection.getRawDataRefImpl()); 215 uint32_t JTSectionSize = Sec32.size; 216 unsigned FirstIndirectSymbol = Sec32.reserved1; 217 unsigned JTEntrySize = Sec32.reserved2; 218 unsigned NumJTEntries = JTSectionSize / JTEntrySize; 219 uint8_t *JTSectionAddr = getSectionAddress(JTSectionID); 220 unsigned JTEntryOffset = 0; 221 222 if (JTSectionSize % JTEntrySize != 0) 223 return make_error<RuntimeDyldError>("Jump-table section does not contain " 224 "a whole number of stubs?"); 225 226 for (unsigned i = 0; i < NumJTEntries; ++i) { 227 unsigned SymbolIndex = 228 Obj.getIndirectSymbolTableEntry(DySymTabCmd, FirstIndirectSymbol + i); 229 symbol_iterator SI = Obj.getSymbolByIndex(SymbolIndex); 230 Expected<StringRef> IndirectSymbolName = SI->getName(); 231 if (!IndirectSymbolName) 232 return IndirectSymbolName.takeError(); 233 uint8_t *JTEntryAddr = JTSectionAddr + JTEntryOffset; 234 createStubFunction(JTEntryAddr); 235 RelocationEntry RE(JTSectionID, JTEntryOffset + 1, 236 MachO::GENERIC_RELOC_VANILLA, 0, true, 2); 237 addRelocationForSymbol(RE, *IndirectSymbolName); 238 JTEntryOffset += JTEntrySize; 239 } 240 241 return Error::success(); 242 } 243 244 }; 245 } 246 247 #undef DEBUG_TYPE 248 249 #endif 250