LCOV - code coverage report
Current view: top level - lib/ExecutionEngine/RuntimeDyld/Targets - RuntimeDyldCOFFX86_64.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 71 96 74.0 %
Date: 2018-06-17 00:07:59 Functions: 8 9 88.9 %
Legend: Lines: hit not hit

          Line data    Source code
       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 "../RuntimeDyldCOFF.h"
      18             : #include "llvm/BinaryFormat/COFF.h"
      19             : #include "llvm/Object/COFF.h"
      20             : 
      21             : #define DEBUG_TYPE "dyld"
      22             : 
      23             : namespace llvm {
      24             : 
      25           6 : 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             :   uint64_t ImageBase;
      34             : 
      35             :   // Fake an __ImageBase pointer by returning the section with the lowest adress
      36             :   uint64_t getImageBase() {
      37           5 :     if (!ImageBase) {
      38           3 :       ImageBase = std::numeric_limits<uint64_t>::max();
      39          31 :       for (const SectionEntry &Section : Sections)
      40          28 :         ImageBase = std::min(ImageBase, Section.getLoadAddress());
      41             :     }
      42           5 :     return ImageBase;
      43             :   }
      44             : 
      45             :   void write32BitOffset(uint8_t *Target, int64_t Addend, uint64_t Delta) {
      46           5 :     uint64_t Result = Addend + Delta;
      47             :     assert(Result <= UINT32_MAX && "Relocation overflow");
      48           5 :     writeBytesUnaligned(Result, Target, 4);
      49             :   }
      50             : 
      51             : public:
      52             :   RuntimeDyldCOFFX86_64(RuntimeDyld::MemoryManager &MM,
      53             :                         JITSymbolResolver &Resolver)
      54           6 :     : RuntimeDyldCOFF(MM, Resolver), ImageBase(0) {}
      55             : 
      56          14 :   unsigned getStubAlignment() override { return 1; }
      57             : 
      58             :   // 2-byte jmp instruction + 32-bit relative address + 64-bit absolute jump
      59          10 :   unsigned getMaxStubSize() override { return 14; }
      60             : 
      61             :   // The target location for the relocation is described by RE.SectionID and
      62             :   // RE.Offset.  RE.SectionID can be used to find the SectionEntry.  Each
      63             :   // SectionEntry has three members describing its location.
      64             :   // SectionEntry::Address is the address at which the section has been loaded
      65             :   // into memory in the current (host) process.  SectionEntry::LoadAddress is
      66             :   // the address that the section will have in the target process.
      67             :   // SectionEntry::ObjAddress is the address of the bits for this section in the
      68             :   // original emitted object image (also in the current address space).
      69             :   //
      70             :   // Relocations will be applied as if the section were loaded at
      71             :   // SectionEntry::LoadAddress, but they will be applied at an address based
      72             :   // on SectionEntry::Address.  SectionEntry::ObjAddress will be used to refer
      73             :   // to Target memory contents if they are required for value calculations.
      74             :   //
      75             :   // The Value parameter here is the load address of the symbol for the
      76             :   // relocation to be applied.  For relocations which refer to symbols in the
      77             :   // current object Value will be the LoadAddress of the section in which
      78             :   // the symbol resides (RE.Addend provides additional information about the
      79             :   // symbol location).  For external symbols, Value will be the address of the
      80             :   // symbol in the target address space.
      81           7 :   void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override {
      82           7 :     const SectionEntry &Section = Sections[RE.SectionID];
      83           7 :     uint8_t *Target = Section.getAddressWithOffset(RE.Offset);
      84             : 
      85           7 :     switch (RE.RelType) {
      86             : 
      87           1 :     case COFF::IMAGE_REL_AMD64_REL32:
      88             :     case COFF::IMAGE_REL_AMD64_REL32_1:
      89             :     case COFF::IMAGE_REL_AMD64_REL32_2:
      90             :     case COFF::IMAGE_REL_AMD64_REL32_3:
      91             :     case COFF::IMAGE_REL_AMD64_REL32_4:
      92             :     case COFF::IMAGE_REL_AMD64_REL32_5: {
      93           1 :       uint64_t FinalAddress = Section.getLoadAddressWithOffset(RE.Offset);
      94             :       // Delta is the distance from the start of the reloc to the end of the
      95             :       // instruction with the reloc.
      96           1 :       uint64_t Delta = 4 + (RE.RelType - COFF::IMAGE_REL_AMD64_REL32);
      97           1 :       Value -= FinalAddress + Delta;
      98           1 :       uint64_t Result = Value + RE.Addend;
      99             :       assert(((int64_t)Result <= INT32_MAX) && "Relocation overflow");
     100             :       assert(((int64_t)Result >= INT32_MIN) && "Relocation underflow");
     101           1 :       writeBytesUnaligned(Result, Target, 4);
     102           1 :       break;
     103             :     }
     104             : 
     105             :     case COFF::IMAGE_REL_AMD64_ADDR32NB: {
     106             :       // ADDR32NB requires an offset less than 2GB from 'ImageBase'.
     107             :       // The MemoryManager can make sure this is always true by forcing the
     108             :       // memory layout to be: CodeSection < ReadOnlySection < ReadWriteSection.
     109             :       const uint64_t ImageBase = getImageBase();
     110           5 :       if (Value < ImageBase || ((Value - ImageBase) > UINT32_MAX)) {
     111           0 :         llvm::errs() << "IMAGE_REL_AMD64_ADDR32NB relocation requires an"
     112           0 :                      << "ordered section layout.\n";
     113             :         write32BitOffset(Target, 0, 0);
     114             :       } else {
     115           5 :         write32BitOffset(Target, RE.Addend, Value - ImageBase);
     116             :       }
     117             :       break;
     118             :     }
     119             : 
     120           1 :     case COFF::IMAGE_REL_AMD64_ADDR64: {
     121           1 :       writeBytesUnaligned(Value + RE.Addend, Target, 8);
     122           1 :       break;
     123             :     }
     124             : 
     125           0 :     default:
     126           0 :       llvm_unreachable("Relocation type not implemented yet!");
     127             :       break;
     128             :     }
     129           7 :   }
     130             : 
     131             :   std::tuple<uint64_t, uint64_t, uint64_t>
     132           0 :   generateRelocationStub(unsigned SectionID, StringRef TargetName,
     133             :                          uint64_t Offset, uint64_t RelType, uint64_t Addend,
     134             :                          StubMap &Stubs) {
     135             :     uintptr_t StubOffset;
     136           0 :     SectionEntry &Section = Sections[SectionID];
     137             : 
     138             :     RelocationValueRef OriginalRelValueRef;
     139           0 :     OriginalRelValueRef.SectionID = SectionID;
     140           0 :     OriginalRelValueRef.Offset = Offset;
     141           0 :     OriginalRelValueRef.Addend = Addend;
     142           0 :     OriginalRelValueRef.SymbolName = TargetName.data();
     143             : 
     144             :     auto Stub = Stubs.find(OriginalRelValueRef);
     145           0 :     if (Stub == Stubs.end()) {
     146             :       LLVM_DEBUG(dbgs() << " Create a new stub function for "
     147             :                         << TargetName.data() << "\n");
     148             : 
     149           0 :       StubOffset = Section.getStubOffset();
     150           0 :       Stubs[OriginalRelValueRef] = StubOffset;
     151           0 :       createStubFunction(Section.getAddressWithOffset(StubOffset));
     152           0 :       Section.advanceStubOffset(getMaxStubSize());
     153             :     } else {
     154             :       LLVM_DEBUG(dbgs() << " Stub function found for " << TargetName.data()
     155             :                         << "\n");
     156           0 :       StubOffset = Stub->second;
     157             :     }
     158             : 
     159             :     // FIXME: If RelType == COFF::IMAGE_REL_AMD64_ADDR32NB we should be able
     160             :     // to ignore the __ImageBase requirement and just forward to the stub
     161             :     // directly as an offset of this section:
     162             :     // write32BitOffset(Section.getAddressWithOffset(Offset), 0, StubOffset);
     163             :     // .xdata exception handler's aren't having this though.
     164             : 
     165             :     // Resolve original relocation to stub function.
     166           0 :     const RelocationEntry RE(SectionID, Offset, RelType, Addend);
     167           0 :     resolveRelocation(RE, Section.getLoadAddressWithOffset(StubOffset));
     168             : 
     169             :     // adjust relocation info so resolution writes to the stub function
     170             :     Addend = 0;
     171           0 :     Offset = StubOffset + 6;
     172             :     RelType = COFF::IMAGE_REL_AMD64_ADDR64;
     173             : 
     174           0 :     return std::make_tuple(Offset, RelType, Addend);
     175             :   }
     176             : 
     177             :   Expected<relocation_iterator>
     178           7 :   processRelocationRef(unsigned SectionID,
     179             :                        relocation_iterator RelI,
     180             :                        const ObjectFile &Obj,
     181             :                        ObjSectionToIDMap &ObjSectionToID,
     182             :                        StubMap &Stubs) override {
     183             :     // If possible, find the symbol referred to in the relocation,
     184             :     // and the section that contains it.
     185           7 :     symbol_iterator Symbol = RelI->getSymbol();
     186          14 :     if (Symbol == Obj.symbol_end())
     187           0 :       report_fatal_error("Unknown symbol in relocation");
     188             :     auto SectionOrError = Symbol->getSection();
     189           7 :     if (!SectionOrError)
     190             :       return SectionOrError.takeError();
     191           7 :     section_iterator SecI = *SectionOrError;
     192             :     // If there is no section, this must be an external reference.
     193          14 :     const bool IsExtern = SecI == Obj.section_end();
     194             : 
     195             :     // Determine the Addend used to adjust the relocation value.
     196           7 :     uint64_t RelType = RelI->getType();
     197           7 :     uint64_t Offset = RelI->getOffset();
     198           7 :     uint64_t Addend = 0;
     199           7 :     SectionEntry &Section = Sections[SectionID];
     200           7 :     uintptr_t ObjTarget = Section.getObjAddress() + Offset;
     201             : 
     202             :     Expected<StringRef> TargetNameOrErr = Symbol->getName();
     203           7 :     if (!TargetNameOrErr)
     204             :       return TargetNameOrErr.takeError();
     205           7 :     StringRef TargetName = *TargetNameOrErr;
     206             : 
     207           7 :     switch (RelType) {
     208             : 
     209           6 :     case COFF::IMAGE_REL_AMD64_REL32:
     210             :     case COFF::IMAGE_REL_AMD64_REL32_1:
     211             :     case COFF::IMAGE_REL_AMD64_REL32_2:
     212             :     case COFF::IMAGE_REL_AMD64_REL32_3:
     213             :     case COFF::IMAGE_REL_AMD64_REL32_4:
     214             :     case COFF::IMAGE_REL_AMD64_REL32_5:
     215             :     case COFF::IMAGE_REL_AMD64_ADDR32NB: {
     216           6 :       uint8_t *Displacement = (uint8_t *)ObjTarget;
     217           6 :       Addend = readBytesUnaligned(Displacement, 4);
     218             : 
     219           6 :       if (IsExtern)
     220           0 :         std::tie(Offset, RelType, Addend) = generateRelocationStub(
     221             :           SectionID, TargetName, Offset, RelType, Addend, Stubs);
     222             : 
     223             :       break;
     224             :     }
     225             : 
     226           1 :     case COFF::IMAGE_REL_AMD64_ADDR64: {
     227           1 :       uint8_t *Displacement = (uint8_t *)ObjTarget;
     228           1 :       Addend = readBytesUnaligned(Displacement, 8);
     229           1 :       break;
     230             :     }
     231             : 
     232             :     default:
     233             :       break;
     234             :     }
     235             : 
     236             :     LLVM_DEBUG(dbgs() << "\t\tIn Section " << SectionID << " Offset " << Offset
     237             :                       << " RelType: " << RelType << " TargetName: "
     238             :                       << TargetName << " Addend " << Addend << "\n");
     239             : 
     240           7 :     if (IsExtern) {
     241           0 :       RelocationEntry RE(SectionID, Offset, RelType, Addend);
     242           0 :       addRelocationForSymbol(RE, TargetName);
     243             :     } else {
     244             :       bool IsCode = SecI->isText();
     245             :       unsigned TargetSectionID;
     246           7 :       if (auto TargetSectionIDOrErr =
     247           7 :           findOrEmitSection(Obj, *SecI, IsCode, ObjSectionToID))
     248           7 :         TargetSectionID = *TargetSectionIDOrErr;
     249             :       else
     250             :         return TargetSectionIDOrErr.takeError();
     251           7 :       uint64_t TargetOffset = getSymbolOffset(*Symbol);
     252           7 :       RelocationEntry RE(SectionID, Offset, RelType, TargetOffset + Addend);
     253           7 :       addRelocationForSection(RE, TargetSectionID);
     254             :     }
     255             : 
     256             :     return ++RelI;
     257             :   }
     258             : 
     259           2 :   void registerEHFrames() override {
     260           4 :     for (auto const &EHFrameSID : UnregisteredEHFrameSections) {
     261           2 :       uint8_t *EHFrameAddr = Sections[EHFrameSID].getAddress();
     262           1 :       uint64_t EHFrameLoadAddr = Sections[EHFrameSID].getLoadAddress();
     263           1 :       size_t EHFrameSize = Sections[EHFrameSID].getSize();
     264           1 :       MemMgr.registerEHFrames(EHFrameAddr, EHFrameLoadAddr, EHFrameSize);
     265           1 :       RegisteredEHFrameSections.push_back(EHFrameSID);
     266             :     }
     267             :     UnregisteredEHFrameSections.clear();
     268           2 :   }
     269             : 
     270           2 :   Error finalizeLoad(const ObjectFile &Obj,
     271             :                      ObjSectionToIDMap &SectionMap) override {
     272             :     // Look for and record the EH frame section IDs.
     273          12 :     for (const auto &SectionPair : SectionMap) {
     274          10 :       const SectionRef &Section = SectionPair.first;
     275          10 :       StringRef Name;
     276          10 :       if (auto EC = Section.getName(Name))
     277           0 :         return errorCodeToError(EC);
     278             : 
     279             :       // Note unwind info is stored in .pdata but often points to .xdata
     280             :       // with an IMAGE_REL_AMD64_ADDR32NB relocation. Using a memory manager
     281             :       // that keeps sections ordered in relation to __ImageBase is necessary.
     282             :       if (Name == ".pdata")
     283           1 :         UnregisteredEHFrameSections.push_back(SectionPair.second);
     284             :     }
     285             :     return Error::success();
     286             :   }
     287             : };
     288             : 
     289             : } // end namespace llvm
     290             : 
     291             : #undef DEBUG_TYPE
     292             : 
     293             : #endif

Generated by: LCOV version 1.13