1 //===- MemoryMapper.h - Cross-process memory mapper -------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // Cross-process (and in-process) memory mapping and transfer 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef LLVM_EXECUTIONENGINE_ORC_MEMORYMAPPER_H 14 #define LLVM_EXECUTIONENGINE_ORC_MEMORYMAPPER_H 15 16 #include "llvm/ExecutionEngine/Orc/Core.h" 17 #include "llvm/ExecutionEngine/Orc/Shared/MemoryFlags.h" 18 #include "llvm/Support/Compiler.h" 19 #include "llvm/Support/Process.h" 20 21 #include <mutex> 22 23 namespace llvm { 24 namespace orc { 25 26 /// Manages mapping, content transfer and protections for JIT memory 27 class LLVM_ABI MemoryMapper { 28 public: 29 /// Represents a single allocation containing multiple segments and 30 /// initialization and deinitialization actions 31 struct AllocInfo { 32 struct SegInfo { 33 ExecutorAddrDiff Offset; 34 const char *WorkingMem; 35 size_t ContentSize; 36 size_t ZeroFillSize; 37 AllocGroup AG; 38 }; 39 40 ExecutorAddr MappingBase; 41 std::vector<SegInfo> Segments; 42 shared::AllocActions Actions; 43 }; 44 45 using OnReservedFunction = unique_function<void(Expected<ExecutorAddrRange>)>; 46 47 // Page size of the target process 48 virtual unsigned int getPageSize() = 0; 49 50 /// Reserves address space in executor process 51 virtual void reserve(size_t NumBytes, OnReservedFunction OnReserved) = 0; 52 53 /// Provides working memory 54 virtual char *prepare(ExecutorAddr Addr, size_t ContentSize) = 0; 55 56 using OnInitializedFunction = unique_function<void(Expected<ExecutorAddr>)>; 57 58 /// Ensures executor memory is synchronized with working copy memory, sends 59 /// functions to be called after initilization and before deinitialization and 60 /// applies memory protections 61 /// Returns a unique address identifying the allocation. This address should 62 /// be passed to deinitialize to run deallocation actions (and reset 63 /// permissions where possible). 64 virtual void initialize(AllocInfo &AI, 65 OnInitializedFunction OnInitialized) = 0; 66 67 using OnDeinitializedFunction = unique_function<void(Error)>; 68 69 /// Runs previously specified deinitialization actions 70 /// Executor addresses returned by initialize should be passed 71 virtual void deinitialize(ArrayRef<ExecutorAddr> Allocations, 72 OnDeinitializedFunction OnDeInitialized) = 0; 73 74 using OnReleasedFunction = unique_function<void(Error)>; 75 76 /// Release address space acquired through reserve() 77 virtual void release(ArrayRef<ExecutorAddr> Reservations, 78 OnReleasedFunction OnRelease) = 0; 79 80 virtual ~MemoryMapper(); 81 }; 82 83 class LLVM_ABI InProcessMemoryMapper : public MemoryMapper { 84 public: 85 InProcessMemoryMapper(size_t PageSize); 86 87 static Expected<std::unique_ptr<InProcessMemoryMapper>> Create(); 88 getPageSize()89 unsigned int getPageSize() override { return PageSize; } 90 91 void reserve(size_t NumBytes, OnReservedFunction OnReserved) override; 92 93 void initialize(AllocInfo &AI, OnInitializedFunction OnInitialized) override; 94 95 char *prepare(ExecutorAddr Addr, size_t ContentSize) override; 96 97 void deinitialize(ArrayRef<ExecutorAddr> Allocations, 98 OnDeinitializedFunction OnDeInitialized) override; 99 100 void release(ArrayRef<ExecutorAddr> Reservations, 101 OnReleasedFunction OnRelease) override; 102 103 ~InProcessMemoryMapper() override; 104 105 private: 106 struct Allocation { 107 size_t Size; 108 std::vector<shared::WrapperFunctionCall> DeinitializationActions; 109 }; 110 using AllocationMap = DenseMap<ExecutorAddr, Allocation>; 111 112 struct Reservation { 113 size_t Size; 114 std::vector<ExecutorAddr> Allocations; 115 }; 116 using ReservationMap = DenseMap<void *, Reservation>; 117 118 std::mutex Mutex; 119 ReservationMap Reservations; 120 AllocationMap Allocations; 121 122 size_t PageSize; 123 }; 124 125 class LLVM_ABI SharedMemoryMapper final : public MemoryMapper { 126 public: 127 struct SymbolAddrs { 128 ExecutorAddr Instance; 129 ExecutorAddr Reserve; 130 ExecutorAddr Initialize; 131 ExecutorAddr Deinitialize; 132 ExecutorAddr Release; 133 }; 134 135 SharedMemoryMapper(ExecutorProcessControl &EPC, SymbolAddrs SAs, 136 size_t PageSize); 137 138 static Expected<std::unique_ptr<SharedMemoryMapper>> 139 Create(ExecutorProcessControl &EPC, SymbolAddrs SAs); 140 getPageSize()141 unsigned int getPageSize() override { return PageSize; } 142 143 void reserve(size_t NumBytes, OnReservedFunction OnReserved) override; 144 145 char *prepare(ExecutorAddr Addr, size_t ContentSize) override; 146 147 void initialize(AllocInfo &AI, OnInitializedFunction OnInitialized) override; 148 149 void deinitialize(ArrayRef<ExecutorAddr> Allocations, 150 OnDeinitializedFunction OnDeInitialized) override; 151 152 void release(ArrayRef<ExecutorAddr> Reservations, 153 OnReleasedFunction OnRelease) override; 154 155 ~SharedMemoryMapper() override; 156 157 private: 158 struct Reservation { 159 void *LocalAddr; 160 size_t Size; 161 int SharedMemoryId; 162 }; 163 164 ExecutorProcessControl &EPC; 165 SymbolAddrs SAs; 166 167 std::mutex Mutex; 168 169 std::map<ExecutorAddr, Reservation> Reservations; 170 171 size_t PageSize; 172 }; 173 174 } // namespace orc 175 } // end namespace llvm 176 177 #endif // LLVM_EXECUTIONENGINE_ORC_MEMORYMAPPER_H 178