RuntimeDyldCOFFX86_64.h revision 288943
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 23namespace llvm { 24 25class RuntimeDyldCOFFX86_64 : public RuntimeDyldCOFF { 26 27private: 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 34public: 35 RuntimeDyldCOFFX86_64(RuntimeDyld::MemoryManager &MM, 36 RuntimeDyld::SymbolResolver &Resolver) 37 : RuntimeDyldCOFF(MM, Resolver) {} 38 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. 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 112 relocation_iterator processRelocationRef(unsigned SectionID, 113 relocation_iterator RelI, 114 const ObjectFile &Obj, 115 ObjSectionToIDMap &ObjSectionToID, 116 StubMap &Stubs) override { 117 // If possible, find the symbol referred to in the relocation, 118 // and the section that contains it. 119 symbol_iterator Symbol = RelI->getSymbol(); 120 if (Symbol == Obj.symbol_end()) 121 report_fatal_error("Unknown symbol in relocation"); 122 section_iterator SecI(Obj.section_end()); 123 Symbol->getSection(SecI); 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.ObjAddress + 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 uint32_t *Displacement = (uint32_t *)ObjTarget; 144 Addend = *Displacement; 145 break; 146 } 147 148 case COFF::IMAGE_REL_AMD64_ADDR64: { 149 uint64_t *Displacement = (uint64_t *)ObjTarget; 150 Addend = *Displacement; 151 break; 152 } 153 154 default: 155 break; 156 } 157 158 ErrorOr<StringRef> TargetNameOrErr = Symbol->getName(); 159 if (std::error_code EC = TargetNameOrErr.getError()) 160 report_fatal_error(EC.message()); 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 findOrEmitSection(Obj, *SecI, IsCode, ObjSectionToID); 174 uint64_t TargetOffset = getSymbolOffset(*Symbol); 175 RelocationEntry RE(SectionID, Offset, RelType, TargetOffset + Addend); 176 addRelocationForSection(RE, TargetSectionID); 177 } 178 179 return ++RelI; 180 } 181 182 unsigned getStubAlignment() override { return 1; } 183 void registerEHFrames() override { 184 for (auto const &EHFrameSID : UnregisteredEHFrameSections) { 185 uint8_t *EHFrameAddr = Sections[EHFrameSID].Address; 186 uint64_t EHFrameLoadAddr = Sections[EHFrameSID].LoadAddress; 187 size_t EHFrameSize = Sections[EHFrameSID].Size; 188 MemMgr.registerEHFrames(EHFrameAddr, EHFrameLoadAddr, EHFrameSize); 189 RegisteredEHFrameSections.push_back(EHFrameSID); 190 } 191 UnregisteredEHFrameSections.clear(); 192 } 193 void deregisterEHFrames() override { 194 // Stub 195 } 196 void finalizeLoad(const ObjectFile &Obj, 197 ObjSectionToIDMap &SectionMap) override { 198 // Look for and record the EH frame section IDs. 199 for (const auto &SectionPair : SectionMap) { 200 const SectionRef &Section = SectionPair.first; 201 StringRef Name; 202 Check(Section.getName(Name)); 203 // Note unwind info is split across .pdata and .xdata, so this 204 // may not be sufficiently general for all users. 205 if (Name == ".xdata") { 206 UnregisteredEHFrameSections.push_back(SectionPair.second); 207 } 208 } 209 } 210}; 211 212} // end namespace llvm 213 214#undef DEBUG_TYPE 215 216#endif 217