X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Frts%2FRtsUtils.c;h=b54d3da6d2883fc620bc168f77325c8de6edc9bf;hb=8ec4842b5dd3a15d0afda537b9461402d6e7f80d;hp=646fba93aff524e0ba9179a1511373f2facd6e20;hpb=ad455445e0c798e348a96a7a835c8d0ccf939e89;p=ghc-hetmet.git diff --git a/ghc/rts/RtsUtils.c b/ghc/rts/RtsUtils.c index 646fba9..b54d3da 100644 --- a/ghc/rts/RtsUtils.c +++ b/ghc/rts/RtsUtils.c @@ -40,6 +40,24 @@ #include #endif +#if defined(openbsd_HOST_OS) || defined(linux_HOST_OS) +#include +#include +#include + +/* no C99 header stdint.h on OpenBSD? */ +#if defined(openbsd_HOST_OS) +typedef unsigned long my_uintptr_t; +#else +#include +typedef uintptr_t my_uintptr_t; +#endif +#endif + +#if defined(_WIN32) +#include +#endif + /* ----------------------------------------------------------------------------- Result-checking malloc wrappers. -------------------------------------------------------------------------- */ @@ -73,11 +91,14 @@ stgReallocBytes (void *p, int n, char *msg) void * stgCallocBytes (int n, int m, char *msg) { - int i; - int sz = n * m; - char* p = stgMallocBytes(sz, msg); - for (i = 0; i < sz; i++) p[i] = 0; - return p; + char *space; + + if ((space = (char *) calloc((size_t) n, (size_t) m)) == NULL) { + /* don't fflush(stdout); WORKAROUND bug in Linux glibc */ + MallocFailHook((W_) n*m, msg); /*msg*/ + stg_exit(EXIT_INTERNAL_ERROR); + } + return space; } /* To simplify changing the underlying allocator used @@ -301,3 +322,42 @@ 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) + /* 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; +}