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 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 RuntimeDyldMachOX86_64(RTDyldMemoryManager * MM)25 RuntimeDyldMachOX86_64(RTDyldMemoryManager *MM) 26 : RuntimeDyldMachOCRTPBase(MM) {} 27 getMaxStubSize()28 unsigned getMaxStubSize() override { return 8; } 29 getStubAlignment()30 unsigned getStubAlignment() override { return 1; } 31 32 relocation_iterator processRelocationRef(unsigned SectionID,relocation_iterator RelI,const ObjectFile & BaseObjT,ObjSectionToIDMap & ObjSectionToID,StubMap & Stubs)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 42 assert(!Obj.isRelocationScattered(RelInfo) && 43 "Scattered relocations not supported on X86_64"); 44 45 RelocationEntry RE(getRelocationEntry(SectionID, Obj, RelI)); 46 RE.Addend = memcpyAddend(RE); 47 RelocationValueRef Value( 48 getRelocationValueRef(Obj, RelI, RE, ObjSectionToID)); 49 50 bool IsExtern = Obj.getPlainRelocationExternal(RelInfo); 51 if (!IsExtern && RE.IsPCRel) 52 makeValueAddendPCRel(Value, Obj, RelI, 1 << RE.Size); 53 54 if (RE.RelType == MachO::X86_64_RELOC_GOT || 55 RE.RelType == MachO::X86_64_RELOC_GOT_LOAD) 56 processGOTRelocation(RE, Value, Stubs); 57 else { 58 RE.Addend = Value.Offset; 59 if (Value.SymbolName) 60 addRelocationForSymbol(RE, Value.SymbolName); 61 else 62 addRelocationForSection(RE, Value.SectionID); 63 } 64 65 return ++RelI; 66 } 67 resolveRelocation(const RelocationEntry & RE,uint64_t Value)68 void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override { 69 DEBUG(dumpRelocationToResolve(RE, Value)); 70 const SectionEntry &Section = Sections[RE.SectionID]; 71 uint8_t *LocalAddress = Section.Address + RE.Offset; 72 73 // If the relocation is PC-relative, the value to be encoded is the 74 // pointer difference. 75 if (RE.IsPCRel) { 76 // FIXME: It seems this value needs to be adjusted by 4 for an effective 77 // PC address. Is that expected? Only for branches, perhaps? 78 uint64_t FinalAddress = Section.LoadAddress + RE.Offset; 79 Value -= FinalAddress + 4; 80 } 81 82 switch (RE.RelType) { 83 default: 84 llvm_unreachable("Invalid relocation type!"); 85 case MachO::X86_64_RELOC_SIGNED_1: 86 case MachO::X86_64_RELOC_SIGNED_2: 87 case MachO::X86_64_RELOC_SIGNED_4: 88 case MachO::X86_64_RELOC_SIGNED: 89 case MachO::X86_64_RELOC_UNSIGNED: 90 case MachO::X86_64_RELOC_BRANCH: 91 writeBytesUnaligned(Value + RE.Addend, LocalAddress, 1 << RE.Size); 92 break; 93 case MachO::X86_64_RELOC_GOT_LOAD: 94 case MachO::X86_64_RELOC_GOT: 95 case MachO::X86_64_RELOC_SUBTRACTOR: 96 case MachO::X86_64_RELOC_TLV: 97 Error("Relocation type not implemented yet!"); 98 } 99 } 100 finalizeSection(const ObjectFile & Obj,unsigned SectionID,const SectionRef & Section)101 void finalizeSection(const ObjectFile &Obj, unsigned SectionID, 102 const SectionRef &Section) {} 103 104 private: processGOTRelocation(const RelocationEntry & RE,RelocationValueRef & Value,StubMap & Stubs)105 void processGOTRelocation(const RelocationEntry &RE, 106 RelocationValueRef &Value, StubMap &Stubs) { 107 SectionEntry &Section = Sections[RE.SectionID]; 108 assert(RE.IsPCRel); 109 assert(RE.Size == 2); 110 Value.Offset -= RE.Addend; 111 RuntimeDyldMachO::StubMap::const_iterator i = Stubs.find(Value); 112 uint8_t *Addr; 113 if (i != Stubs.end()) { 114 Addr = Section.Address + i->second; 115 } else { 116 Stubs[Value] = Section.StubOffset; 117 uint8_t *GOTEntry = Section.Address + Section.StubOffset; 118 RelocationEntry GOTRE(RE.SectionID, Section.StubOffset, 119 MachO::X86_64_RELOC_UNSIGNED, Value.Offset, false, 120 3); 121 if (Value.SymbolName) 122 addRelocationForSymbol(GOTRE, Value.SymbolName); 123 else 124 addRelocationForSection(GOTRE, Value.SectionID); 125 Section.StubOffset += 8; 126 Addr = GOTEntry; 127 } 128 RelocationEntry TargetRE(RE.SectionID, RE.Offset, 129 MachO::X86_64_RELOC_UNSIGNED, RE.Addend, true, 2); 130 resolveRelocation(TargetRE, (uint64_t)Addr); 131 } 132 }; 133 } 134 135 #undef DEBUG_TYPE 136 137 #endif 138