RuntimeDyldMachOI386.h revision 353358
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 17namespace llvm { 18 19class RuntimeDyldMachOI386 20 : public RuntimeDyldMachOCRTPBase<RuntimeDyldMachOI386> { 21public: 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 Section.getName(Name); 132 133 if (Name == "__jump_table") 134 return populateJumpTable(cast<MachOObjectFile>(Obj), Section, SectionID); 135 else if (Name == "__pointers") 136 return populateIndirectSymbolPointersSection(cast<MachOObjectFile>(Obj), 137 Section, SectionID); 138 return Error::success(); 139 } 140 141private: 142 Expected<relocation_iterator> 143 processSECTDIFFRelocation(unsigned SectionID, relocation_iterator RelI, 144 const ObjectFile &BaseObjT, 145 ObjSectionToIDMap &ObjSectionToID) { 146 const MachOObjectFile &Obj = 147 static_cast<const MachOObjectFile&>(BaseObjT); 148 MachO::any_relocation_info RE = 149 Obj.getRelocation(RelI->getRawDataRefImpl()); 150 151 SectionEntry &Section = Sections[SectionID]; 152 uint32_t RelocType = Obj.getAnyRelocationType(RE); 153 bool IsPCRel = Obj.getAnyRelocationPCRel(RE); 154 unsigned Size = Obj.getAnyRelocationLength(RE); 155 uint64_t Offset = RelI->getOffset(); 156 uint8_t *LocalAddress = Section.getAddressWithOffset(Offset); 157 unsigned NumBytes = 1 << Size; 158 uint64_t Addend = readBytesUnaligned(LocalAddress, NumBytes); 159 160 ++RelI; 161 MachO::any_relocation_info RE2 = 162 Obj.getRelocation(RelI->getRawDataRefImpl()); 163 164 uint32_t AddrA = Obj.getScatteredRelocationValue(RE); 165 section_iterator SAI = getSectionByAddress(Obj, AddrA); 166 assert(SAI != Obj.section_end() && "Can't find section for address A"); 167 uint64_t SectionABase = SAI->getAddress(); 168 uint64_t SectionAOffset = AddrA - SectionABase; 169 SectionRef SectionA = *SAI; 170 bool IsCode = SectionA.isText(); 171 uint32_t SectionAID = ~0U; 172 if (auto SectionAIDOrErr = 173 findOrEmitSection(Obj, SectionA, IsCode, ObjSectionToID)) 174 SectionAID = *SectionAIDOrErr; 175 else 176 return SectionAIDOrErr.takeError(); 177 178 uint32_t AddrB = Obj.getScatteredRelocationValue(RE2); 179 section_iterator SBI = getSectionByAddress(Obj, AddrB); 180 assert(SBI != Obj.section_end() && "Can't find section for address B"); 181 uint64_t SectionBBase = SBI->getAddress(); 182 uint64_t SectionBOffset = AddrB - SectionBBase; 183 SectionRef SectionB = *SBI; 184 uint32_t SectionBID = ~0U; 185 if (auto SectionBIDOrErr = 186 findOrEmitSection(Obj, SectionB, IsCode, ObjSectionToID)) 187 SectionBID = *SectionBIDOrErr; 188 else 189 return SectionBIDOrErr.takeError(); 190 191 // Compute the addend 'C' from the original expression 'A - B + C'. 192 Addend -= AddrA - AddrB; 193 194 LLVM_DEBUG(dbgs() << "Found SECTDIFF: AddrA: " << AddrA 195 << ", AddrB: " << AddrB << ", Addend: " << Addend 196 << ", SectionA ID: " << SectionAID << ", SectionAOffset: " 197 << SectionAOffset << ", SectionB ID: " << SectionBID 198 << ", SectionBOffset: " << SectionBOffset << "\n"); 199 RelocationEntry R(SectionID, Offset, RelocType, Addend, SectionAID, 200 SectionAOffset, SectionBID, SectionBOffset, 201 IsPCRel, Size); 202 203 addRelocationForSection(R, SectionAID); 204 205 return ++RelI; 206 } 207 208 // Populate stubs in __jump_table section. 209 Error populateJumpTable(const MachOObjectFile &Obj, 210 const SectionRef &JTSection, 211 unsigned JTSectionID) { 212 MachO::dysymtab_command DySymTabCmd = Obj.getDysymtabLoadCommand(); 213 MachO::section Sec32 = Obj.getSection(JTSection.getRawDataRefImpl()); 214 uint32_t JTSectionSize = Sec32.size; 215 unsigned FirstIndirectSymbol = Sec32.reserved1; 216 unsigned JTEntrySize = Sec32.reserved2; 217 unsigned NumJTEntries = JTSectionSize / JTEntrySize; 218 uint8_t *JTSectionAddr = getSectionAddress(JTSectionID); 219 unsigned JTEntryOffset = 0; 220 221 if (JTSectionSize % JTEntrySize != 0) 222 return make_error<RuntimeDyldError>("Jump-table section does not contain " 223 "a whole number of stubs?"); 224 225 for (unsigned i = 0; i < NumJTEntries; ++i) { 226 unsigned SymbolIndex = 227 Obj.getIndirectSymbolTableEntry(DySymTabCmd, FirstIndirectSymbol + i); 228 symbol_iterator SI = Obj.getSymbolByIndex(SymbolIndex); 229 Expected<StringRef> IndirectSymbolName = SI->getName(); 230 if (!IndirectSymbolName) 231 return IndirectSymbolName.takeError(); 232 uint8_t *JTEntryAddr = JTSectionAddr + JTEntryOffset; 233 createStubFunction(JTEntryAddr); 234 RelocationEntry RE(JTSectionID, JTEntryOffset + 1, 235 MachO::GENERIC_RELOC_VANILLA, 0, true, 2); 236 addRelocationForSymbol(RE, *IndirectSymbolName); 237 JTEntryOffset += JTEntrySize; 238 } 239 240 return Error::success(); 241 } 242 243}; 244} 245 246#undef DEBUG_TYPE 247 248#endif 249