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