1 //===-- RuntimeDyldCOFFX86_64.h --- COFF/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 // COFF x86_x64 support for MC-JIT runtime dynamic linker. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDCOFF86_64_H 15 #define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDCOFF86_64_H 16 17 #include "llvm/Object/COFF.h" 18 #include "llvm/Support/COFF.h" 19 #include "../RuntimeDyldCOFF.h" 20 21 #define DEBUG_TYPE "dyld" 22 23 namespace llvm { 24 25 class RuntimeDyldCOFFX86_64 : public RuntimeDyldCOFF { 26 27 private: 28 // When a module is loaded we save the SectionID of the unwind 29 // sections in a table until we receive a request to register all 30 // unregisteredEH frame sections with the memory manager. 31 SmallVector<SID, 2> UnregisteredEHFrameSections; 32 SmallVector<SID, 2> RegisteredEHFrameSections; 33 34 public: RuntimeDyldCOFFX86_64(RuntimeDyld::MemoryManager & MM,RuntimeDyld::SymbolResolver & Resolver)35 RuntimeDyldCOFFX86_64(RuntimeDyld::MemoryManager &MM, 36 RuntimeDyld::SymbolResolver &Resolver) 37 : RuntimeDyldCOFF(MM, Resolver) {} 38 getMaxStubSize()39 unsigned getMaxStubSize() override { 40 return 6; // 2-byte jmp instruction + 32-bit relative address 41 } 42 43 // The target location for the relocation is described by RE.SectionID and 44 // RE.Offset. RE.SectionID can be used to find the SectionEntry. Each 45 // SectionEntry has three members describing its location. 46 // SectionEntry::Address is the address at which the section has been loaded 47 // into memory in the current (host) process. SectionEntry::LoadAddress is 48 // the address that the section will have in the target process. 49 // SectionEntry::ObjAddress is the address of the bits for this section in the 50 // original emitted object image (also in the current address space). 51 // 52 // Relocations will be applied as if the section were loaded at 53 // SectionEntry::LoadAddress, but they will be applied at an address based 54 // on SectionEntry::Address. SectionEntry::ObjAddress will be used to refer 55 // to Target memory contents if they are required for value calculations. 56 // 57 // The Value parameter here is the load address of the symbol for the 58 // relocation to be applied. For relocations which refer to symbols in the 59 // current object Value will be the LoadAddress of the section in which 60 // the symbol resides (RE.Addend provides additional information about the 61 // symbol location). For external symbols, Value will be the address of the 62 // symbol in the target address space. resolveRelocation(const RelocationEntry & RE,uint64_t Value)63 void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override { 64 const SectionEntry &Section = Sections[RE.SectionID]; 65 uint8_t *Target = Section.getAddressWithOffset(RE.Offset); 66 67 switch (RE.RelType) { 68 69 case COFF::IMAGE_REL_AMD64_REL32: 70 case COFF::IMAGE_REL_AMD64_REL32_1: 71 case COFF::IMAGE_REL_AMD64_REL32_2: 72 case COFF::IMAGE_REL_AMD64_REL32_3: 73 case COFF::IMAGE_REL_AMD64_REL32_4: 74 case COFF::IMAGE_REL_AMD64_REL32_5: { 75 uint64_t FinalAddress = Section.getLoadAddressWithOffset(RE.Offset); 76 // Delta is the distance from the start of the reloc to the end of the 77 // instruction with the reloc. 78 uint64_t Delta = 4 + (RE.RelType - COFF::IMAGE_REL_AMD64_REL32); 79 Value -= FinalAddress + Delta; 80 uint64_t Result = Value + RE.Addend; 81 assert(((int64_t)Result <= INT32_MAX) && "Relocation overflow"); 82 assert(((int64_t)Result >= INT32_MIN) && "Relocation underflow"); 83 writeBytesUnaligned(Result, Target, 4); 84 break; 85 } 86 87 case COFF::IMAGE_REL_AMD64_ADDR32NB: { 88 // Note ADDR32NB requires a well-established notion of 89 // image base. This address must be less than or equal 90 // to every section's load address, and all sections must be 91 // within a 32 bit offset from the base. 92 // 93 // For now we just set these to zero. 94 writeBytesUnaligned(0, Target, 4); 95 break; 96 } 97 98 case COFF::IMAGE_REL_AMD64_ADDR64: { 99 writeBytesUnaligned(Value + RE.Addend, Target, 8); 100 break; 101 } 102 103 default: 104 llvm_unreachable("Relocation type not implemented yet!"); 105 break; 106 } 107 } 108 processRelocationRef(unsigned SectionID,relocation_iterator RelI,const ObjectFile & Obj,ObjSectionToIDMap & ObjSectionToID,StubMap & Stubs)109 relocation_iterator processRelocationRef(unsigned SectionID, 110 relocation_iterator RelI, 111 const ObjectFile &Obj, 112 ObjSectionToIDMap &ObjSectionToID, 113 StubMap &Stubs) override { 114 // If possible, find the symbol referred to in the relocation, 115 // and the section that contains it. 116 symbol_iterator Symbol = RelI->getSymbol(); 117 if (Symbol == Obj.symbol_end()) 118 report_fatal_error("Unknown symbol in relocation"); 119 section_iterator SecI = *Symbol->getSection(); 120 // If there is no section, this must be an external reference. 121 const bool IsExtern = SecI == Obj.section_end(); 122 123 // Determine the Addend used to adjust the relocation value. 124 uint64_t RelType = RelI->getType(); 125 uint64_t Offset = RelI->getOffset(); 126 uint64_t Addend = 0; 127 SectionEntry &Section = Sections[SectionID]; 128 uintptr_t ObjTarget = Section.getObjAddress() + Offset; 129 130 switch (RelType) { 131 132 case COFF::IMAGE_REL_AMD64_REL32: 133 case COFF::IMAGE_REL_AMD64_REL32_1: 134 case COFF::IMAGE_REL_AMD64_REL32_2: 135 case COFF::IMAGE_REL_AMD64_REL32_3: 136 case COFF::IMAGE_REL_AMD64_REL32_4: 137 case COFF::IMAGE_REL_AMD64_REL32_5: 138 case COFF::IMAGE_REL_AMD64_ADDR32NB: { 139 uint8_t *Displacement = (uint8_t *)ObjTarget; 140 Addend = readBytesUnaligned(Displacement, 4); 141 break; 142 } 143 144 case COFF::IMAGE_REL_AMD64_ADDR64: { 145 uint8_t *Displacement = (uint8_t *)ObjTarget; 146 Addend = readBytesUnaligned(Displacement, 8); 147 break; 148 } 149 150 default: 151 break; 152 } 153 154 ErrorOr<StringRef> TargetNameOrErr = Symbol->getName(); 155 if (std::error_code EC = TargetNameOrErr.getError()) 156 report_fatal_error(EC.message()); 157 StringRef TargetName = *TargetNameOrErr; 158 159 DEBUG(dbgs() << "\t\tIn Section " << SectionID << " Offset " << Offset 160 << " RelType: " << RelType << " TargetName: " << TargetName 161 << " Addend " << Addend << "\n"); 162 163 if (IsExtern) { 164 RelocationEntry RE(SectionID, Offset, RelType, Addend); 165 addRelocationForSymbol(RE, TargetName); 166 } else { 167 bool IsCode = SecI->isText(); 168 unsigned TargetSectionID = 169 findOrEmitSection(Obj, *SecI, IsCode, ObjSectionToID); 170 uint64_t TargetOffset = getSymbolOffset(*Symbol); 171 RelocationEntry RE(SectionID, Offset, RelType, TargetOffset + Addend); 172 addRelocationForSection(RE, TargetSectionID); 173 } 174 175 return ++RelI; 176 } 177 getStubAlignment()178 unsigned getStubAlignment() override { return 1; } registerEHFrames()179 void registerEHFrames() override { 180 for (auto const &EHFrameSID : UnregisteredEHFrameSections) { 181 uint8_t *EHFrameAddr = Sections[EHFrameSID].getAddress(); 182 uint64_t EHFrameLoadAddr = Sections[EHFrameSID].getLoadAddress(); 183 size_t EHFrameSize = Sections[EHFrameSID].getSize(); 184 MemMgr.registerEHFrames(EHFrameAddr, EHFrameLoadAddr, EHFrameSize); 185 RegisteredEHFrameSections.push_back(EHFrameSID); 186 } 187 UnregisteredEHFrameSections.clear(); 188 } deregisterEHFrames()189 void deregisterEHFrames() override { 190 // Stub 191 } finalizeLoad(const ObjectFile & Obj,ObjSectionToIDMap & SectionMap)192 void finalizeLoad(const ObjectFile &Obj, 193 ObjSectionToIDMap &SectionMap) override { 194 // Look for and record the EH frame section IDs. 195 for (const auto &SectionPair : SectionMap) { 196 const SectionRef &Section = SectionPair.first; 197 StringRef Name; 198 Check(Section.getName(Name)); 199 // Note unwind info is split across .pdata and .xdata, so this 200 // may not be sufficiently general for all users. 201 if (Name == ".xdata") { 202 UnregisteredEHFrameSections.push_back(SectionPair.second); 203 } 204 } 205 } 206 }; 207 208 } // end namespace llvm 209 210 #undef DEBUG_TYPE 211 212 #endif 213