diff options
author | Simon Marlow <simonmar@microsoft.com> | 2006-05-30 10:02:11 +0000 |
---|---|---|
committer | Simon Marlow <simonmar@microsoft.com> | 2006-05-30 10:02:11 +0000 |
commit | e3c55aebd4f9ce7a5b4390d4726612865fd207f2 (patch) | |
tree | 87a1e86bc77f2c1d8d4dba8757e14fce324fe736 /rts/RtsUtils.c | |
parent | 6b36d8ad3bfd1890583f3bcab96559f05bff332b (diff) | |
download | haskell-e3c55aebd4f9ce7a5b4390d4726612865fd207f2.tar.gz |
replace stgMallocBytesRWX() with our own allocator
See bug #738
Allocating executable memory is getting more difficult these days. In
particular, the default SELinux policy on Fedora Core 5 disallows
making the heap (i.e. malloc()'d memory) executable, although it does
apparently allow mmap()'ing anonymous executable memory by default.
Previously, stgMallocBytesRWX() used malloc() underneath, and then
tried to make the page holding the memory executable. This was rather
hacky and fails with Fedora Core 5.
This patch adds a mini-allocator for executable memory, based on the
block allocator. We grab page-sized blocks and make them executable,
then allocate small objects from the page. There's a simple free
function, that will free whole pages back to the system when they are
empty.
Diffstat (limited to 'rts/RtsUtils.c')
-rw-r--r-- | rts/RtsUtils.c | 52 |
1 files changed, 0 insertions, 52 deletions
diff --git a/rts/RtsUtils.c b/rts/RtsUtils.c index af68905707..bf02c328fb 100644 --- a/rts/RtsUtils.c +++ b/rts/RtsUtils.c @@ -39,19 +39,6 @@ #include <pthread.h> #endif -#if defined(openbsd_HOST_OS) || defined(linux_HOST_OS) || defined(darwin_HOST_OS) -#include <unistd.h> -#include <sys/types.h> -#include <sys/mman.h> - -/* no C99 header stdint.h on OpenBSD? */ -#if defined(openbsd_HOST_OS) -typedef unsigned long my_uintptr_t; -#else -#include <stdint.h> -typedef uintptr_t my_uintptr_t; -#endif -#endif #if defined(_WIN32) #include <windows.h> @@ -325,42 +312,3 @@ int genericRaise(int sig) { return raise(sig); #endif } - -/* ----------------------------------------------------------------------------- - Allocating executable memory - -------------------------------------------------------------------------- */ - -/* Heavily arch-specific, I'm afraid.. */ - -/* - * Allocate len bytes which are readable, writable, and executable. - * - * ToDo: If this turns out to be a performance bottleneck, one could - * e.g. cache the last VirtualProtect/mprotect-ed region and do - * nothing in case of a cache hit. - */ -void* -stgMallocBytesRWX(int len) -{ - void *addr = stgMallocBytes(len, "mallocBytesRWX"); -#if defined(i386_HOST_ARCH) && defined(_WIN32) - /* This could be necessary for processors which distinguish between READ and - EXECUTE memory accesses, e.g. Itaniums. */ - DWORD dwOldProtect = 0; - if (VirtualProtect (addr, len, PAGE_EXECUTE_READWRITE, &dwOldProtect) == 0) { - barf("mallocBytesRWX: failed to protect 0x%p; error=%lu; old protection: %lu\n", - addr, (unsigned long)GetLastError(), (unsigned long)dwOldProtect); - } -#elif defined(openbsd_HOST_OS) || defined(linux_HOST_OS) || defined(darwin_HOST_OS) - /* malloced memory isn't executable by default on OpenBSD */ - my_uintptr_t pageSize = sysconf(_SC_PAGESIZE); - my_uintptr_t mask = ~(pageSize - 1); - my_uintptr_t startOfFirstPage = ((my_uintptr_t)addr ) & mask; - my_uintptr_t startOfLastPage = ((my_uintptr_t)addr + len - 1) & mask; - my_uintptr_t size = startOfLastPage - startOfFirstPage + pageSize; - if (mprotect((void*)startOfFirstPage, (size_t)size, PROT_EXEC | PROT_READ | PROT_WRITE) != 0) { - barf("mallocBytesRWX: failed to protect 0x%p\n", addr); - } -#endif - return addr; -} |