1 //===-- RuntimeDyldMachOX86_64.h ---- MachO/X86_64 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_RUNTIMEDYLDMACHOX86_64_H 10 #define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOX86_64_H 11 12 #include "../RuntimeDyldMachO.h" 13 14 #define DEBUG_TYPE "dyld" 15 16 namespace llvm { 17 18 class RuntimeDyldMachOX86_64 19 : public RuntimeDyldMachOCRTPBase<RuntimeDyldMachOX86_64> { 20 public: 21 22 typedef uint64_t TargetPtrT; 23 24 RuntimeDyldMachOX86_64(RuntimeDyld::MemoryManager &MM, 25 JITSymbolResolver &Resolver) 26 : RuntimeDyldMachOCRTPBase(MM, Resolver) {} 27 28 unsigned getMaxStubSize() const override { return 8; } 29 30 Align getStubAlignment() override { return Align(8); } 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 (RelType == MachO::X86_64_RELOC_SUBTRACTOR) 44 return processSubtractRelocation(SectionID, RelI, Obj, ObjSectionToID); 45 46 assert(!Obj.isRelocationScattered(RelInfo) && 47 "Scattered relocations not supported on X86_64"); 48 49 RelocationEntry RE(getRelocationEntry(SectionID, Obj, RelI)); 50 RE.Addend = memcpyAddend(RE); 51 RelocationValueRef Value; 52 if (auto ValueOrErr = getRelocationValueRef(Obj, RelI, RE, ObjSectionToID)) 53 Value = *ValueOrErr; 54 else 55 return ValueOrErr.takeError(); 56 57 bool IsExtern = Obj.getPlainRelocationExternal(RelInfo); 58 if (!IsExtern && RE.IsPCRel) 59 makeValueAddendPCRel(Value, RelI, 1 << RE.Size); 60 61 switch (RelType) { 62 UNIMPLEMENTED_RELOC(MachO::X86_64_RELOC_TLV); 63 default: 64 if (RelType > MachO::X86_64_RELOC_TLV) 65 return make_error<RuntimeDyldError>(("MachO X86_64 relocation type " + 66 Twine(RelType) + 67 " is out of range").str()); 68 break; 69 } 70 71 if (RE.RelType == MachO::X86_64_RELOC_GOT || 72 RE.RelType == MachO::X86_64_RELOC_GOT_LOAD) 73 processGOTRelocation(RE, Value, Stubs); 74 else { 75 RE.Addend = Value.Offset; 76 if (Value.SymbolName) 77 addRelocationForSymbol(RE, Value.SymbolName); 78 else 79 addRelocationForSection(RE, Value.SectionID); 80 } 81 82 return ++RelI; 83 } 84 85 void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override { 86 LLVM_DEBUG(dumpRelocationToResolve(RE, Value)); 87 const SectionEntry &Section = Sections[RE.SectionID]; 88 uint8_t *LocalAddress = Section.getAddressWithOffset(RE.Offset); 89 90 // If the relocation is PC-relative, the value to be encoded is the 91 // pointer difference. 92 if (RE.IsPCRel) { 93 // FIXME: It seems this value needs to be adjusted by 4 for an effective 94 // PC address. Is that expected? Only for branches, perhaps? 95 uint64_t FinalAddress = Section.getLoadAddressWithOffset(RE.Offset); 96 Value -= FinalAddress + 4; 97 } 98 99 switch (RE.RelType) { 100 default: 101 llvm_unreachable("Invalid relocation type!"); 102 case MachO::X86_64_RELOC_SIGNED_1: 103 case MachO::X86_64_RELOC_SIGNED_2: 104 case MachO::X86_64_RELOC_SIGNED_4: 105 case MachO::X86_64_RELOC_SIGNED: 106 case MachO::X86_64_RELOC_UNSIGNED: 107 case MachO::X86_64_RELOC_BRANCH: 108 writeBytesUnaligned(Value + RE.Addend, LocalAddress, 1 << RE.Size); 109 break; 110 case MachO::X86_64_RELOC_SUBTRACTOR: { 111 uint64_t SectionABase = Sections[RE.Sections.SectionA].getLoadAddress(); 112 uint64_t SectionBBase = Sections[RE.Sections.SectionB].getLoadAddress(); 113 assert((Value == SectionABase || Value == SectionBBase) && 114 "Unexpected SUBTRACTOR relocation value."); 115 Value = SectionABase - SectionBBase + RE.Addend; 116 writeBytesUnaligned(Value, LocalAddress, 1 << RE.Size); 117 break; 118 } 119 } 120 } 121 122 Error finalizeSection(const ObjectFile &Obj, unsigned SectionID, 123 const SectionRef &Section) { 124 return Error::success(); 125 } 126 127 private: 128 void processGOTRelocation(const RelocationEntry &RE, 129 RelocationValueRef &Value, StubMap &Stubs) { 130 SectionEntry &Section = Sections[RE.SectionID]; 131 assert(RE.IsPCRel); 132 assert(RE.Size == 2); 133 Value.Offset -= RE.Addend; 134 RuntimeDyldMachO::StubMap::const_iterator i = Stubs.find(Value); 135 uint8_t *Addr; 136 if (i != Stubs.end()) { 137 Addr = Section.getAddressWithOffset(i->second); 138 } else { 139 Stubs[Value] = Section.getStubOffset(); 140 uint8_t *GOTEntry = Section.getAddressWithOffset(Section.getStubOffset()); 141 RelocationEntry GOTRE(RE.SectionID, Section.getStubOffset(), 142 MachO::X86_64_RELOC_UNSIGNED, Value.Offset, false, 143 3); 144 if (Value.SymbolName) 145 addRelocationForSymbol(GOTRE, Value.SymbolName); 146 else 147 addRelocationForSection(GOTRE, Value.SectionID); 148 Section.advanceStubOffset(8); 149 Addr = GOTEntry; 150 } 151 RelocationEntry TargetRE(RE.SectionID, RE.Offset, 152 MachO::X86_64_RELOC_UNSIGNED, RE.Addend, true, 2); 153 resolveRelocation(TargetRE, (uint64_t)Addr); 154 } 155 156 Expected<relocation_iterator> 157 processSubtractRelocation(unsigned SectionID, relocation_iterator RelI, 158 const MachOObjectFile &BaseObj, 159 ObjSectionToIDMap &ObjSectionToID) { 160 const MachOObjectFile &Obj = 161 static_cast<const MachOObjectFile&>(BaseObj); 162 MachO::any_relocation_info RE = 163 Obj.getRelocation(RelI->getRawDataRefImpl()); 164 165 unsigned Size = Obj.getAnyRelocationLength(RE); 166 uint64_t Offset = RelI->getOffset(); 167 uint8_t *LocalAddress = Sections[SectionID].getAddressWithOffset(Offset); 168 unsigned NumBytes = 1 << Size; 169 int64_t Addend = 170 SignExtend64(readBytesUnaligned(LocalAddress, NumBytes), NumBytes * 8); 171 172 unsigned SectionBID = ~0U; 173 uint64_t SectionBOffset = 0; 174 175 MachO::any_relocation_info RelInfo = 176 Obj.getRelocation(RelI->getRawDataRefImpl()); 177 178 bool AIsExternal = BaseObj.getPlainRelocationExternal(RelInfo); 179 180 if (AIsExternal) { 181 Expected<StringRef> SubtrahendNameOrErr = RelI->getSymbol()->getName(); 182 if (!SubtrahendNameOrErr) 183 return SubtrahendNameOrErr.takeError(); 184 auto SubtrahendI = GlobalSymbolTable.find(*SubtrahendNameOrErr); 185 SectionBID = SubtrahendI->second.getSectionID(); 186 SectionBOffset = SubtrahendI->second.getOffset(); 187 } else { 188 SectionRef SecB = Obj.getAnyRelocationSection(RelInfo); 189 bool IsCode = SecB.isText(); 190 Expected<unsigned> SectionBIDOrErr = 191 findOrEmitSection(Obj, SecB, IsCode, ObjSectionToID); 192 if (!SectionBIDOrErr) 193 return SectionBIDOrErr.takeError(); 194 SectionBID = *SectionBIDOrErr; 195 Addend += SecB.getAddress(); 196 } 197 198 ++RelI; 199 200 unsigned SectionAID = ~0U; 201 uint64_t SectionAOffset = 0; 202 203 RelInfo = Obj.getRelocation(RelI->getRawDataRefImpl()); 204 205 bool BIsExternal = BaseObj.getPlainRelocationExternal(RelInfo); 206 if (BIsExternal) { 207 Expected<StringRef> MinuendNameOrErr = RelI->getSymbol()->getName(); 208 if (!MinuendNameOrErr) 209 return MinuendNameOrErr.takeError(); 210 auto MinuendI = GlobalSymbolTable.find(*MinuendNameOrErr); 211 SectionAID = MinuendI->second.getSectionID(); 212 SectionAOffset = MinuendI->second.getOffset(); 213 } else { 214 SectionRef SecA = Obj.getAnyRelocationSection(RelInfo); 215 bool IsCode = SecA.isText(); 216 Expected<unsigned> SectionAIDOrErr = 217 findOrEmitSection(Obj, SecA, IsCode, ObjSectionToID); 218 if (!SectionAIDOrErr) 219 return SectionAIDOrErr.takeError(); 220 SectionAID = *SectionAIDOrErr; 221 Addend -= SecA.getAddress(); 222 } 223 224 RelocationEntry R(SectionID, Offset, MachO::X86_64_RELOC_SUBTRACTOR, (uint64_t)Addend, 225 SectionAID, SectionAOffset, SectionBID, SectionBOffset, 226 false, Size); 227 228 addRelocationForSection(R, SectionAID); 229 230 return ++RelI; 231 } 232 233 }; 234 } 235 236 #undef DEBUG_TYPE 237 238 #endif 239