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 109 Expected<relocation_iterator> processRelocationRef(unsigned SectionID,relocation_iterator RelI,const ObjectFile & Obj,ObjSectionToIDMap & ObjSectionToID,StubMap & Stubs)110 processRelocationRef(unsigned SectionID, 111 relocation_iterator RelI, 112 const ObjectFile &Obj, 113 ObjSectionToIDMap &ObjSectionToID, 114 StubMap &Stubs) override { 115 // If possible, find the symbol referred to in the relocation, 116 // and the section that contains it. 117 symbol_iterator Symbol = RelI->getSymbol(); 118 if (Symbol == Obj.symbol_end()) 119 report_fatal_error("Unknown symbol in relocation"); 120 auto SectionOrError = Symbol->getSection(); 121 if (!SectionOrError) 122 return SectionOrError.takeError(); 123 section_iterator SecI = *SectionOrError; 124 // If there is no section, this must be an external reference. 125 const bool IsExtern = SecI == Obj.section_end(); 126 127 // Determine the Addend used to adjust the relocation value. 128 uint64_t RelType = RelI->getType(); 129 uint64_t Offset = RelI->getOffset(); 130 uint64_t Addend = 0; 131 SectionEntry &Section = Sections[SectionID]; 132 uintptr_t ObjTarget = Section.getObjAddress() + Offset; 133 134 switch (RelType) { 135 136 case COFF::IMAGE_REL_AMD64_REL32: 137 case COFF::IMAGE_REL_AMD64_REL32_1: 138 case COFF::IMAGE_REL_AMD64_REL32_2: 139 case COFF::IMAGE_REL_AMD64_REL32_3: 140 case COFF::IMAGE_REL_AMD64_REL32_4: 141 case COFF::IMAGE_REL_AMD64_REL32_5: 142 case COFF::IMAGE_REL_AMD64_ADDR32NB: { 143 uint8_t *Displacement = (uint8_t *)ObjTarget; 144 Addend = readBytesUnaligned(Displacement, 4); 145 break; 146 } 147 148 case COFF::IMAGE_REL_AMD64_ADDR64: { 149 uint8_t *Displacement = (uint8_t *)ObjTarget; 150 Addend = readBytesUnaligned(Displacement, 8); 151 break; 152 } 153 154 default: 155 break; 156 } 157 158 Expected<StringRef> TargetNameOrErr = Symbol->getName(); 159 if (!TargetNameOrErr) 160 return TargetNameOrErr.takeError(); 161 StringRef TargetName = *TargetNameOrErr; 162 163 DEBUG(dbgs() << "\t\tIn Section " << SectionID << " Offset " << Offset 164 << " RelType: " << RelType << " TargetName: " << TargetName 165 << " Addend " << Addend << "\n"); 166 167 if (IsExtern) { 168 RelocationEntry RE(SectionID, Offset, RelType, Addend); 169 addRelocationForSymbol(RE, TargetName); 170 } else { 171 bool IsCode = SecI->isText(); 172 unsigned TargetSectionID; 173 if (auto TargetSectionIDOrErr = 174 findOrEmitSection(Obj, *SecI, IsCode, ObjSectionToID)) 175 TargetSectionID = *TargetSectionIDOrErr; 176 else 177 return TargetSectionIDOrErr.takeError(); 178 uint64_t TargetOffset = getSymbolOffset(*Symbol); 179 RelocationEntry RE(SectionID, Offset, RelType, TargetOffset + Addend); 180 addRelocationForSection(RE, TargetSectionID); 181 } 182 183 return ++RelI; 184 } 185 getStubAlignment()186 unsigned getStubAlignment() override { return 1; } registerEHFrames()187 void registerEHFrames() override { 188 for (auto const &EHFrameSID : UnregisteredEHFrameSections) { 189 uint8_t *EHFrameAddr = Sections[EHFrameSID].getAddress(); 190 uint64_t EHFrameLoadAddr = Sections[EHFrameSID].getLoadAddress(); 191 size_t EHFrameSize = Sections[EHFrameSID].getSize(); 192 MemMgr.registerEHFrames(EHFrameAddr, EHFrameLoadAddr, EHFrameSize); 193 RegisteredEHFrameSections.push_back(EHFrameSID); 194 } 195 UnregisteredEHFrameSections.clear(); 196 } deregisterEHFrames()197 void deregisterEHFrames() override { 198 // Stub 199 } finalizeLoad(const ObjectFile & Obj,ObjSectionToIDMap & SectionMap)200 Error finalizeLoad(const ObjectFile &Obj, 201 ObjSectionToIDMap &SectionMap) override { 202 // Look for and record the EH frame section IDs. 203 for (const auto &SectionPair : SectionMap) { 204 const SectionRef &Section = SectionPair.first; 205 StringRef Name; 206 if (auto EC = Section.getName(Name)) 207 return errorCodeToError(EC); 208 // Note unwind info is split across .pdata and .xdata, so this 209 // may not be sufficiently general for all users. 210 if (Name == ".xdata") { 211 UnregisteredEHFrameSections.push_back(SectionPair.second); 212 } 213 } 214 return Error::success(); 215 } 216 }; 217 218 } // end namespace llvm 219 220 #undef DEBUG_TYPE 221 222 #endif 223