diff options
author | Moritz Angermann <moritz.angermann@gmail.com> | 2021-02-13 16:44:19 +0800 |
---|---|---|
committer | Marge Bot <ben+marge-bot@smart-cactus.org> | 2021-03-29 17:25:49 -0400 |
commit | e754ff7f178a629a2261cba77a29d9510391aebd (patch) | |
tree | 77aca9f315288b52efbc9d410a57300a4029279d /rts/sm/Storage.c | |
parent | 4421fb34b3a70db1323833337c94ac4364824124 (diff) | |
download | haskell-e754ff7f178a629a2261cba77a29d9510391aebd.tar.gz |
Allocate Adjustors and mark them readable in two steps
This drops allocateExec for darwin, and replaces it with
a alloc, write, mark executable strategy instead. This prevents
us from trying to allocate an executable range and then write to
it, which X^W will prohibit on darwin.
This will *only* work if we can use mmap.
Diffstat (limited to 'rts/sm/Storage.c')
-rw-r--r-- | rts/sm/Storage.c | 37 |
1 files changed, 36 insertions, 1 deletions
diff --git a/rts/sm/Storage.c b/rts/sm/Storage.c index dc0dd7fd01..37f32de0f5 100644 --- a/rts/sm/Storage.c +++ b/rts/sm/Storage.c @@ -11,6 +11,18 @@ * * ---------------------------------------------------------------------------*/ +#include <ghcconfig.h> +#if RTS_LINKER_USE_MMAP +/* + * On FreeBSD and Darwin, when _XOPEN_SOURCE is defined, MAP_ANONYMOUS is not + * exposed from <sys/mman.h>. Include <sys/mman.h> before "PosixSource.h". + * + * Alternatively, we could drop "PosixSource.h" from this file, but for just + * one non-POSIX macro, that seems a needless price to pay. + */ +#include <sys/mman.h> +#endif + #include "PosixSource.h" #include "Rts.h" @@ -34,6 +46,10 @@ #include "Hash.h" #endif +#if RTS_LINKER_USE_MMAP +#include "LinkerInternals.h" +#endif + #include <string.h> #include "ffi.h" @@ -1791,6 +1807,20 @@ void flushExec (W_ len, AdjustorExecutable exec_addr) #endif } +#if RTS_LINKER_USE_MMAP +AdjustorWritable allocateWrite(W_ bytes) { + return mmapForLinker(bytes, PROT_READ | PROT_WRITE, MAP_ANONYMOUS, -1, 0); +} + +void markExec(W_ bytes, AdjustorWritable writ) { + mmapForLinkerMarkExecutable(writ, bytes); +} + +void freeWrite(W_ bytes, AdjustorWritable writ) { + munmap(writ, bytes); +} +#endif + #if defined(linux_HOST_OS) || defined(netbsd_HOST_OS) // On Linux we need to use libffi for allocating executable memory, @@ -1820,7 +1850,7 @@ void freeExec (AdjustorExecutable addr) RELEASE_SM_LOCK } -#elif (defined(arm_HOST_ARCH) || defined(aarch64_HOST_ARCH)) && (defined(ios_HOST_OS) || defined(darwin_HOST_OS)) +#elif defined(darwin_HOST_OS) static HashTable* allocatedExecs; @@ -1828,6 +1858,11 @@ AdjustorWritable allocateExec(W_ bytes, AdjustorExecutable *exec_ret) { AdjustorWritable writ; ffi_closure* cl; + // This check is necessary as we can't use allocateExec for anything *but* + // ffi_closures on ios/darwin on arm. libffi does some heavy lifting to + // get around the X^W restrictions, and we can't just use this codepath + // to allocate generic executable space. For those cases we have to refer + // back to allocateWrite/markExec/freeWrite (see above.) if (bytes != sizeof(ffi_closure)) { barf("allocateExec: for ffi_closure only"); } |