1 //===--- JITLinkMemoryManager.cpp - JITLinkMemoryManager implementation ---===// 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 #include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h" 11 #include "llvm/Support/Process.h" 12 13 namespace llvm { 14 namespace jitlink { 15 16 JITLinkMemoryManager::~JITLinkMemoryManager() = default; 17 JITLinkMemoryManager::Allocation::~Allocation() = default; 18 19 Expected<std::unique_ptr<JITLinkMemoryManager::Allocation>> 20 InProcessMemoryManager::allocate(const SegmentsRequestMap &Request) { 21 22 using AllocationMap = DenseMap<unsigned, sys::MemoryBlock>; 23 24 // Local class for allocation. 25 class IPMMAlloc : public Allocation { 26 public: 27 IPMMAlloc(AllocationMap SegBlocks) : SegBlocks(std::move(SegBlocks)) {} 28 MutableArrayRef<char> getWorkingMemory(ProtectionFlags Seg) override { 29 assert(SegBlocks.count(Seg) && "No allocation for segment"); 30 return {static_cast<char *>(SegBlocks[Seg].base()), 31 SegBlocks[Seg].allocatedSize()}; 32 } 33 JITTargetAddress getTargetMemory(ProtectionFlags Seg) override { 34 assert(SegBlocks.count(Seg) && "No allocation for segment"); 35 return reinterpret_cast<JITTargetAddress>(SegBlocks[Seg].base()); 36 } 37 void finalizeAsync(FinalizeContinuation OnFinalize) override { 38 OnFinalize(applyProtections()); 39 } 40 Error deallocate() override { 41 for (auto &KV : SegBlocks) 42 if (auto EC = sys::Memory::releaseMappedMemory(KV.second)) 43 return errorCodeToError(EC); 44 return Error::success(); 45 } 46 47 private: 48 Error applyProtections() { 49 for (auto &KV : SegBlocks) { 50 auto &Prot = KV.first; 51 auto &Block = KV.second; 52 if (auto EC = sys::Memory::protectMappedMemory(Block, Prot)) 53 return errorCodeToError(EC); 54 if (Prot & sys::Memory::MF_EXEC) 55 sys::Memory::InvalidateInstructionCache(Block.base(), 56 Block.allocatedSize()); 57 } 58 return Error::success(); 59 } 60 61 AllocationMap SegBlocks; 62 }; 63 64 AllocationMap Blocks; 65 const sys::Memory::ProtectionFlags ReadWrite = 66 static_cast<sys::Memory::ProtectionFlags>(sys::Memory::MF_READ | 67 sys::Memory::MF_WRITE); 68 69 for (auto &KV : Request) { 70 auto &Seg = KV.second; 71 72 if (Seg.getContentAlignment() > sys::Process::getPageSizeEstimate()) 73 return make_error<StringError>("Cannot request higher than page " 74 "alignment", 75 inconvertibleErrorCode()); 76 77 if (sys::Process::getPageSizeEstimate() % Seg.getContentAlignment() != 0) 78 return make_error<StringError>("Page size is not a multiple of " 79 "alignment", 80 inconvertibleErrorCode()); 81 82 uint64_t ZeroFillStart = 83 alignTo(Seg.getContentSize(), Seg.getZeroFillAlignment()); 84 uint64_t SegmentSize = ZeroFillStart + Seg.getZeroFillSize(); 85 86 std::error_code EC; 87 auto SegMem = 88 sys::Memory::allocateMappedMemory(SegmentSize, nullptr, ReadWrite, EC); 89 90 if (EC) 91 return errorCodeToError(EC); 92 93 // Zero out the zero-fill memory. 94 memset(static_cast<char *>(SegMem.base()) + ZeroFillStart, 0, 95 Seg.getZeroFillSize()); 96 97 // Record the block for this segment. 98 Blocks[KV.first] = std::move(SegMem); 99 } 100 return std::unique_ptr<InProcessMemoryManager::Allocation>( 101 new IPMMAlloc(std::move(Blocks))); 102 } 103 104 } // end namespace jitlink 105 } // end namespace llvm 106