Home | History | Annotate | Download | only in Targets
      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:
     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.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   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 
    178   unsigned getStubAlignment() override { return 1; }
    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   }
    189   void deregisterEHFrames() override {
    190     // Stub
    191   }
    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