RuntimeDyldCOFFX86_64.h revision 309124
1283625Sdim//===-- RuntimeDyldCOFFX86_64.h --- COFF/X86_64 specific code ---*- C++ -*-===// 2283625Sdim// 3283625Sdim// The LLVM Compiler Infrastructure 4283625Sdim// 5283625Sdim// This file is distributed under the University of Illinois Open Source 6283625Sdim// License. See LICENSE.TXT for details. 7283625Sdim// 8283625Sdim//===----------------------------------------------------------------------===// 9283625Sdim// 10283625Sdim// COFF x86_x64 support for MC-JIT runtime dynamic linker. 11283625Sdim// 12283625Sdim//===----------------------------------------------------------------------===// 13283625Sdim 14283625Sdim#ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDCOFF86_64_H 15283625Sdim#define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDCOFF86_64_H 16283625Sdim 17283625Sdim#include "llvm/Object/COFF.h" 18283625Sdim#include "llvm/Support/COFF.h" 19283625Sdim#include "../RuntimeDyldCOFF.h" 20283625Sdim 21283625Sdim#define DEBUG_TYPE "dyld" 22283625Sdim 23283625Sdimnamespace llvm { 24283625Sdim 25283625Sdimclass RuntimeDyldCOFFX86_64 : public RuntimeDyldCOFF { 26283625Sdim 27283625Sdimprivate: 28283625Sdim // When a module is loaded we save the SectionID of the unwind 29283625Sdim // sections in a table until we receive a request to register all 30283625Sdim // unregisteredEH frame sections with the memory manager. 31283625Sdim SmallVector<SID, 2> UnregisteredEHFrameSections; 32283625Sdim SmallVector<SID, 2> RegisteredEHFrameSections; 33283625Sdim 34283625Sdimpublic: 35283625Sdim RuntimeDyldCOFFX86_64(RuntimeDyld::MemoryManager &MM, 36283625Sdim RuntimeDyld::SymbolResolver &Resolver) 37283625Sdim : RuntimeDyldCOFF(MM, Resolver) {} 38283625Sdim 39283625Sdim unsigned getMaxStubSize() override { 40283625Sdim return 6; // 2-byte jmp instruction + 32-bit relative address 41283625Sdim } 42283625Sdim 43283625Sdim // The target location for the relocation is described by RE.SectionID and 44283625Sdim // RE.Offset. RE.SectionID can be used to find the SectionEntry. Each 45283625Sdim // SectionEntry has three members describing its location. 46283625Sdim // SectionEntry::Address is the address at which the section has been loaded 47283625Sdim // into memory in the current (host) process. SectionEntry::LoadAddress is 48283625Sdim // the address that the section will have in the target process. 49283625Sdim // SectionEntry::ObjAddress is the address of the bits for this section in the 50283625Sdim // original emitted object image (also in the current address space). 51283625Sdim // 52283625Sdim // Relocations will be applied as if the section were loaded at 53283625Sdim // SectionEntry::LoadAddress, but they will be applied at an address based 54283625Sdim // on SectionEntry::Address. SectionEntry::ObjAddress will be used to refer 55283625Sdim // to Target memory contents if they are required for value calculations. 56283625Sdim // 57283625Sdim // The Value parameter here is the load address of the symbol for the 58283625Sdim // relocation to be applied. For relocations which refer to symbols in the 59283625Sdim // current object Value will be the LoadAddress of the section in which 60283625Sdim // the symbol resides (RE.Addend provides additional information about the 61283625Sdim // symbol location). For external symbols, Value will be the address of the 62283625Sdim // symbol in the target address space. 63283625Sdim void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override { 64283625Sdim const SectionEntry &Section = Sections[RE.SectionID]; 65296417Sdim uint8_t *Target = Section.getAddressWithOffset(RE.Offset); 66283625Sdim 67283625Sdim switch (RE.RelType) { 68283625Sdim 69283625Sdim case COFF::IMAGE_REL_AMD64_REL32: 70283625Sdim case COFF::IMAGE_REL_AMD64_REL32_1: 71283625Sdim case COFF::IMAGE_REL_AMD64_REL32_2: 72283625Sdim case COFF::IMAGE_REL_AMD64_REL32_3: 73283625Sdim case COFF::IMAGE_REL_AMD64_REL32_4: 74283625Sdim case COFF::IMAGE_REL_AMD64_REL32_5: { 75296417Sdim uint64_t FinalAddress = Section.getLoadAddressWithOffset(RE.Offset); 76283625Sdim // Delta is the distance from the start of the reloc to the end of the 77283625Sdim // instruction with the reloc. 78283625Sdim uint64_t Delta = 4 + (RE.RelType - COFF::IMAGE_REL_AMD64_REL32); 79283625Sdim Value -= FinalAddress + Delta; 80283625Sdim uint64_t Result = Value + RE.Addend; 81283625Sdim assert(((int64_t)Result <= INT32_MAX) && "Relocation overflow"); 82283625Sdim assert(((int64_t)Result >= INT32_MIN) && "Relocation underflow"); 83296417Sdim writeBytesUnaligned(Result, Target, 4); 84283625Sdim break; 85283625Sdim } 86283625Sdim 87283625Sdim case COFF::IMAGE_REL_AMD64_ADDR32NB: { 88283625Sdim // Note ADDR32NB requires a well-established notion of 89283625Sdim // image base. This address must be less than or equal 90283625Sdim // to every section's load address, and all sections must be 91283625Sdim // within a 32 bit offset from the base. 92283625Sdim // 93283625Sdim // For now we just set these to zero. 94296417Sdim writeBytesUnaligned(0, Target, 4); 95283625Sdim break; 96283625Sdim } 97283625Sdim 98283625Sdim case COFF::IMAGE_REL_AMD64_ADDR64: { 99296417Sdim writeBytesUnaligned(Value + RE.Addend, Target, 8); 100283625Sdim break; 101283625Sdim } 102283625Sdim 103283625Sdim default: 104283625Sdim llvm_unreachable("Relocation type not implemented yet!"); 105283625Sdim break; 106283625Sdim } 107283625Sdim } 108283625Sdim 109309124Sdim Expected<relocation_iterator> 110309124Sdim processRelocationRef(unsigned SectionID, 111309124Sdim relocation_iterator RelI, 112309124Sdim const ObjectFile &Obj, 113309124Sdim ObjSectionToIDMap &ObjSectionToID, 114309124Sdim StubMap &Stubs) override { 115283625Sdim // If possible, find the symbol referred to in the relocation, 116283625Sdim // and the section that contains it. 117283625Sdim symbol_iterator Symbol = RelI->getSymbol(); 118283625Sdim if (Symbol == Obj.symbol_end()) 119283625Sdim report_fatal_error("Unknown symbol in relocation"); 120309124Sdim auto SectionOrError = Symbol->getSection(); 121309124Sdim if (!SectionOrError) 122309124Sdim return SectionOrError.takeError(); 123309124Sdim section_iterator SecI = *SectionOrError; 124283625Sdim // If there is no section, this must be an external reference. 125283625Sdim const bool IsExtern = SecI == Obj.section_end(); 126283625Sdim 127283625Sdim // Determine the Addend used to adjust the relocation value. 128285181Sdim uint64_t RelType = RelI->getType(); 129285181Sdim uint64_t Offset = RelI->getOffset(); 130283625Sdim uint64_t Addend = 0; 131283625Sdim SectionEntry &Section = Sections[SectionID]; 132296417Sdim uintptr_t ObjTarget = Section.getObjAddress() + Offset; 133283625Sdim 134283625Sdim switch (RelType) { 135283625Sdim 136283625Sdim case COFF::IMAGE_REL_AMD64_REL32: 137283625Sdim case COFF::IMAGE_REL_AMD64_REL32_1: 138283625Sdim case COFF::IMAGE_REL_AMD64_REL32_2: 139283625Sdim case COFF::IMAGE_REL_AMD64_REL32_3: 140283625Sdim case COFF::IMAGE_REL_AMD64_REL32_4: 141283625Sdim case COFF::IMAGE_REL_AMD64_REL32_5: 142283625Sdim case COFF::IMAGE_REL_AMD64_ADDR32NB: { 143296417Sdim uint8_t *Displacement = (uint8_t *)ObjTarget; 144296417Sdim Addend = readBytesUnaligned(Displacement, 4); 145283625Sdim break; 146283625Sdim } 147283625Sdim 148283625Sdim case COFF::IMAGE_REL_AMD64_ADDR64: { 149296417Sdim uint8_t *Displacement = (uint8_t *)ObjTarget; 150296417Sdim Addend = readBytesUnaligned(Displacement, 8); 151283625Sdim break; 152283625Sdim } 153283625Sdim 154283625Sdim default: 155283625Sdim break; 156283625Sdim } 157283625Sdim 158309124Sdim Expected<StringRef> TargetNameOrErr = Symbol->getName(); 159309124Sdim if (!TargetNameOrErr) 160309124Sdim return TargetNameOrErr.takeError(); 161285181Sdim StringRef TargetName = *TargetNameOrErr; 162283625Sdim 163283625Sdim DEBUG(dbgs() << "\t\tIn Section " << SectionID << " Offset " << Offset 164283625Sdim << " RelType: " << RelType << " TargetName: " << TargetName 165283625Sdim << " Addend " << Addend << "\n"); 166283625Sdim 167283625Sdim if (IsExtern) { 168283625Sdim RelocationEntry RE(SectionID, Offset, RelType, Addend); 169283625Sdim addRelocationForSymbol(RE, TargetName); 170283625Sdim } else { 171283625Sdim bool IsCode = SecI->isText(); 172309124Sdim unsigned TargetSectionID; 173309124Sdim if (auto TargetSectionIDOrErr = 174309124Sdim findOrEmitSection(Obj, *SecI, IsCode, ObjSectionToID)) 175309124Sdim TargetSectionID = *TargetSectionIDOrErr; 176309124Sdim else 177309124Sdim return TargetSectionIDOrErr.takeError(); 178283625Sdim uint64_t TargetOffset = getSymbolOffset(*Symbol); 179283625Sdim RelocationEntry RE(SectionID, Offset, RelType, TargetOffset + Addend); 180283625Sdim addRelocationForSection(RE, TargetSectionID); 181283625Sdim } 182283625Sdim 183283625Sdim return ++RelI; 184283625Sdim } 185283625Sdim 186283625Sdim unsigned getStubAlignment() override { return 1; } 187283625Sdim void registerEHFrames() override { 188283625Sdim for (auto const &EHFrameSID : UnregisteredEHFrameSections) { 189296417Sdim uint8_t *EHFrameAddr = Sections[EHFrameSID].getAddress(); 190296417Sdim uint64_t EHFrameLoadAddr = Sections[EHFrameSID].getLoadAddress(); 191296417Sdim size_t EHFrameSize = Sections[EHFrameSID].getSize(); 192283625Sdim MemMgr.registerEHFrames(EHFrameAddr, EHFrameLoadAddr, EHFrameSize); 193283625Sdim RegisteredEHFrameSections.push_back(EHFrameSID); 194283625Sdim } 195283625Sdim UnregisteredEHFrameSections.clear(); 196283625Sdim } 197283625Sdim void deregisterEHFrames() override { 198283625Sdim // Stub 199283625Sdim } 200309124Sdim Error finalizeLoad(const ObjectFile &Obj, 201309124Sdim ObjSectionToIDMap &SectionMap) override { 202283625Sdim // Look for and record the EH frame section IDs. 203283625Sdim for (const auto &SectionPair : SectionMap) { 204283625Sdim const SectionRef &Section = SectionPair.first; 205283625Sdim StringRef Name; 206309124Sdim if (auto EC = Section.getName(Name)) 207309124Sdim return errorCodeToError(EC); 208283625Sdim // Note unwind info is split across .pdata and .xdata, so this 209283625Sdim // may not be sufficiently general for all users. 210283625Sdim if (Name == ".xdata") { 211283625Sdim UnregisteredEHFrameSections.push_back(SectionPair.second); 212283625Sdim } 213283625Sdim } 214309124Sdim return Error::success(); 215283625Sdim } 216283625Sdim}; 217283625Sdim 218283625Sdim} // end namespace llvm 219283625Sdim 220283625Sdim#undef DEBUG_TYPE 221283625Sdim 222283625Sdim#endif 223