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
21using namespace llvm;
22
23#define DEBUG_TYPE "lli"
24
25RemoteMemoryManager::~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
32uint8_t *RemoteMemoryManager::
33allocateCodeSection(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
47uint8_t *RemoteMemoryManager::
48allocateDataSection(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
63sys::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
80void 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
151bool 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
176void RemoteMemoryManager::setMemoryWritable() { llvm_unreachable("Unexpected!"); }
177void RemoteMemoryManager::setMemoryExecutable() { llvm_unreachable("Unexpected!"); }
178void RemoteMemoryManager::setPoisonMemory(bool poison) { llvm_unreachable("Unexpected!"); }
179void RemoteMemoryManager::AllocateGOT() { llvm_unreachable("Unexpected!"); }
180uint8_t *RemoteMemoryManager::getGOTBase() const {
181  llvm_unreachable("Unexpected!");
182  return nullptr;
183}
184uint8_t *RemoteMemoryManager::startFunctionBody(const Function *F, uintptr_t &ActualSize){
185  llvm_unreachable("Unexpected!");
186  return nullptr;
187}
188uint8_t *RemoteMemoryManager::allocateStub(const GlobalValue* F, unsigned StubSize,
189                                              unsigned Alignment) {
190  llvm_unreachable("Unexpected!");
191  return nullptr;
192}
193void RemoteMemoryManager::endFunctionBody(const Function *F, uint8_t *FunctionStart,
194                                             uint8_t *FunctionEnd) {
195  llvm_unreachable("Unexpected!");
196}
197uint8_t *RemoteMemoryManager::allocateSpace(intptr_t Size, unsigned Alignment) {
198  llvm_unreachable("Unexpected!");
199  return nullptr;
200}
201uint8_t *RemoteMemoryManager::allocateGlobal(uintptr_t Size, unsigned Alignment) {
202  llvm_unreachable("Unexpected!");
203  return nullptr;
204}
205void RemoteMemoryManager::deallocateFunctionBody(void *Body) {
206  llvm_unreachable("Unexpected!");
207}
208