RuntimeDyldMachOI386.h revision 353358
1153323Srodrigc//===---- RuntimeDyldMachOI386.h ---- MachO/I386 specific code. ---*- C++ -*-=// 2159451Srodrigc// 3159451Srodrigc// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4153323Srodrigc// See https://llvm.org/LICENSE.txt for license information. 5159451Srodrigc// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6159451Srodrigc// 7153323Srodrigc//===----------------------------------------------------------------------===// 8153323Srodrigc 9159451Srodrigc#ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOI386_H 10159451Srodrigc#define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOI386_H 11159451Srodrigc 12159451Srodrigc#include "../RuntimeDyldMachO.h" 13153323Srodrigc#include <string> 14159451Srodrigc 15159451Srodrigc#define DEBUG_TYPE "dyld" 16159451Srodrigc 17153323Srodrigcnamespace llvm { 18153323Srodrigc 19153323Srodrigcclass RuntimeDyldMachOI386 20153323Srodrigc : public RuntimeDyldMachOCRTPBase<RuntimeDyldMachOI386> { 21153323Srodrigcpublic: 22153323Srodrigc 23153323Srodrigc typedef uint32_t TargetPtrT; 24153323Srodrigc 25153323Srodrigc RuntimeDyldMachOI386(RuntimeDyld::MemoryManager &MM, 26153323Srodrigc JITSymbolResolver &Resolver) 27153323Srodrigc : RuntimeDyldMachOCRTPBase(MM, Resolver) {} 28153323Srodrigc 29153323Srodrigc unsigned getMaxStubSize() const override { return 0; } 30153323Srodrigc 31153323Srodrigc unsigned getStubAlignment() override { return 1; } 32153323Srodrigc 33153323Srodrigc Expected<relocation_iterator> 34153323Srodrigc processRelocationRef(unsigned SectionID, relocation_iterator RelI, 35153323Srodrigc const ObjectFile &BaseObjT, 36153323Srodrigc ObjSectionToIDMap &ObjSectionToID, 37153323Srodrigc StubMap &Stubs) override { 38153323Srodrigc const MachOObjectFile &Obj = 39153323Srodrigc static_cast<const MachOObjectFile &>(BaseObjT); 40153323Srodrigc MachO::any_relocation_info RelInfo = 41153323Srodrigc Obj.getRelocation(RelI->getRawDataRefImpl()); 42153323Srodrigc uint32_t RelType = Obj.getAnyRelocationType(RelInfo); 43153323Srodrigc 44153323Srodrigc if (Obj.isRelocationScattered(RelInfo)) { 45153323Srodrigc if (RelType == MachO::GENERIC_RELOC_SECTDIFF || 46153323Srodrigc RelType == MachO::GENERIC_RELOC_LOCAL_SECTDIFF) 47153323Srodrigc return processSECTDIFFRelocation(SectionID, RelI, Obj, 48153323Srodrigc ObjSectionToID); 49153323Srodrigc else if (RelType == MachO::GENERIC_RELOC_VANILLA) 50153323Srodrigc return processScatteredVANILLA(SectionID, RelI, Obj, ObjSectionToID); 51153323Srodrigc return make_error<RuntimeDyldError>(("Unhandled I386 scattered relocation " 52153323Srodrigc "type: " + Twine(RelType)).str()); 53153323Srodrigc } 54153323Srodrigc 55153323Srodrigc switch (RelType) { 56153323Srodrigc UNIMPLEMENTED_RELOC(MachO::GENERIC_RELOC_PAIR); 57153323Srodrigc UNIMPLEMENTED_RELOC(MachO::GENERIC_RELOC_PB_LA_PTR); 58153323Srodrigc UNIMPLEMENTED_RELOC(MachO::GENERIC_RELOC_TLV); 59153323Srodrigc default: 60153323Srodrigc if (RelType > MachO::GENERIC_RELOC_TLV) 61153323Srodrigc return make_error<RuntimeDyldError>(("MachO I386 relocation type " + 62153323Srodrigc Twine(RelType) + 63153323Srodrigc " is out of range").str()); 64153323Srodrigc break; 65153323Srodrigc } 66153323Srodrigc 67153323Srodrigc RelocationEntry RE(getRelocationEntry(SectionID, Obj, RelI)); 68153323Srodrigc RE.Addend = memcpyAddend(RE); 69153323Srodrigc RelocationValueRef Value; 70153323Srodrigc if (auto ValueOrErr = getRelocationValueRef(Obj, RelI, RE, ObjSectionToID)) 71153323Srodrigc Value = *ValueOrErr; 72153323Srodrigc else 73153323Srodrigc return ValueOrErr.takeError(); 74153323Srodrigc 75153323Srodrigc // Addends for external, PC-rel relocations on i386 point back to the zero 76153323Srodrigc // offset. Calculate the final offset from the relocation target instead. 77153323Srodrigc // This allows us to use the same logic for both external and internal 78153323Srodrigc // relocations in resolveI386RelocationRef. 79153323Srodrigc // bool IsExtern = Obj.getPlainRelocationExternal(RelInfo); 80153323Srodrigc // if (IsExtern && RE.IsPCRel) { 81153323Srodrigc // uint64_t RelocAddr = 0; 82153323Srodrigc // RelI->getAddress(RelocAddr); 83153323Srodrigc // Value.Addend += RelocAddr + 4; 84153323Srodrigc // } 85153323Srodrigc if (RE.IsPCRel) 86153323Srodrigc makeValueAddendPCRel(Value, RelI, 1 << RE.Size); 87153323Srodrigc 88153323Srodrigc RE.Addend = Value.Offset; 89153323Srodrigc 90153323Srodrigc if (Value.SymbolName) 91153323Srodrigc addRelocationForSymbol(RE, Value.SymbolName); 92153323Srodrigc else 93153323Srodrigc addRelocationForSection(RE, Value.SectionID); 94153323Srodrigc 95153323Srodrigc return ++RelI; 96153323Srodrigc } 97153323Srodrigc 98153323Srodrigc void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override { 99153323Srodrigc LLVM_DEBUG(dumpRelocationToResolve(RE, Value)); 100153323Srodrigc 101153323Srodrigc const SectionEntry &Section = Sections[RE.SectionID]; 102153323Srodrigc uint8_t *LocalAddress = Section.getAddressWithOffset(RE.Offset); 103153323Srodrigc 104153323Srodrigc if (RE.IsPCRel) { 105153323Srodrigc uint64_t FinalAddress = Section.getLoadAddressWithOffset(RE.Offset); 106153323Srodrigc Value -= FinalAddress + 4; // see MachOX86_64::resolveRelocation. 107159451Srodrigc } 108159451Srodrigc 109153323Srodrigc switch (RE.RelType) { 110153323Srodrigc case MachO::GENERIC_RELOC_VANILLA: 111153323Srodrigc 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