2
0

SectionMemoryManager.cpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. //===- SectionMemoryManager.cpp - Memory manager for MCJIT/RtDyld *- 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. // This file implements the section-based memory manager used by the MCJIT
  11. // execution engine and RuntimeDyld
  12. //
  13. //===----------------------------------------------------------------------===//
  14. #include "llvm/Config/config.h"
  15. #include "llvm/ExecutionEngine/SectionMemoryManager.h"
  16. #include "llvm/Support/MathExtras.h"
  17. namespace llvm {
  18. uint8_t *SectionMemoryManager::allocateDataSection(uintptr_t Size,
  19. unsigned Alignment,
  20. unsigned SectionID,
  21. StringRef SectionName,
  22. bool IsReadOnly) {
  23. if (IsReadOnly)
  24. return allocateSection(RODataMem, Size, Alignment);
  25. return allocateSection(RWDataMem, Size, Alignment);
  26. }
  27. uint8_t *SectionMemoryManager::allocateCodeSection(uintptr_t Size,
  28. unsigned Alignment,
  29. unsigned SectionID,
  30. StringRef SectionName) {
  31. return allocateSection(CodeMem, Size, Alignment);
  32. }
  33. uint8_t *SectionMemoryManager::allocateSection(MemoryGroup &MemGroup,
  34. uintptr_t Size,
  35. unsigned Alignment) {
  36. if (!Alignment)
  37. Alignment = 16;
  38. assert(!(Alignment & (Alignment - 1)) && "Alignment must be a power of two.");
  39. uintptr_t RequiredSize = Alignment * ((Size + Alignment - 1)/Alignment + 1);
  40. uintptr_t Addr = 0;
  41. // Look in the list of free memory regions and use a block there if one
  42. // is available.
  43. for (int i = 0, e = MemGroup.FreeMem.size(); i != e; ++i) {
  44. sys::MemoryBlock &MB = MemGroup.FreeMem[i];
  45. if (MB.size() >= RequiredSize) {
  46. Addr = (uintptr_t)MB.base();
  47. uintptr_t EndOfBlock = Addr + MB.size();
  48. // Align the address.
  49. Addr = (Addr + Alignment - 1) & ~(uintptr_t)(Alignment - 1);
  50. // Store cutted free memory block.
  51. MemGroup.FreeMem[i] = sys::MemoryBlock((void*)(Addr + Size),
  52. EndOfBlock - Addr - Size);
  53. return (uint8_t*)Addr;
  54. }
  55. }
  56. // No pre-allocated free block was large enough. Allocate a new memory region.
  57. // Note that all sections get allocated as read-write. The permissions will
  58. // be updated later based on memory group.
  59. //
  60. // FIXME: It would be useful to define a default allocation size (or add
  61. // it as a constructor parameter) to minimize the number of allocations.
  62. //
  63. // FIXME: Initialize the Near member for each memory group to avoid
  64. // interleaving.
  65. std::error_code ec;
  66. sys::MemoryBlock MB = sys::Memory::allocateMappedMemory(RequiredSize,
  67. &MemGroup.Near,
  68. sys::Memory::MF_READ |
  69. sys::Memory::MF_WRITE,
  70. ec);
  71. if (ec) {
  72. // FIXME: Add error propagation to the interface.
  73. return nullptr;
  74. }
  75. // Save this address as the basis for our next request
  76. MemGroup.Near = MB;
  77. MemGroup.AllocatedMem.push_back(MB);
  78. Addr = (uintptr_t)MB.base();
  79. uintptr_t EndOfBlock = Addr + MB.size();
  80. // Align the address.
  81. Addr = (Addr + Alignment - 1) & ~(uintptr_t)(Alignment - 1);
  82. // The allocateMappedMemory may allocate much more memory than we need. In
  83. // this case, we store the unused memory as a free memory block.
  84. unsigned FreeSize = EndOfBlock-Addr-Size;
  85. if (FreeSize > 16)
  86. MemGroup.FreeMem.push_back(sys::MemoryBlock((void*)(Addr + Size), FreeSize));
  87. // Return aligned address
  88. return (uint8_t*)Addr;
  89. }
  90. bool SectionMemoryManager::finalizeMemory(std::string *ErrMsg)
  91. {
  92. // FIXME: Should in-progress permissions be reverted if an error occurs?
  93. std::error_code ec;
  94. // Don't allow free memory blocks to be used after setting protection flags.
  95. CodeMem.FreeMem.clear();
  96. // Make code memory executable.
  97. ec = applyMemoryGroupPermissions(CodeMem,
  98. sys::Memory::MF_READ | sys::Memory::MF_EXEC);
  99. if (ec) {
  100. if (ErrMsg) {
  101. *ErrMsg = ec.message();
  102. }
  103. return true;
  104. }
  105. // Don't allow free memory blocks to be used after setting protection flags.
  106. RODataMem.FreeMem.clear();
  107. // Make read-only data memory read-only.
  108. ec = applyMemoryGroupPermissions(RODataMem,
  109. sys::Memory::MF_READ | sys::Memory::MF_EXEC);
  110. if (ec) {
  111. if (ErrMsg) {
  112. *ErrMsg = ec.message();
  113. }
  114. return true;
  115. }
  116. // Read-write data memory already has the correct permissions
  117. // Some platforms with separate data cache and instruction cache require
  118. // explicit cache flush, otherwise JIT code manipulations (like resolved
  119. // relocations) will get to the data cache but not to the instruction cache.
  120. invalidateInstructionCache();
  121. return false;
  122. }
  123. std::error_code
  124. SectionMemoryManager::applyMemoryGroupPermissions(MemoryGroup &MemGroup,
  125. unsigned Permissions) {
  126. for (int i = 0, e = MemGroup.AllocatedMem.size(); i != e; ++i) {
  127. std::error_code ec;
  128. ec =
  129. sys::Memory::protectMappedMemory(MemGroup.AllocatedMem[i], Permissions);
  130. if (ec) {
  131. return ec;
  132. }
  133. }
  134. return std::error_code();
  135. }
  136. void SectionMemoryManager::invalidateInstructionCache() {
  137. for (int i = 0, e = CodeMem.AllocatedMem.size(); i != e; ++i)
  138. sys::Memory::InvalidateInstructionCache(CodeMem.AllocatedMem[i].base(),
  139. CodeMem.AllocatedMem[i].size());
  140. }
  141. SectionMemoryManager::~SectionMemoryManager() {
  142. for (unsigned i = 0, e = CodeMem.AllocatedMem.size(); i != e; ++i)
  143. sys::Memory::releaseMappedMemory(CodeMem.AllocatedMem[i]);
  144. for (unsigned i = 0, e = RWDataMem.AllocatedMem.size(); i != e; ++i)
  145. sys::Memory::releaseMappedMemory(RWDataMem.AllocatedMem[i]);
  146. for (unsigned i = 0, e = RODataMem.AllocatedMem.size(); i != e; ++i)
  147. sys::Memory::releaseMappedMemory(RODataMem.AllocatedMem[i]);
  148. }
  149. } // namespace llvm