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