40#ifdef USE_LLVM_BACKPORT_SECTION_MEMORY_MANAGER
43#include "llvm/Support/MathExtras.h"
44#include "llvm/Support/Process.h"
50 uintptr_t
Size)
const {
51 for (
const FreeMemBlock &FreeMB : MemGroup.FreeMem) {
52 if (FreeMB.Free.allocatedSize() >=
Size)
58#if LLVM_VERSION_MAJOR < 16
62 uint32_t RODataAlign_i,
64 uint32_t RWDataAlign_i) {
65 Align CodeAlign(CodeAlign_i);
66 Align RODataAlign(RODataAlign_i);
67 Align RWDataAlign(RWDataAlign_i);
70 uintptr_t CodeSize, Align CodeAlign, uintptr_t RODataSize,
71 Align RODataAlign, uintptr_t RWDataSize, Align RWDataAlign) {
73 if (CodeSize == 0 && RODataSize == 0 && RWDataSize == 0)
76 static const size_t PageSize = sys::Process::getPageSizeEstimate();
81 constexpr uint64_t StubAlign = 8;
82 CodeAlign = Align(std::max(CodeAlign.value(), StubAlign));
83 RODataAlign = Align(std::max(RODataAlign.value(), StubAlign));
84 RWDataAlign = Align(std::max(RWDataAlign.value(), StubAlign));
88 uint64_t RequiredCodeSize = alignTo(CodeSize, CodeAlign) + CodeAlign.value();
89 uint64_t RequiredRODataSize =
90 alignTo(RODataSize, RODataAlign) + RODataAlign.value();
91 uint64_t RequiredRWDataSize =
92 alignTo(RWDataSize, RWDataAlign) + RWDataAlign.value();
112 RequiredCodeSize = alignTo(RequiredCodeSize, PageSize);
113 RequiredRODataSize = alignTo(RequiredRODataSize, PageSize);
114 RequiredRWDataSize = alignTo(RequiredRWDataSize, PageSize);
115 uint64_t RequiredSize =
116 RequiredCodeSize + RequiredRODataSize + RequiredRWDataSize;
121 sys::Memory::MF_READ | sys::Memory::MF_WRITE, ec);
127 uintptr_t Addr = (uintptr_t)MB.base();
129 FreeMB.PendingPrefixIndex = (unsigned)-1;
132 assert(isAddrAligned(CodeAlign, (
void *)Addr));
133 FreeMB.Free = sys::MemoryBlock((
void *)Addr, RequiredCodeSize);
135 Addr += RequiredCodeSize;
138 if (RODataSize > 0) {
139 assert(isAddrAligned(RODataAlign, (
void *)Addr));
140 FreeMB.Free = sys::MemoryBlock((
void *)Addr, RequiredRODataSize);
142 Addr += RequiredRODataSize;
145 if (RWDataSize > 0) {
146 assert(isAddrAligned(RWDataAlign, (
void *)Addr));
147 FreeMB.Free = sys::MemoryBlock((
void *)Addr, RequiredRWDataSize);
155 StringRef SectionName,
167 StringRef SectionName) {
174 unsigned Alignment) {
178 assert(!(Alignment & (Alignment - 1)) &&
"Alignment must be a power of two.");
180 uintptr_t RequiredSize = Alignment * ((
Size + Alignment - 1) / Alignment + 1);
183 MemoryGroup &MemGroup = [&]() -> MemoryGroup & {
192 llvm_unreachable(
"Unknown SectionMemoryManager::AllocationPurpose");
197 for (FreeMemBlock &FreeMB : MemGroup.FreeMem) {
198 if (FreeMB.Free.allocatedSize() >= RequiredSize) {
199 Addr = (uintptr_t)FreeMB.Free.base();
200 uintptr_t EndOfBlock = Addr + FreeMB.Free.allocatedSize();
202 Addr = (Addr + Alignment - 1) & ~(uintptr_t)(Alignment - 1);
204 if (FreeMB.PendingPrefixIndex == (
unsigned)-1) {
206 MemGroup.PendingMem.push_back(sys::MemoryBlock((
void *)Addr,
Size));
210 FreeMB.PendingPrefixIndex = MemGroup.PendingMem.size() - 1;
212 sys::MemoryBlock &PendingMB =
213 MemGroup.PendingMem[FreeMB.PendingPrefixIndex];
214 PendingMB = sys::MemoryBlock(PendingMB.base(),
215 Addr +
Size - (uintptr_t)PendingMB.base());
220 sys::MemoryBlock((
void *)(Addr +
Size), EndOfBlock - Addr -
Size);
221 return (uint8_t *)Addr;
236 Purpose, RequiredSize, &MemGroup.Near,
237 sys::Memory::MF_READ | sys::Memory::MF_WRITE, ec);
256 MemGroup.AllocatedMem.push_back(MB);
257 Addr = (uintptr_t)MB.base();
258 uintptr_t EndOfBlock = Addr + MB.allocatedSize();
261 Addr = (Addr + Alignment - 1) & ~(uintptr_t)(Alignment - 1);
264 MemGroup.PendingMem.push_back(sys::MemoryBlock((
void *)Addr,
Size));
268 unsigned FreeSize = EndOfBlock - Addr -
Size;
271 FreeMB.Free = sys::MemoryBlock((
void *)(Addr +
Size), FreeSize);
272 FreeMB.PendingPrefixIndex = (unsigned)-1;
273 MemGroup.FreeMem.push_back(FreeMB);
277 return (uint8_t *)Addr;
286 sys::Memory::MF_READ | sys::Memory::MF_EXEC);
289 *ErrMsg = ec.message();
298 *ErrMsg = ec.message();
313static sys::MemoryBlock trimBlockToPageSize(sys::MemoryBlock M) {
314 static const size_t PageSize = sys::Process::getPageSizeEstimate();
316 size_t StartOverlap =
317 (PageSize - ((uintptr_t)M.base() % PageSize)) % PageSize;
319 size_t TrimmedSize = M.allocatedSize();
320 TrimmedSize -= StartOverlap;
321 TrimmedSize -= TrimmedSize % PageSize;
323 sys::MemoryBlock Trimmed((
void *)((uintptr_t)M.base() + StartOverlap),
326 assert(((uintptr_t)Trimmed.base() % PageSize) == 0);
327 assert((Trimmed.allocatedSize() % PageSize) == 0);
328 assert(M.base() <= Trimmed.base() &&
329 Trimmed.allocatedSize() <= M.allocatedSize());
336 unsigned Permissions) {
337 for (sys::MemoryBlock &MB : MemGroup.PendingMem)
341 MemGroup.PendingMem.clear();
345 for (FreeMemBlock &FreeMB : MemGroup.FreeMem) {
346 FreeMB.Free = trimBlockToPageSize(FreeMB.Free);
348 FreeMB.PendingPrefixIndex = (unsigned)-1;
352 erase_if(MemGroup.FreeMem, [](FreeMemBlock &FreeMB) {
353 return FreeMB.Free.allocatedSize() == 0;
356 return std::error_code();
361 sys::Memory::InvalidateInstructionCache(
Block.base(),
362 Block.allocatedSize());
367 for (sys::MemoryBlock &
Block :
Group->AllocatedMem)
379class DefaultMMapper
final :
public SectionMemoryManager::MemoryMapper {
383 size_t NumBytes,
const sys::MemoryBlock *
const NearBlock,
384 unsigned Flags, std::error_code &EC)
override {
385 return sys::Memory::allocateMappedMemory(NumBytes, NearBlock, Flags, EC);
388 std::error_code protectMappedMemory(
const sys::MemoryBlock &
Block,
389 unsigned Flags)
override {
390 return sys::Memory::protectMappedMemory(
Block, Flags);
393 std::error_code releaseMappedMemory(sys::MemoryBlock &M)
override {
394 return sys::Memory::releaseMappedMemory(M);
404 OwnedMMapper = std::make_unique<DefaultMMapper>();
405 MMapper = OwnedMMapper.get();
virtual std::error_code releaseMappedMemory(sys::MemoryBlock &M)=0
virtual sys::MemoryBlock allocateMappedMemory(AllocationPurpose Purpose, size_t NumBytes, const sys::MemoryBlock *const NearBlock, unsigned Flags, std::error_code &EC)=0
virtual std::error_code protectMappedMemory(const sys::MemoryBlock &Block, unsigned Flags)=0
std::unique_ptr< MemoryMapper > OwnedMMapper
SectionMemoryManager(MemoryMapper *MM=nullptr, bool ReserveAlloc=false)
virtual void invalidateInstructionCache()
~SectionMemoryManager() override
virtual void reserveAllocationSpace(uintptr_t CodeSize, uint32_t CodeAlign, uintptr_t RODataSize, uint32_t RODataAlign, uintptr_t RWDataSize, uint32_t RWDataAlign) override
bool finalizeMemory(std::string *ErrMsg=nullptr) override
uint8_t * allocateSection(AllocationPurpose Purpose, uintptr_t Size, unsigned Alignment)
bool hasSpace(const MemoryGroup &MemGroup, uintptr_t Size) const
uint8_t * allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, StringRef SectionName, bool IsReadOnly) override
std::error_code applyMemoryGroupPermissions(MemoryGroup &MemGroup, unsigned Permissions)
uint8_t * allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, StringRef SectionName) override
SmallVector< sys::MemoryBlock, 16 > AllocatedMem
SmallVector< sys::MemoryBlock, 16 > PendingMem
SmallVector< FreeMemBlock, 16 > FreeMem