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