RemoteMemoryManager.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  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. #include "RemoteMemoryManager.h"
  15. #include "llvm/ExecutionEngine/ExecutionEngine.h"
  16. #include "llvm/Support/Debug.h"
  17. #include "llvm/Support/Format.h"
  18. #include "llvm/Support/raw_ostream.h"
  19. using namespace llvm;
  20. #define DEBUG_TYPE "lli"
  21. RemoteMemoryManager::~RemoteMemoryManager() {
  22. for (SmallVector<Allocation, 2>::iterator
  23. I = AllocatedSections.begin(), E = AllocatedSections.end();
  24. I != E; ++I)
  25. sys::Memory::releaseMappedMemory(I->MB);
  26. }
  27. uint8_t *RemoteMemoryManager::
  28. allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID,
  29. StringRef SectionName) {
  30. // The recording memory manager is just a local copy of the remote target.
  31. // The alignment requirement is just stored here for later use. Regular
  32. // heap storage is sufficient here, but we're using mapped memory to work
  33. // around a bug in MCJIT.
  34. sys::MemoryBlock Block = allocateSection(Size);
  35. // AllocatedSections will own this memory.
  36. AllocatedSections.push_back( Allocation(Block, Alignment, true) );
  37. // UnmappedSections has the same information but does not own the memory.
  38. UnmappedSections.push_back( Allocation(Block, Alignment, true) );
  39. return (uint8_t*)Block.base();
  40. }
  41. uint8_t *RemoteMemoryManager::
  42. allocateDataSection(uintptr_t Size, unsigned Alignment,
  43. unsigned SectionID, StringRef SectionName,
  44. bool IsReadOnly) {
  45. // The recording memory manager is just a local copy of the remote target.
  46. // The alignment requirement is just stored here for later use. Regular
  47. // heap storage is sufficient here, but we're using mapped memory to work
  48. // around a bug in MCJIT.
  49. sys::MemoryBlock Block = allocateSection(Size);
  50. // AllocatedSections will own this memory.
  51. AllocatedSections.push_back( Allocation(Block, Alignment, false) );
  52. // UnmappedSections has the same information but does not own the memory.
  53. UnmappedSections.push_back( Allocation(Block, Alignment, false) );
  54. return (uint8_t*)Block.base();
  55. }
  56. sys::MemoryBlock RemoteMemoryManager::allocateSection(uintptr_t Size) {
  57. std::error_code ec;
  58. sys::MemoryBlock MB = sys::Memory::allocateMappedMemory(Size,
  59. &Near,
  60. sys::Memory::MF_READ |
  61. sys::Memory::MF_WRITE,
  62. ec);
  63. assert(!ec && MB.base());
  64. // FIXME: This is part of a work around to keep sections near one another
  65. // when MCJIT performs relocations after code emission but before
  66. // the generated code is moved to the remote target.
  67. // Save this address as the basis for our next request
  68. Near = MB;
  69. return MB;
  70. }
  71. void RemoteMemoryManager::notifyObjectLoaded(ExecutionEngine *EE,
  72. const object::ObjectFile &Obj) {
  73. // The client should have called setRemoteTarget() before triggering any
  74. // code generation.
  75. assert(Target);
  76. if (!Target)
  77. return;
  78. // FIXME: Make this function thread safe.
  79. // Lay out our sections in order, with all the code sections first, then
  80. // all the data sections.
  81. uint64_t CurOffset = 0;
  82. unsigned MaxAlign = Target->getPageAlignment();
  83. SmallVector<std::pair<Allocation, uint64_t>, 16> Offsets;
  84. unsigned NumSections = UnmappedSections.size();
  85. // We're going to go through the list twice to separate code and data, but
  86. // it's a very small list, so that's OK.
  87. for (size_t i = 0, e = NumSections; i != e; ++i) {
  88. Allocation &Section = UnmappedSections[i];
  89. if (Section.IsCode) {
  90. unsigned Size = Section.MB.size();
  91. unsigned Align = Section.Alignment;
  92. DEBUG(dbgs() << "code region: size " << Size
  93. << ", alignment " << Align << "\n");
  94. // Align the current offset up to whatever is needed for the next
  95. // section.
  96. CurOffset = (CurOffset + Align - 1) / Align * Align;
  97. // Save off the address of the new section and allocate its space.
  98. Offsets.push_back(std::pair<Allocation,uint64_t>(Section, CurOffset));
  99. CurOffset += Size;
  100. }
  101. }
  102. // Adjust to keep code and data aligned on separate pages.
  103. CurOffset = (CurOffset + MaxAlign - 1) / MaxAlign * MaxAlign;
  104. for (size_t i = 0, e = NumSections; i != e; ++i) {
  105. Allocation &Section = UnmappedSections[i];
  106. if (!Section.IsCode) {
  107. unsigned Size = Section.MB.size();
  108. unsigned Align = Section.Alignment;
  109. DEBUG(dbgs() << "data region: size " << Size
  110. << ", alignment " << Align << "\n");
  111. // Align the current offset up to whatever is needed for the next
  112. // section.
  113. CurOffset = (CurOffset + Align - 1) / Align * Align;
  114. // Save off the address of the new section and allocate its space.
  115. Offsets.push_back(std::pair<Allocation,uint64_t>(Section, CurOffset));
  116. CurOffset += Size;
  117. }
  118. }
  119. // Allocate space in the remote target.
  120. uint64_t RemoteAddr;
  121. if (!Target->allocateSpace(CurOffset, MaxAlign, RemoteAddr))
  122. report_fatal_error(Target->getErrorMsg());
  123. // Map the section addresses so relocations will get updated in the local
  124. // copies of the sections.
  125. for (unsigned i = 0, e = Offsets.size(); i != e; ++i) {
  126. uint64_t Addr = RemoteAddr + Offsets[i].second;
  127. EE->mapSectionAddress(const_cast<void*>(Offsets[i].first.MB.base()), Addr);
  128. DEBUG(dbgs() << " Mapping local: " << Offsets[i].first.MB.base()
  129. << " to remote: 0x" << format("%llx", Addr) << "\n");
  130. MappedSections[Addr] = Offsets[i].first;
  131. }
  132. UnmappedSections.clear();
  133. }
  134. bool RemoteMemoryManager::finalizeMemory(std::string *ErrMsg) {
  135. // FIXME: Make this function thread safe.
  136. for (DenseMap<uint64_t, Allocation>::iterator
  137. I = MappedSections.begin(), E = MappedSections.end();
  138. I != E; ++I) {
  139. uint64_t RemoteAddr = I->first;
  140. const Allocation &Section = I->second;
  141. if (Section.IsCode) {
  142. if (!Target->loadCode(RemoteAddr, Section.MB.base(), Section.MB.size()))
  143. report_fatal_error(Target->getErrorMsg());
  144. DEBUG(dbgs() << " loading code: " << Section.MB.base()
  145. << " to remote: 0x" << format("%llx", RemoteAddr) << "\n");
  146. } else {
  147. if (!Target->loadData(RemoteAddr, Section.MB.base(), Section.MB.size()))
  148. report_fatal_error(Target->getErrorMsg());
  149. DEBUG(dbgs() << " loading data: " << Section.MB.base()
  150. << " to remote: 0x" << format("%llx", RemoteAddr) << "\n");
  151. }
  152. }
  153. MappedSections.clear();
  154. return false;
  155. }