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