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.Address + 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 uint32_t *TargetAddress = (uint32_t *)Target; 76 uint64_t FinalAddress = Section.LoadAddress + RE.Offset; 77 // Delta is the distance from the start of the reloc to the end of the 78 // instruction with the reloc. 79 uint64_t Delta = 4 + (RE.RelType - COFF::IMAGE_REL_AMD64_REL32); 80 Value -= FinalAddress + Delta; 81 uint64_t Result = Value + RE.Addend; 82 assert(((int64_t)Result <= INT32_MAX) && "Relocation overflow"); 83 assert(((int64_t)Result >= INT32_MIN) && "Relocation underflow"); 84 *TargetAddress = Result; 85 break; 86 } 87 88 case COFF::IMAGE_REL_AMD64_ADDR32NB: { 89 // Note ADDR32NB requires a well-established notion of 90 // image base. This address must be less than or equal 91 // to every section's load address, and all sections must be 92 // within a 32 bit offset from the base. 93 // 94 // For now we just set these to zero. 95 uint32_t *TargetAddress = (uint32_t *)Target; 96 *TargetAddress = 0; 97 break; 98 } 99 100 case COFF::IMAGE_REL_AMD64_ADDR64: { 101 uint64_t *TargetAddress = (uint64_t *)Target; 102 *TargetAddress = Value + RE.Addend; 103 break; 104 } 105 106 default: 107 llvm_unreachable("Relocation type not implemented yet!"); 108 break; 109 } 110 } 111 processRelocationRef(unsigned SectionID,relocation_iterator RelI,const ObjectFile & Obj,ObjSectionToIDMap & ObjSectionToID,StubMap & Stubs)112 relocation_iterator processRelocationRef(unsigned SectionID, 113 relocation_iterator RelI, 114 const ObjectFile &Obj, 115 ObjSectionToIDMap &ObjSectionToID, 116 StubMap &Stubs) override { 117 // Find the symbol referred to in the relocation, and 118 // get its section and offset. 119 // 120 // Insist for now that all symbols be resolvable within 121 // the scope of this object file. 122 symbol_iterator Symbol = RelI->getSymbol(); 123 if (Symbol == Obj.symbol_end()) 124 report_fatal_error("Unknown symbol in relocation"); 125 unsigned TargetSectionID = 0; 126 uint64_t TargetOffset = UnknownAddressOrSize; 127 section_iterator SecI(Obj.section_end()); 128 Symbol->getSection(SecI); 129 if (SecI == Obj.section_end()) 130 report_fatal_error("Unknown section in relocation"); 131 bool IsCode = SecI->isText(); 132 TargetSectionID = findOrEmitSection(Obj, *SecI, IsCode, ObjSectionToID); 133 TargetOffset = getSymbolOffset(*Symbol); 134 135 // Determine the Addend used to adjust the relocation value. 136 uint64_t RelType; 137 Check(RelI->getType(RelType)); 138 uint64_t Offset; 139 Check(RelI->getOffset(Offset)); 140 uint64_t Addend = 0; 141 SectionEntry &Section = Sections[SectionID]; 142 uintptr_t ObjTarget = Section.ObjAddress + Offset; 143 144 switch (RelType) { 145 146 case COFF::IMAGE_REL_AMD64_REL32: 147 case COFF::IMAGE_REL_AMD64_REL32_1: 148 case COFF::IMAGE_REL_AMD64_REL32_2: 149 case COFF::IMAGE_REL_AMD64_REL32_3: 150 case COFF::IMAGE_REL_AMD64_REL32_4: 151 case COFF::IMAGE_REL_AMD64_REL32_5: 152 case COFF::IMAGE_REL_AMD64_ADDR32NB: { 153 uint32_t *Displacement = (uint32_t *)ObjTarget; 154 Addend = *Displacement; 155 break; 156 } 157 158 case COFF::IMAGE_REL_AMD64_ADDR64: { 159 uint64_t *Displacement = (uint64_t *)ObjTarget; 160 Addend = *Displacement; 161 break; 162 } 163 164 default: 165 break; 166 } 167 168 StringRef TargetName; 169 Symbol->getName(TargetName); 170 DEBUG(dbgs() << "\t\tIn Section " << SectionID << " Offset " << Offset 171 << " RelType: " << RelType << " TargetName: " << TargetName 172 << " Addend " << Addend << "\n"); 173 174 RelocationEntry RE(SectionID, Offset, RelType, TargetOffset + Addend); 175 addRelocationForSection(RE, TargetSectionID); 176 177 return ++RelI; 178 } 179 getStubAlignment()180 unsigned getStubAlignment() override { return 1; } registerEHFrames()181 void registerEHFrames() override { 182 for (auto const &EHFrameSID : UnregisteredEHFrameSections) { 183 uint8_t *EHFrameAddr = Sections[EHFrameSID].Address; 184 uint64_t EHFrameLoadAddr = Sections[EHFrameSID].LoadAddress; 185 size_t EHFrameSize = Sections[EHFrameSID].Size; 186 MemMgr.registerEHFrames(EHFrameAddr, EHFrameLoadAddr, EHFrameSize); 187 RegisteredEHFrameSections.push_back(EHFrameSID); 188 } 189 UnregisteredEHFrameSections.clear(); 190 } deregisterEHFrames()191 void deregisterEHFrames() override { 192 // Stub 193 } finalizeLoad(const ObjectFile & Obj,ObjSectionToIDMap & SectionMap)194 void finalizeLoad(const ObjectFile &Obj, 195 ObjSectionToIDMap &SectionMap) override { 196 // Look for and record the EH frame section IDs. 197 for (const auto &SectionPair : SectionMap) { 198 const SectionRef &Section = SectionPair.first; 199 StringRef Name; 200 Check(Section.getName(Name)); 201 // Note unwind info is split across .pdata and .xdata, so this 202 // may not be sufficiently general for all users. 203 if (Name == ".xdata") { 204 UnregisteredEHFrameSections.push_back(SectionPair.second); 205 } 206 } 207 } 208 }; 209 210 } // end namespace llvm 211 212 #undef DEBUG_TYPE 213 214 #endif 215