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.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     // 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 
    180   unsigned getStubAlignment() override { return 1; }
    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   }
    191   void deregisterEHFrames() override {
    192     // Stub
    193   }
    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