xref: /aosp_15_r20/external/swiftshader/src/Reactor/ExecutableMemory.cpp (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
1*03ce13f7SAndroid Build Coastguard Worker // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2*03ce13f7SAndroid Build Coastguard Worker //
3*03ce13f7SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*03ce13f7SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*03ce13f7SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*03ce13f7SAndroid Build Coastguard Worker //
7*03ce13f7SAndroid Build Coastguard Worker //    http://www.apache.org/licenses/LICENSE-2.0
8*03ce13f7SAndroid Build Coastguard Worker //
9*03ce13f7SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*03ce13f7SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*03ce13f7SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*03ce13f7SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*03ce13f7SAndroid Build Coastguard Worker // limitations under the License.
14*03ce13f7SAndroid Build Coastguard Worker 
15*03ce13f7SAndroid Build Coastguard Worker #include "ExecutableMemory.hpp"
16*03ce13f7SAndroid Build Coastguard Worker 
17*03ce13f7SAndroid Build Coastguard Worker #include "Debug.hpp"
18*03ce13f7SAndroid Build Coastguard Worker 
19*03ce13f7SAndroid Build Coastguard Worker #if defined(_WIN32)
20*03ce13f7SAndroid Build Coastguard Worker #	ifndef WIN32_LEAN_AND_MEAN
21*03ce13f7SAndroid Build Coastguard Worker #		define WIN32_LEAN_AND_MEAN
22*03ce13f7SAndroid Build Coastguard Worker #	endif
23*03ce13f7SAndroid Build Coastguard Worker #	include <Windows.h>
24*03ce13f7SAndroid Build Coastguard Worker #	include <intrin.h>
25*03ce13f7SAndroid Build Coastguard Worker #elif defined(__Fuchsia__)
26*03ce13f7SAndroid Build Coastguard Worker #	include <unistd.h>
27*03ce13f7SAndroid Build Coastguard Worker #	include <zircon/process.h>
28*03ce13f7SAndroid Build Coastguard Worker #	include <zircon/syscalls.h>
29*03ce13f7SAndroid Build Coastguard Worker #else
30*03ce13f7SAndroid Build Coastguard Worker #	include <errno.h>
31*03ce13f7SAndroid Build Coastguard Worker #	include <sys/mman.h>
32*03ce13f7SAndroid Build Coastguard Worker #	include <stdlib.h>
33*03ce13f7SAndroid Build Coastguard Worker #	include <unistd.h>
34*03ce13f7SAndroid Build Coastguard Worker #endif
35*03ce13f7SAndroid Build Coastguard Worker 
36*03ce13f7SAndroid Build Coastguard Worker #if defined(__ANDROID__) && !defined(ANDROID_HOST_BUILD) && !defined(ANDROID_NDK_BUILD)
37*03ce13f7SAndroid Build Coastguard Worker #	include <sys/prctl.h>
38*03ce13f7SAndroid Build Coastguard Worker #endif
39*03ce13f7SAndroid Build Coastguard Worker 
40*03ce13f7SAndroid Build Coastguard Worker #include <memory.h>
41*03ce13f7SAndroid Build Coastguard Worker 
42*03ce13f7SAndroid Build Coastguard Worker #undef allocate
43*03ce13f7SAndroid Build Coastguard Worker #undef deallocate
44*03ce13f7SAndroid Build Coastguard Worker 
45*03ce13f7SAndroid Build Coastguard Worker #if(defined(__i386__) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)) && !defined(__x86__)
46*03ce13f7SAndroid Build Coastguard Worker #	define __x86__
47*03ce13f7SAndroid Build Coastguard Worker #endif
48*03ce13f7SAndroid Build Coastguard Worker 
49*03ce13f7SAndroid Build Coastguard Worker #define STRINGIFY(x) #x
50*03ce13f7SAndroid Build Coastguard Worker #define MACRO_STRINGIFY(x) STRINGIFY(x)
51*03ce13f7SAndroid Build Coastguard Worker 
52*03ce13f7SAndroid Build Coastguard Worker // A Clang extension to determine compiler features.
53*03ce13f7SAndroid Build Coastguard Worker // We use it to detect Sanitizer builds (e.g. -fsanitize=memory).
54*03ce13f7SAndroid Build Coastguard Worker #ifndef __has_feature
55*03ce13f7SAndroid Build Coastguard Worker #	define __has_feature(x) 0
56*03ce13f7SAndroid Build Coastguard Worker #endif
57*03ce13f7SAndroid Build Coastguard Worker 
58*03ce13f7SAndroid Build Coastguard Worker namespace rr {
59*03ce13f7SAndroid Build Coastguard Worker namespace {
60*03ce13f7SAndroid Build Coastguard Worker 
61*03ce13f7SAndroid Build Coastguard Worker struct Allocation
62*03ce13f7SAndroid Build Coastguard Worker {
63*03ce13f7SAndroid Build Coastguard Worker 	// size_t bytes;
64*03ce13f7SAndroid Build Coastguard Worker 	unsigned char *block;
65*03ce13f7SAndroid Build Coastguard Worker };
66*03ce13f7SAndroid Build Coastguard Worker 
allocateRaw(size_t bytes,size_t alignment)67*03ce13f7SAndroid Build Coastguard Worker void *allocateRaw(size_t bytes, size_t alignment)
68*03ce13f7SAndroid Build Coastguard Worker {
69*03ce13f7SAndroid Build Coastguard Worker 	ASSERT((alignment & (alignment - 1)) == 0);  // Power of 2 alignment.
70*03ce13f7SAndroid Build Coastguard Worker 
71*03ce13f7SAndroid Build Coastguard Worker #if defined(__linux__) && defined(REACTOR_ANONYMOUS_MMAP_NAME)
72*03ce13f7SAndroid Build Coastguard Worker 	if(alignment < sizeof(void *))
73*03ce13f7SAndroid Build Coastguard Worker 	{
74*03ce13f7SAndroid Build Coastguard Worker 		return malloc(bytes);
75*03ce13f7SAndroid Build Coastguard Worker 	}
76*03ce13f7SAndroid Build Coastguard Worker 	else
77*03ce13f7SAndroid Build Coastguard Worker 	{
78*03ce13f7SAndroid Build Coastguard Worker 		void *allocation;
79*03ce13f7SAndroid Build Coastguard Worker 		int result = posix_memalign(&allocation, alignment, bytes);
80*03ce13f7SAndroid Build Coastguard Worker 		if(result != 0)
81*03ce13f7SAndroid Build Coastguard Worker 		{
82*03ce13f7SAndroid Build Coastguard Worker 			errno = result;
83*03ce13f7SAndroid Build Coastguard Worker 			allocation = nullptr;
84*03ce13f7SAndroid Build Coastguard Worker 		}
85*03ce13f7SAndroid Build Coastguard Worker 		return allocation;
86*03ce13f7SAndroid Build Coastguard Worker 	}
87*03ce13f7SAndroid Build Coastguard Worker #else
88*03ce13f7SAndroid Build Coastguard Worker 	unsigned char *block = new unsigned char[bytes + sizeof(Allocation) + alignment];
89*03ce13f7SAndroid Build Coastguard Worker 	unsigned char *aligned = nullptr;
90*03ce13f7SAndroid Build Coastguard Worker 
91*03ce13f7SAndroid Build Coastguard Worker 	if(block)
92*03ce13f7SAndroid Build Coastguard Worker 	{
93*03ce13f7SAndroid Build Coastguard Worker 		aligned = (unsigned char *)((uintptr_t)(block + sizeof(Allocation) + alignment - 1) & -(intptr_t)alignment);
94*03ce13f7SAndroid Build Coastguard Worker 		Allocation *allocation = (Allocation *)(aligned - sizeof(Allocation));
95*03ce13f7SAndroid Build Coastguard Worker 
96*03ce13f7SAndroid Build Coastguard Worker 		// allocation->bytes = bytes;
97*03ce13f7SAndroid Build Coastguard Worker 		allocation->block = block;
98*03ce13f7SAndroid Build Coastguard Worker 	}
99*03ce13f7SAndroid Build Coastguard Worker 
100*03ce13f7SAndroid Build Coastguard Worker 	return aligned;
101*03ce13f7SAndroid Build Coastguard Worker #endif
102*03ce13f7SAndroid Build Coastguard Worker }
103*03ce13f7SAndroid Build Coastguard Worker 
104*03ce13f7SAndroid Build Coastguard Worker #if defined(_WIN32)
permissionsToProtectMode(int permissions)105*03ce13f7SAndroid Build Coastguard Worker DWORD permissionsToProtectMode(int permissions)
106*03ce13f7SAndroid Build Coastguard Worker {
107*03ce13f7SAndroid Build Coastguard Worker 	switch(permissions)
108*03ce13f7SAndroid Build Coastguard Worker 	{
109*03ce13f7SAndroid Build Coastguard Worker 	case PERMISSION_READ:
110*03ce13f7SAndroid Build Coastguard Worker 		return PAGE_READONLY;
111*03ce13f7SAndroid Build Coastguard Worker 	case PERMISSION_EXECUTE:
112*03ce13f7SAndroid Build Coastguard Worker 		return PAGE_EXECUTE;
113*03ce13f7SAndroid Build Coastguard Worker 	case PERMISSION_READ | PERMISSION_WRITE:
114*03ce13f7SAndroid Build Coastguard Worker 		return PAGE_READWRITE;
115*03ce13f7SAndroid Build Coastguard Worker 	case PERMISSION_READ | PERMISSION_EXECUTE:
116*03ce13f7SAndroid Build Coastguard Worker 		return PAGE_EXECUTE_READ;
117*03ce13f7SAndroid Build Coastguard Worker 	case PERMISSION_READ | PERMISSION_WRITE | PERMISSION_EXECUTE:
118*03ce13f7SAndroid Build Coastguard Worker 		return PAGE_EXECUTE_READWRITE;
119*03ce13f7SAndroid Build Coastguard Worker 	}
120*03ce13f7SAndroid Build Coastguard Worker 	return PAGE_NOACCESS;
121*03ce13f7SAndroid Build Coastguard Worker }
122*03ce13f7SAndroid Build Coastguard Worker #endif
123*03ce13f7SAndroid Build Coastguard Worker 
124*03ce13f7SAndroid Build Coastguard Worker #if !defined(_WIN32) && !defined(__Fuchsia__)
permissionsToMmapProt(int permissions)125*03ce13f7SAndroid Build Coastguard Worker int permissionsToMmapProt(int permissions)
126*03ce13f7SAndroid Build Coastguard Worker {
127*03ce13f7SAndroid Build Coastguard Worker 	int result = 0;
128*03ce13f7SAndroid Build Coastguard Worker 	if(permissions & PERMISSION_READ)
129*03ce13f7SAndroid Build Coastguard Worker 	{
130*03ce13f7SAndroid Build Coastguard Worker 		result |= PROT_READ;
131*03ce13f7SAndroid Build Coastguard Worker 	}
132*03ce13f7SAndroid Build Coastguard Worker 	if(permissions & PERMISSION_WRITE)
133*03ce13f7SAndroid Build Coastguard Worker 	{
134*03ce13f7SAndroid Build Coastguard Worker 		result |= PROT_WRITE;
135*03ce13f7SAndroid Build Coastguard Worker 	}
136*03ce13f7SAndroid Build Coastguard Worker 	if(permissions & PERMISSION_EXECUTE)
137*03ce13f7SAndroid Build Coastguard Worker 	{
138*03ce13f7SAndroid Build Coastguard Worker 		result |= PROT_EXEC;
139*03ce13f7SAndroid Build Coastguard Worker 	}
140*03ce13f7SAndroid Build Coastguard Worker 	return result;
141*03ce13f7SAndroid Build Coastguard Worker }
142*03ce13f7SAndroid Build Coastguard Worker #endif  // !defined(_WIN32) && !defined(__Fuchsia__)
143*03ce13f7SAndroid Build Coastguard Worker 
144*03ce13f7SAndroid Build Coastguard Worker #if defined(__linux__) && defined(REACTOR_ANONYMOUS_MMAP_NAME)
145*03ce13f7SAndroid Build Coastguard Worker #	if !defined(__ANDROID__) || defined(ANDROID_HOST_BUILD) || defined(ANDROID_NDK_BUILD)
146*03ce13f7SAndroid Build Coastguard Worker // Create a file descriptor for anonymous memory with the given
147*03ce13f7SAndroid Build Coastguard Worker // name. Returns -1 on failure.
148*03ce13f7SAndroid Build Coastguard Worker // TODO: remove once libc wrapper exists.
memfd_create(const char * name,unsigned int flags)149*03ce13f7SAndroid Build Coastguard Worker static int memfd_create(const char *name, unsigned int flags)
150*03ce13f7SAndroid Build Coastguard Worker {
151*03ce13f7SAndroid Build Coastguard Worker #		if __aarch64__
152*03ce13f7SAndroid Build Coastguard Worker #			define __NR_memfd_create 279
153*03ce13f7SAndroid Build Coastguard Worker #		elif __arm__
154*03ce13f7SAndroid Build Coastguard Worker #			define __NR_memfd_create 279
155*03ce13f7SAndroid Build Coastguard Worker #		elif __powerpc64__
156*03ce13f7SAndroid Build Coastguard Worker #			define __NR_memfd_create 360
157*03ce13f7SAndroid Build Coastguard Worker #		elif __i386__
158*03ce13f7SAndroid Build Coastguard Worker #			define __NR_memfd_create 356
159*03ce13f7SAndroid Build Coastguard Worker #		elif __x86_64__
160*03ce13f7SAndroid Build Coastguard Worker #			define __NR_memfd_create 319
161*03ce13f7SAndroid Build Coastguard Worker #		endif /* __NR_memfd_create__ */
162*03ce13f7SAndroid Build Coastguard Worker #		ifdef __NR_memfd_create
163*03ce13f7SAndroid Build Coastguard Worker 	// In the event of no system call this returns -1 with errno set
164*03ce13f7SAndroid Build Coastguard Worker 	// as ENOSYS.
165*03ce13f7SAndroid Build Coastguard Worker 	return syscall(__NR_memfd_create, name, flags);
166*03ce13f7SAndroid Build Coastguard Worker #		else
167*03ce13f7SAndroid Build Coastguard Worker 	return -1;
168*03ce13f7SAndroid Build Coastguard Worker #		endif
169*03ce13f7SAndroid Build Coastguard Worker }
170*03ce13f7SAndroid Build Coastguard Worker 
171*03ce13f7SAndroid Build Coastguard Worker // Returns a file descriptor for use with an anonymous mmap, if
172*03ce13f7SAndroid Build Coastguard Worker // memfd_create fails, -1 is returned. Note, the mappings should be
173*03ce13f7SAndroid Build Coastguard Worker // MAP_PRIVATE so that underlying pages aren't shared.
anonymousFd()174*03ce13f7SAndroid Build Coastguard Worker int anonymousFd()
175*03ce13f7SAndroid Build Coastguard Worker {
176*03ce13f7SAndroid Build Coastguard Worker 	static int fd = memfd_create(MACRO_STRINGIFY(REACTOR_ANONYMOUS_MMAP_NAME), 0);
177*03ce13f7SAndroid Build Coastguard Worker 	return fd;
178*03ce13f7SAndroid Build Coastguard Worker }
179*03ce13f7SAndroid Build Coastguard Worker #	else   // __ANDROID__ && !ANDROID_HOST_BUILD && !ANDROID_NDK_BUILD
anonymousFd()180*03ce13f7SAndroid Build Coastguard Worker int anonymousFd()
181*03ce13f7SAndroid Build Coastguard Worker {
182*03ce13f7SAndroid Build Coastguard Worker 	return -1;
183*03ce13f7SAndroid Build Coastguard Worker }
184*03ce13f7SAndroid Build Coastguard Worker #	endif  // __ANDROID__ && !ANDROID_HOST_BUILD && !ANDROID_NDK_BUILD
185*03ce13f7SAndroid Build Coastguard Worker 
186*03ce13f7SAndroid Build Coastguard Worker // Ensure there is enough space in the "anonymous" fd for length.
ensureAnonFileSize(int anonFd,size_t length)187*03ce13f7SAndroid Build Coastguard Worker void ensureAnonFileSize(int anonFd, size_t length)
188*03ce13f7SAndroid Build Coastguard Worker {
189*03ce13f7SAndroid Build Coastguard Worker 	static size_t fileSize = 0;
190*03ce13f7SAndroid Build Coastguard Worker 	if(length > fileSize)
191*03ce13f7SAndroid Build Coastguard Worker 	{
192*03ce13f7SAndroid Build Coastguard Worker 		[[maybe_unused]] int result = ftruncate(anonFd, length);
193*03ce13f7SAndroid Build Coastguard Worker 		ASSERT(result == 0);
194*03ce13f7SAndroid Build Coastguard Worker 		fileSize = length;
195*03ce13f7SAndroid Build Coastguard Worker 	}
196*03ce13f7SAndroid Build Coastguard Worker }
197*03ce13f7SAndroid Build Coastguard Worker #endif  // defined(__linux__) && defined(REACTOR_ANONYMOUS_MMAP_NAME)
198*03ce13f7SAndroid Build Coastguard Worker 
199*03ce13f7SAndroid Build Coastguard Worker #if defined(__Fuchsia__)
permissionsToZxVmOptions(int permissions)200*03ce13f7SAndroid Build Coastguard Worker zx_vm_option_t permissionsToZxVmOptions(int permissions)
201*03ce13f7SAndroid Build Coastguard Worker {
202*03ce13f7SAndroid Build Coastguard Worker 	zx_vm_option_t result = 0;
203*03ce13f7SAndroid Build Coastguard Worker 	if(permissions & PERMISSION_READ)
204*03ce13f7SAndroid Build Coastguard Worker 	{
205*03ce13f7SAndroid Build Coastguard Worker 		result |= ZX_VM_PERM_READ;
206*03ce13f7SAndroid Build Coastguard Worker 	}
207*03ce13f7SAndroid Build Coastguard Worker 	if(permissions & PERMISSION_WRITE)
208*03ce13f7SAndroid Build Coastguard Worker 	{
209*03ce13f7SAndroid Build Coastguard Worker 		result |= ZX_VM_PERM_WRITE;
210*03ce13f7SAndroid Build Coastguard Worker 	}
211*03ce13f7SAndroid Build Coastguard Worker 	if(permissions & PERMISSION_EXECUTE)
212*03ce13f7SAndroid Build Coastguard Worker 	{
213*03ce13f7SAndroid Build Coastguard Worker 		result |= ZX_VM_PERM_EXECUTE;
214*03ce13f7SAndroid Build Coastguard Worker 	}
215*03ce13f7SAndroid Build Coastguard Worker 	return result;
216*03ce13f7SAndroid Build Coastguard Worker }
217*03ce13f7SAndroid Build Coastguard Worker #endif  // defined(__Fuchsia__)
218*03ce13f7SAndroid Build Coastguard Worker 
219*03ce13f7SAndroid Build Coastguard Worker }  // anonymous namespace
220*03ce13f7SAndroid Build Coastguard Worker 
memoryPageSize()221*03ce13f7SAndroid Build Coastguard Worker size_t memoryPageSize()
222*03ce13f7SAndroid Build Coastguard Worker {
223*03ce13f7SAndroid Build Coastguard Worker 	static int pageSize = [] {
224*03ce13f7SAndroid Build Coastguard Worker #if defined(_WIN32)
225*03ce13f7SAndroid Build Coastguard Worker 		SYSTEM_INFO systemInfo;
226*03ce13f7SAndroid Build Coastguard Worker 		GetSystemInfo(&systemInfo);
227*03ce13f7SAndroid Build Coastguard Worker 		return systemInfo.dwPageSize;
228*03ce13f7SAndroid Build Coastguard Worker #else
229*03ce13f7SAndroid Build Coastguard Worker 		return sysconf(_SC_PAGESIZE);
230*03ce13f7SAndroid Build Coastguard Worker #endif
231*03ce13f7SAndroid Build Coastguard Worker 	}();
232*03ce13f7SAndroid Build Coastguard Worker 
233*03ce13f7SAndroid Build Coastguard Worker 	return pageSize;
234*03ce13f7SAndroid Build Coastguard Worker }
235*03ce13f7SAndroid Build Coastguard Worker 
allocate(size_t bytes,size_t alignment)236*03ce13f7SAndroid Build Coastguard Worker void *allocate(size_t bytes, size_t alignment)
237*03ce13f7SAndroid Build Coastguard Worker {
238*03ce13f7SAndroid Build Coastguard Worker 	void *memory = allocateRaw(bytes, alignment);
239*03ce13f7SAndroid Build Coastguard Worker 
240*03ce13f7SAndroid Build Coastguard Worker 	// Zero-initialize the memory, for security reasons.
241*03ce13f7SAndroid Build Coastguard Worker 	// MemorySanitizer builds skip this so that we can detect when we
242*03ce13f7SAndroid Build Coastguard Worker 	// inadvertently rely on this, which would indicate a bug.
243*03ce13f7SAndroid Build Coastguard Worker 	if(memory && !__has_feature(memory_sanitizer))
244*03ce13f7SAndroid Build Coastguard Worker 	{
245*03ce13f7SAndroid Build Coastguard Worker 		memset(memory, 0, bytes);
246*03ce13f7SAndroid Build Coastguard Worker 	}
247*03ce13f7SAndroid Build Coastguard Worker 
248*03ce13f7SAndroid Build Coastguard Worker 	return memory;
249*03ce13f7SAndroid Build Coastguard Worker }
250*03ce13f7SAndroid Build Coastguard Worker 
deallocate(void * memory)251*03ce13f7SAndroid Build Coastguard Worker void deallocate(void *memory)
252*03ce13f7SAndroid Build Coastguard Worker {
253*03ce13f7SAndroid Build Coastguard Worker #if defined(__linux__) && defined(REACTOR_ANONYMOUS_MMAP_NAME)
254*03ce13f7SAndroid Build Coastguard Worker 	free(memory);
255*03ce13f7SAndroid Build Coastguard Worker #else
256*03ce13f7SAndroid Build Coastguard Worker 	if(memory)
257*03ce13f7SAndroid Build Coastguard Worker 	{
258*03ce13f7SAndroid Build Coastguard Worker 		unsigned char *aligned = (unsigned char *)memory;
259*03ce13f7SAndroid Build Coastguard Worker 		Allocation *allocation = (Allocation *)(aligned - sizeof(Allocation));
260*03ce13f7SAndroid Build Coastguard Worker 
261*03ce13f7SAndroid Build Coastguard Worker 		delete[] allocation->block;
262*03ce13f7SAndroid Build Coastguard Worker 	}
263*03ce13f7SAndroid Build Coastguard Worker #endif
264*03ce13f7SAndroid Build Coastguard Worker }
265*03ce13f7SAndroid Build Coastguard Worker 
266*03ce13f7SAndroid Build Coastguard Worker // Rounds |x| up to a multiple of |m|, where |m| is a power of 2.
roundUp(uintptr_t x,uintptr_t m)267*03ce13f7SAndroid Build Coastguard Worker inline uintptr_t roundUp(uintptr_t x, uintptr_t m)
268*03ce13f7SAndroid Build Coastguard Worker {
269*03ce13f7SAndroid Build Coastguard Worker 	ASSERT(m > 0 && (m & (m - 1)) == 0);  // |m| must be a power of 2.
270*03ce13f7SAndroid Build Coastguard Worker 	return (x + m - 1) & ~(m - 1);
271*03ce13f7SAndroid Build Coastguard Worker }
272*03ce13f7SAndroid Build Coastguard Worker 
allocateMemoryPages(size_t bytes,int permissions,bool need_exec)273*03ce13f7SAndroid Build Coastguard Worker void *allocateMemoryPages(size_t bytes, int permissions, bool need_exec)
274*03ce13f7SAndroid Build Coastguard Worker {
275*03ce13f7SAndroid Build Coastguard Worker 	size_t pageSize = memoryPageSize();
276*03ce13f7SAndroid Build Coastguard Worker 	size_t length = roundUp(bytes, pageSize);
277*03ce13f7SAndroid Build Coastguard Worker 	void *mapping = nullptr;
278*03ce13f7SAndroid Build Coastguard Worker 
279*03ce13f7SAndroid Build Coastguard Worker #if defined(_WIN32)
280*03ce13f7SAndroid Build Coastguard Worker 	return VirtualAlloc(nullptr, length, MEM_COMMIT | MEM_RESERVE,
281*03ce13f7SAndroid Build Coastguard Worker 	                    permissionsToProtectMode(permissions));
282*03ce13f7SAndroid Build Coastguard Worker #elif defined(__linux__) && defined(REACTOR_ANONYMOUS_MMAP_NAME)
283*03ce13f7SAndroid Build Coastguard Worker 	int flags = MAP_PRIVATE;
284*03ce13f7SAndroid Build Coastguard Worker 
285*03ce13f7SAndroid Build Coastguard Worker 	// Try to name the memory region for the executable code,
286*03ce13f7SAndroid Build Coastguard Worker 	// to aid profilers.
287*03ce13f7SAndroid Build Coastguard Worker 	int anonFd = anonymousFd();
288*03ce13f7SAndroid Build Coastguard Worker 	if(anonFd == -1)
289*03ce13f7SAndroid Build Coastguard Worker 	{
290*03ce13f7SAndroid Build Coastguard Worker 		flags |= MAP_ANONYMOUS;
291*03ce13f7SAndroid Build Coastguard Worker 	}
292*03ce13f7SAndroid Build Coastguard Worker 	else
293*03ce13f7SAndroid Build Coastguard Worker 	{
294*03ce13f7SAndroid Build Coastguard Worker 		ensureAnonFileSize(anonFd, length);
295*03ce13f7SAndroid Build Coastguard Worker 	}
296*03ce13f7SAndroid Build Coastguard Worker 
297*03ce13f7SAndroid Build Coastguard Worker 	mapping = mmap(
298*03ce13f7SAndroid Build Coastguard Worker 	    nullptr, length, permissionsToMmapProt(permissions), flags, anonFd, 0);
299*03ce13f7SAndroid Build Coastguard Worker 
300*03ce13f7SAndroid Build Coastguard Worker 	if(mapping == MAP_FAILED)
301*03ce13f7SAndroid Build Coastguard Worker 	{
302*03ce13f7SAndroid Build Coastguard Worker 		mapping = nullptr;
303*03ce13f7SAndroid Build Coastguard Worker 	}
304*03ce13f7SAndroid Build Coastguard Worker #	if defined(__ANDROID__) && !defined(ANDROID_HOST_BUILD) && !defined(ANDROID_NDK_BUILD)
305*03ce13f7SAndroid Build Coastguard Worker 	else
306*03ce13f7SAndroid Build Coastguard Worker 	{
307*03ce13f7SAndroid Build Coastguard Worker 		// On Android, prefer to use a non-standard prctl called
308*03ce13f7SAndroid Build Coastguard Worker 		// PR_SET_VMA_ANON_NAME to set the name of a private anonymous
309*03ce13f7SAndroid Build Coastguard Worker 		// mapping, as Android restricts EXECUTE permission on
310*03ce13f7SAndroid Build Coastguard Worker 		// CoW/shared anonymous mappings with sepolicy neverallows.
311*03ce13f7SAndroid Build Coastguard Worker 		prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, mapping, length,
312*03ce13f7SAndroid Build Coastguard Worker 		      MACRO_STRINGIFY(REACTOR_ANONYMOUS_MMAP_NAME));
313*03ce13f7SAndroid Build Coastguard Worker 	}
314*03ce13f7SAndroid Build Coastguard Worker #	endif  // __ANDROID__ && !ANDROID_HOST_BUILD && !ANDROID_NDK_BUILD
315*03ce13f7SAndroid Build Coastguard Worker #elif defined(__Fuchsia__)
316*03ce13f7SAndroid Build Coastguard Worker 	zx_handle_t vmo;
317*03ce13f7SAndroid Build Coastguard Worker 	if(zx_vmo_create(length, 0, &vmo) != ZX_OK)
318*03ce13f7SAndroid Build Coastguard Worker 	{
319*03ce13f7SAndroid Build Coastguard Worker 		return nullptr;
320*03ce13f7SAndroid Build Coastguard Worker 	}
321*03ce13f7SAndroid Build Coastguard Worker 	if(need_exec &&
322*03ce13f7SAndroid Build Coastguard Worker 	   zx_vmo_replace_as_executable(vmo, ZX_HANDLE_INVALID, &vmo) != ZX_OK)
323*03ce13f7SAndroid Build Coastguard Worker 	{
324*03ce13f7SAndroid Build Coastguard Worker 		return nullptr;
325*03ce13f7SAndroid Build Coastguard Worker 	}
326*03ce13f7SAndroid Build Coastguard Worker 	zx_vaddr_t reservation;
327*03ce13f7SAndroid Build Coastguard Worker 	zx_status_t status = zx_vmar_map(
328*03ce13f7SAndroid Build Coastguard Worker 	    zx_vmar_root_self(), permissionsToZxVmOptions(permissions), 0, vmo,
329*03ce13f7SAndroid Build Coastguard Worker 	    0, length, &reservation);
330*03ce13f7SAndroid Build Coastguard Worker 	zx_handle_close(vmo);
331*03ce13f7SAndroid Build Coastguard Worker 	if(status != ZX_OK)
332*03ce13f7SAndroid Build Coastguard Worker 	{
333*03ce13f7SAndroid Build Coastguard Worker 		return nullptr;
334*03ce13f7SAndroid Build Coastguard Worker 	}
335*03ce13f7SAndroid Build Coastguard Worker 
336*03ce13f7SAndroid Build Coastguard Worker 	// zx_vmar_map() returns page-aligned address.
337*03ce13f7SAndroid Build Coastguard Worker 	ASSERT(roundUp(reservation, pageSize) == reservation);
338*03ce13f7SAndroid Build Coastguard Worker 
339*03ce13f7SAndroid Build Coastguard Worker 	mapping = reinterpret_cast<void *>(reservation);
340*03ce13f7SAndroid Build Coastguard Worker #elif defined(__APPLE__)
341*03ce13f7SAndroid Build Coastguard Worker 	int prot = permissionsToMmapProt(permissions);
342*03ce13f7SAndroid Build Coastguard Worker 	int flags = MAP_PRIVATE | MAP_ANONYMOUS;
343*03ce13f7SAndroid Build Coastguard Worker 	// On macOS 10.14 and higher, executables that are code signed with the
344*03ce13f7SAndroid Build Coastguard Worker 	// "runtime" option cannot execute writable memory by default. They can opt
345*03ce13f7SAndroid Build Coastguard Worker 	// into this capability by specifying the "com.apple.security.cs.allow-jit"
346*03ce13f7SAndroid Build Coastguard Worker 	// code signing entitlement and allocating the region with the MAP_JIT flag.
347*03ce13f7SAndroid Build Coastguard Worker 	mapping = mmap(nullptr, length, prot, flags | MAP_JIT, -1, 0);
348*03ce13f7SAndroid Build Coastguard Worker 
349*03ce13f7SAndroid Build Coastguard Worker 	if(mapping == MAP_FAILED)
350*03ce13f7SAndroid Build Coastguard Worker 	{
351*03ce13f7SAndroid Build Coastguard Worker 		// Retry without MAP_JIT (for older macOS versions).
352*03ce13f7SAndroid Build Coastguard Worker 		mapping = mmap(nullptr, length, prot, flags, -1, 0);
353*03ce13f7SAndroid Build Coastguard Worker 	}
354*03ce13f7SAndroid Build Coastguard Worker 
355*03ce13f7SAndroid Build Coastguard Worker 	if(mapping == MAP_FAILED)
356*03ce13f7SAndroid Build Coastguard Worker 	{
357*03ce13f7SAndroid Build Coastguard Worker 		mapping = nullptr;
358*03ce13f7SAndroid Build Coastguard Worker 	}
359*03ce13f7SAndroid Build Coastguard Worker #else
360*03ce13f7SAndroid Build Coastguard Worker 	mapping = allocate(length, pageSize);
361*03ce13f7SAndroid Build Coastguard Worker 	protectMemoryPages(mapping, length, permissions);
362*03ce13f7SAndroid Build Coastguard Worker #endif
363*03ce13f7SAndroid Build Coastguard Worker 
364*03ce13f7SAndroid Build Coastguard Worker 	return mapping;
365*03ce13f7SAndroid Build Coastguard Worker }
366*03ce13f7SAndroid Build Coastguard Worker 
protectMemoryPages(void * memory,size_t bytes,int permissions)367*03ce13f7SAndroid Build Coastguard Worker void protectMemoryPages(void *memory, size_t bytes, int permissions)
368*03ce13f7SAndroid Build Coastguard Worker {
369*03ce13f7SAndroid Build Coastguard Worker 	if(bytes == 0)
370*03ce13f7SAndroid Build Coastguard Worker 	{
371*03ce13f7SAndroid Build Coastguard Worker 		return;
372*03ce13f7SAndroid Build Coastguard Worker 	}
373*03ce13f7SAndroid Build Coastguard Worker 
374*03ce13f7SAndroid Build Coastguard Worker 	bytes = roundUp(bytes, memoryPageSize());
375*03ce13f7SAndroid Build Coastguard Worker 
376*03ce13f7SAndroid Build Coastguard Worker #if defined(_WIN32)
377*03ce13f7SAndroid Build Coastguard Worker 	unsigned long oldProtection;
378*03ce13f7SAndroid Build Coastguard Worker 	BOOL result =
379*03ce13f7SAndroid Build Coastguard Worker 	    VirtualProtect(memory, bytes, permissionsToProtectMode(permissions),
380*03ce13f7SAndroid Build Coastguard Worker 	                   &oldProtection);
381*03ce13f7SAndroid Build Coastguard Worker 	ASSERT(result);
382*03ce13f7SAndroid Build Coastguard Worker #elif defined(__Fuchsia__)
383*03ce13f7SAndroid Build Coastguard Worker 	zx_status_t status = zx_vmar_protect(
384*03ce13f7SAndroid Build Coastguard Worker 	    zx_vmar_root_self(), permissionsToZxVmOptions(permissions),
385*03ce13f7SAndroid Build Coastguard Worker 	    reinterpret_cast<zx_vaddr_t>(memory), bytes);
386*03ce13f7SAndroid Build Coastguard Worker 	ASSERT(status == ZX_OK);
387*03ce13f7SAndroid Build Coastguard Worker #else
388*03ce13f7SAndroid Build Coastguard Worker 	int result =
389*03ce13f7SAndroid Build Coastguard Worker 	    mprotect(memory, bytes, permissionsToMmapProt(permissions));
390*03ce13f7SAndroid Build Coastguard Worker 	ASSERT(result == 0);
391*03ce13f7SAndroid Build Coastguard Worker #endif
392*03ce13f7SAndroid Build Coastguard Worker }
393*03ce13f7SAndroid Build Coastguard Worker 
deallocateMemoryPages(void * memory,size_t bytes)394*03ce13f7SAndroid Build Coastguard Worker void deallocateMemoryPages(void *memory, size_t bytes)
395*03ce13f7SAndroid Build Coastguard Worker {
396*03ce13f7SAndroid Build Coastguard Worker #if defined(_WIN32)
397*03ce13f7SAndroid Build Coastguard Worker 	unsigned long oldProtection;
398*03ce13f7SAndroid Build Coastguard Worker 	BOOL result;
399*03ce13f7SAndroid Build Coastguard Worker 	result = VirtualProtect(memory, bytes, PAGE_READWRITE, &oldProtection);
400*03ce13f7SAndroid Build Coastguard Worker 	ASSERT(result);
401*03ce13f7SAndroid Build Coastguard Worker 	result = VirtualFree(memory, 0, MEM_RELEASE);
402*03ce13f7SAndroid Build Coastguard Worker 	ASSERT(result);
403*03ce13f7SAndroid Build Coastguard Worker #elif defined(__APPLE__) || (defined(__linux__) && defined(REACTOR_ANONYMOUS_MMAP_NAME))
404*03ce13f7SAndroid Build Coastguard Worker 	size_t pageSize = memoryPageSize();
405*03ce13f7SAndroid Build Coastguard Worker 	size_t length = (bytes + pageSize - 1) & ~(pageSize - 1);
406*03ce13f7SAndroid Build Coastguard Worker 	int result = munmap(memory, length);
407*03ce13f7SAndroid Build Coastguard Worker 	ASSERT(result == 0);
408*03ce13f7SAndroid Build Coastguard Worker #elif defined(__Fuchsia__)
409*03ce13f7SAndroid Build Coastguard Worker 	size_t pageSize = memoryPageSize();
410*03ce13f7SAndroid Build Coastguard Worker 	size_t length = roundUp(bytes, pageSize);
411*03ce13f7SAndroid Build Coastguard Worker 	zx_status_t status = zx_vmar_unmap(
412*03ce13f7SAndroid Build Coastguard Worker 	    zx_vmar_root_self(), reinterpret_cast<zx_vaddr_t>(memory), length);
413*03ce13f7SAndroid Build Coastguard Worker 	ASSERT(status == ZX_OK);
414*03ce13f7SAndroid Build Coastguard Worker #else
415*03ce13f7SAndroid Build Coastguard Worker 	int result = mprotect(memory, bytes, PROT_READ | PROT_WRITE);
416*03ce13f7SAndroid Build Coastguard Worker 	ASSERT(result == 0);
417*03ce13f7SAndroid Build Coastguard Worker 	deallocate(memory);
418*03ce13f7SAndroid Build Coastguard Worker #endif
419*03ce13f7SAndroid Build Coastguard Worker }
420*03ce13f7SAndroid Build Coastguard Worker 
421*03ce13f7SAndroid Build Coastguard Worker }  // namespace rr
422