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: 73 82 89.0 %
Date: 2017-09-14 15:23:50 Functions: 8 8 100.0 %
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           5 : 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             :                         JITSymbolResolver &Resolver)
      37           4 :     : RuntimeDyldCOFF(MM, Resolver) {}
      38             : 
      39           6 :   unsigned getMaxStubSize() override {
      40           6 :     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           5 :   void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override {
      64          10 :     const SectionEntry &Section = Sections[RE.SectionID];
      65          10 :     uint8_t *Target = Section.getAddressWithOffset(RE.Offset);
      66             : 
      67           5 :     switch (RE.RelType) {
      68             : 
      69           1 :     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           2 :       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           1 :       uint64_t Delta = 4 + (RE.RelType - COFF::IMAGE_REL_AMD64_REL32);
      79           1 :       Value -= FinalAddress + Delta;
      80           1 :       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           1 :       writeBytesUnaligned(Result, Target, 4);
      84           1 :       break;
      85             :     }
      86             : 
      87           3 :     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           3 :       writeBytesUnaligned(0, Target, 4);
      95           3 :       break;
      96             :     }
      97             : 
      98           1 :     case COFF::IMAGE_REL_AMD64_ADDR64: {
      99           1 :       writeBytesUnaligned(Value + RE.Addend, Target, 8);
     100           1 :       break;
     101             :     }
     102             : 
     103           0 :     default:
     104           0 :       llvm_unreachable("Relocation type not implemented yet!");
     105             :       break;
     106             :     }
     107           5 :   }
     108             : 
     109             :   Expected<relocation_iterator>
     110           5 :   processRelocationRef(unsigned SectionID,
     111             :                        relocation_iterator RelI,
     112             :                        const ObjectFile &Obj,
     113             :                        ObjSectionToIDMap &ObjSectionToID,
     114             :                        StubMap &Stubs) override {
     115             :     // If possible, find the symbol referred to in the relocation,
     116             :     // and the section that contains it.
     117          10 :     symbol_iterator Symbol = RelI->getSymbol();
     118          10 :     if (Symbol == Obj.symbol_end())
     119           0 :       report_fatal_error("Unknown symbol in relocation");
     120          15 :     auto SectionOrError = Symbol->getSection();
     121           5 :     if (!SectionOrError)
     122           0 :       return SectionOrError.takeError();
     123           5 :     section_iterator SecI = *SectionOrError;
     124             :     // If there is no section, this must be an external reference.
     125          10 :     const bool IsExtern = SecI == Obj.section_end();
     126             : 
     127             :     // Determine the Addend used to adjust the relocation value.
     128          10 :     uint64_t RelType = RelI->getType();
     129          10 :     uint64_t Offset = RelI->getOffset();
     130           5 :     uint64_t Addend = 0;
     131          10 :     SectionEntry &Section = Sections[SectionID];
     132           5 :     uintptr_t ObjTarget = Section.getObjAddress() + Offset;
     133             : 
     134           5 :     switch (RelType) {
     135             : 
     136           4 :     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           4 :       uint8_t *Displacement = (uint8_t *)ObjTarget;
     144           4 :       Addend = readBytesUnaligned(Displacement, 4);
     145           4 :       break;
     146             :     }
     147             : 
     148           1 :     case COFF::IMAGE_REL_AMD64_ADDR64: {
     149           1 :       uint8_t *Displacement = (uint8_t *)ObjTarget;
     150           1 :       Addend = readBytesUnaligned(Displacement, 8);
     151           1 :       break;
     152             :     }
     153             : 
     154             :     default:
     155             :       break;
     156             :     }
     157             : 
     158          15 :     Expected<StringRef> TargetNameOrErr = Symbol->getName();
     159           5 :     if (!TargetNameOrErr)
     160           0 :       return TargetNameOrErr.takeError();
     161           5 :     StringRef TargetName = *TargetNameOrErr;
     162             : 
     163             :     DEBUG(dbgs() << "\t\tIn Section " << SectionID << " Offset " << Offset
     164             :                  << " RelType: " << RelType << " TargetName: " << TargetName
     165             :                  << " Addend " << Addend << "\n");
     166             : 
     167           5 :     if (IsExtern) {
     168           0 :       RelocationEntry RE(SectionID, Offset, RelType, Addend);
     169           0 :       addRelocationForSymbol(RE, TargetName);
     170             :     } else {
     171          10 :       bool IsCode = SecI->isText();
     172             :       unsigned TargetSectionID;
     173           5 :       if (auto TargetSectionIDOrErr =
     174          15 :           findOrEmitSection(Obj, *SecI, IsCode, ObjSectionToID))
     175           5 :         TargetSectionID = *TargetSectionIDOrErr;
     176             :       else
     177           0 :         return TargetSectionIDOrErr.takeError();
     178          10 :       uint64_t TargetOffset = getSymbolOffset(*Symbol);
     179          10 :       RelocationEntry RE(SectionID, Offset, RelType, TargetOffset + Addend);
     180           5 :       addRelocationForSection(RE, TargetSectionID);
     181             :     }
     182             : 
     183           5 :     return ++RelI;
     184             :   }
     185             : 
     186           8 :   unsigned getStubAlignment() override { return 1; }
     187           1 :   void registerEHFrames() override {
     188           4 :     for (auto const &EHFrameSID : UnregisteredEHFrameSections) {
     189           2 :       uint8_t *EHFrameAddr = Sections[EHFrameSID].getAddress();
     190           2 :       uint64_t EHFrameLoadAddr = Sections[EHFrameSID].getLoadAddress();
     191           2 :       size_t EHFrameSize = Sections[EHFrameSID].getSize();
     192           1 :       MemMgr.registerEHFrames(EHFrameAddr, EHFrameLoadAddr, EHFrameSize);
     193           1 :       RegisteredEHFrameSections.push_back(EHFrameSID);
     194             :     }
     195           2 :     UnregisteredEHFrameSections.clear();
     196           1 :   }
     197           1 :   Error finalizeLoad(const ObjectFile &Obj,
     198             :                      ObjSectionToIDMap &SectionMap) override {
     199             :     // Look for and record the EH frame section IDs.
     200           9 :     for (const auto &SectionPair : SectionMap) {
     201           6 :       const SectionRef &Section = SectionPair.first;
     202           6 :       StringRef Name;
     203           6 :       if (auto EC = Section.getName(Name))
     204           0 :         return errorCodeToError(EC);
     205             :       // Note unwind info is split across .pdata and .xdata, so this
     206             :       // may not be sufficiently general for all users.
     207           7 :       if (Name == ".xdata") {
     208           1 :         UnregisteredEHFrameSections.push_back(SectionPair.second);
     209             :       }
     210             :     }
     211           3 :     return Error::success();
     212             :   }
     213             : };
     214             : 
     215             : } // end namespace llvm
     216             : 
     217             : #undef DEBUG_TYPE
     218             : 
     219             : #endif

Generated by: LCOV version 1.13