Home | History | Annotate | Download | only in lli
      1 //===---- RemoteMemoryManager.cpp - Recording memory manager --------------===//
      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 // This memory manager allocates local storage and keeps a record of each
     11 // allocation. Iterators are provided for all data and code allocations.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 
     15 #include "RemoteMemoryManager.h"
     16 #include "llvm/ExecutionEngine/ExecutionEngine.h"
     17 #include "llvm/ExecutionEngine/ObjectImage.h"
     18 #include "llvm/Support/Debug.h"
     19 #include "llvm/Support/Format.h"
     20 
     21 using namespace llvm;
     22 
     23 #define DEBUG_TYPE "lli"
     24 
     25 RemoteMemoryManager::~RemoteMemoryManager() {
     26   for (SmallVector<Allocation, 2>::iterator
     27          I = AllocatedSections.begin(), E = AllocatedSections.end();
     28        I != E; ++I)
     29     sys::Memory::releaseMappedMemory(I->MB);
     30 }
     31 
     32 uint8_t *RemoteMemoryManager::
     33 allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID,
     34                     StringRef SectionName) {
     35   // The recording memory manager is just a local copy of the remote target.
     36   // The alignment requirement is just stored here for later use. Regular
     37   // heap storage is sufficient here, but we're using mapped memory to work
     38   // around a bug in MCJIT.
     39   sys::MemoryBlock Block = allocateSection(Size);
     40   // AllocatedSections will own this memory.
     41   AllocatedSections.push_back( Allocation(Block, Alignment, true) );
     42   // UnmappedSections has the same information but does not own the memory.
     43   UnmappedSections.push_back( Allocation(Block, Alignment, true) );
     44   return (uint8_t*)Block.base();
     45 }
     46 
     47 uint8_t *RemoteMemoryManager::
     48 allocateDataSection(uintptr_t Size, unsigned Alignment,
     49                     unsigned SectionID, StringRef SectionName,
     50                     bool IsReadOnly) {
     51   // The recording memory manager is just a local copy of the remote target.
     52   // The alignment requirement is just stored here for later use. Regular
     53   // heap storage is sufficient here, but we're using mapped memory to work
     54   // around a bug in MCJIT.
     55   sys::MemoryBlock Block = allocateSection(Size);
     56   // AllocatedSections will own this memory.
     57   AllocatedSections.push_back( Allocation(Block, Alignment, false) );
     58   // UnmappedSections has the same information but does not own the memory.
     59   UnmappedSections.push_back( Allocation(Block, Alignment, false) );
     60   return (uint8_t*)Block.base();
     61 }
     62 
     63 sys::MemoryBlock RemoteMemoryManager::allocateSection(uintptr_t Size) {
     64   std::error_code ec;
     65   sys::MemoryBlock MB = sys::Memory::allocateMappedMemory(Size,
     66                                                           &Near,
     67                                                           sys::Memory::MF_READ |
     68                                                           sys::Memory::MF_WRITE,
     69                                                           ec);
     70   assert(!ec && MB.base());
     71 
     72   // FIXME: This is part of a work around to keep sections near one another
     73   // when MCJIT performs relocations after code emission but before
     74   // the generated code is moved to the remote target.
     75   // Save this address as the basis for our next request
     76   Near = MB;
     77   return MB;
     78 }
     79 
     80 void RemoteMemoryManager::notifyObjectLoaded(ExecutionEngine *EE,
     81                                                 const ObjectImage *Obj) {
     82   // The client should have called setRemoteTarget() before triggering any
     83   // code generation.
     84   assert(Target);
     85   if (!Target)
     86     return;
     87 
     88   // FIXME: Make this function thread safe.
     89 
     90   // Lay out our sections in order, with all the code sections first, then
     91   // all the data sections.
     92   uint64_t CurOffset = 0;
     93   unsigned MaxAlign = Target->getPageAlignment();
     94   SmallVector<std::pair<Allocation, uint64_t>, 16> Offsets;
     95   unsigned NumSections = UnmappedSections.size();
     96   // We're going to go through the list twice to separate code and data, but
     97   // it's a very small list, so that's OK.
     98   for (size_t i = 0, e = NumSections; i != e; ++i) {
     99     Allocation &Section = UnmappedSections[i];
    100     if (Section.IsCode) {
    101       unsigned Size = Section.MB.size();
    102       unsigned Align = Section.Alignment;
    103       DEBUG(dbgs() << "code region: size " << Size
    104                   << ", alignment " << Align << "\n");
    105       // Align the current offset up to whatever is needed for the next
    106       // section.
    107       CurOffset = (CurOffset + Align - 1) / Align * Align;
    108       // Save off the address of the new section and allocate its space.
    109       Offsets.push_back(std::pair<Allocation,uint64_t>(Section, CurOffset));
    110       CurOffset += Size;
    111     }
    112   }
    113   // Adjust to keep code and data aligned on separate pages.
    114   CurOffset = (CurOffset + MaxAlign - 1) / MaxAlign * MaxAlign;
    115   for (size_t i = 0, e = NumSections; i != e; ++i) {
    116     Allocation &Section = UnmappedSections[i];
    117     if (!Section.IsCode) {
    118       unsigned Size = Section.MB.size();
    119       unsigned Align = Section.Alignment;
    120       DEBUG(dbgs() << "data region: size " << Size
    121                   << ", alignment " << Align << "\n");
    122       // Align the current offset up to whatever is needed for the next
    123       // section.
    124       CurOffset = (CurOffset + Align - 1) / Align * Align;
    125       // Save off the address of the new section and allocate its space.
    126       Offsets.push_back(std::pair<Allocation,uint64_t>(Section, CurOffset));
    127       CurOffset += Size;
    128     }
    129   }
    130 
    131   // Allocate space in the remote target.
    132   uint64_t RemoteAddr;
    133   if (!Target->allocateSpace(CurOffset, MaxAlign, RemoteAddr))
    134     report_fatal_error(Target->getErrorMsg());
    135 
    136   // Map the section addresses so relocations will get updated in the local
    137   // copies of the sections.
    138   for (unsigned i = 0, e = Offsets.size(); i != e; ++i) {
    139     uint64_t Addr = RemoteAddr + Offsets[i].second;
    140     EE->mapSectionAddress(const_cast<void*>(Offsets[i].first.MB.base()), Addr);
    141 
    142     DEBUG(dbgs() << "  Mapping local: " << Offsets[i].first.MB.base()
    143                  << " to remote: 0x" << format("%llx", Addr) << "\n");
    144 
    145     MappedSections[Addr] = Offsets[i].first;
    146   }
    147 
    148   UnmappedSections.clear();
    149 }
    150 
    151 bool RemoteMemoryManager::finalizeMemory(std::string *ErrMsg) {
    152   // FIXME: Make this function thread safe.
    153   for (DenseMap<uint64_t, Allocation>::iterator
    154          I = MappedSections.begin(), E = MappedSections.end();
    155        I != E; ++I) {
    156     uint64_t RemoteAddr = I->first;
    157     const Allocation &Section = I->second;
    158     if (Section.IsCode) {
    159       if (!Target->loadCode(RemoteAddr, Section.MB.base(), Section.MB.size()))
    160         report_fatal_error(Target->getErrorMsg());
    161       DEBUG(dbgs() << "  loading code: " << Section.MB.base()
    162             << " to remote: 0x" << format("%llx", RemoteAddr) << "\n");
    163     } else {
    164       if (!Target->loadData(RemoteAddr, Section.MB.base(), Section.MB.size()))
    165         report_fatal_error(Target->getErrorMsg());
    166       DEBUG(dbgs() << "  loading data: " << Section.MB.base()
    167             << " to remote: 0x" << format("%llx", RemoteAddr) << "\n");
    168     }
    169   }
    170 
    171   MappedSections.clear();
    172 
    173   return false;
    174 }
    175 
    176 void RemoteMemoryManager::setMemoryWritable() { llvm_unreachable("Unexpected!"); }
    177 void RemoteMemoryManager::setMemoryExecutable() { llvm_unreachable("Unexpected!"); }
    178 void RemoteMemoryManager::setPoisonMemory(bool poison) { llvm_unreachable("Unexpected!"); }
    179 void RemoteMemoryManager::AllocateGOT() { llvm_unreachable("Unexpected!"); }
    180 uint8_t *RemoteMemoryManager::getGOTBase() const {
    181   llvm_unreachable("Unexpected!");
    182   return nullptr;
    183 }
    184 uint8_t *RemoteMemoryManager::startFunctionBody(const Function *F, uintptr_t &ActualSize){
    185   llvm_unreachable("Unexpected!");
    186   return nullptr;
    187 }
    188 uint8_t *RemoteMemoryManager::allocateStub(const GlobalValue* F, unsigned StubSize,
    189                                               unsigned Alignment) {
    190   llvm_unreachable("Unexpected!");
    191   return nullptr;
    192 }
    193 void RemoteMemoryManager::endFunctionBody(const Function *F, uint8_t *FunctionStart,
    194                                              uint8_t *FunctionEnd) {
    195   llvm_unreachable("Unexpected!");
    196 }
    197 uint8_t *RemoteMemoryManager::allocateSpace(intptr_t Size, unsigned Alignment) {
    198   llvm_unreachable("Unexpected!");
    199   return nullptr;
    200 }
    201 uint8_t *RemoteMemoryManager::allocateGlobal(uintptr_t Size, unsigned Alignment) {
    202   llvm_unreachable("Unexpected!");
    203   return nullptr;
    204 }
    205 void RemoteMemoryManager::deallocateFunctionBody(void *Body) {
    206   llvm_unreachable("Unexpected!");
    207 }
    208