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