diff --git a/src/configure b/src/configure index 1fa9ac9ae4..bb6e5d7f93 100755 --- a/src/configure +++ b/src/configure @@ -3938,6 +3938,13 @@ if test "${enable_shared}" = "yes" ; then LIBRACKET_DEP="${LIBRACKET_DEP} libmzgc.la" fi +if test "${enable_foreign}" = "yes" ; then + check_for_mprotect=yes +fi +if test "${enable_jit}" = "yes" ; then + check_for_mprotect=yes +fi + ############## platform tests ################ # for flags we don't want to use in config tests: @@ -4047,6 +4054,7 @@ case "$host_os" in EXE_SUFFIX=".exe" COLLECTS_PATH="collects" skip_iconv_check=yes + check_for_mprotect=no cat >>confdefs.h <<\_ACEOF #define HAVE_STDINT_H 1 @@ -5531,6 +5539,72 @@ echo "${ECHO_T}$have_libffi" >&6; } fi fi +if test "${check_for_mprotect}" = "yes" ; then + msg="for mmap and mprotect" + { echo "$as_me:$LINENO: checking $msg" >&5 +echo $ECHO_N "checking $msg... $ECHO_C" >&6; } + if test "$cross_compiling" = yes; then + use_mprotect=no +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + #include + #include + int main() { + void *p; + p = mmap(0, 2 << 16, PROT_READ | PROT_WRITE, MAP_PRIVATE, open("/dev/zero", O_RDWR), 0); + mprotect(p, 2 << 16, PROT_READ | PROT_WRITE | PROT_EXEC); + return 0; + } +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + use_mprotect=yes +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +use_mprotect=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + + { echo "$as_me:$LINENO: result: $use_mprotect" >&5 +echo "${ECHO_T}$use_mprotect" >&6; } + if test "${use_mprotect}" = "yes" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_MMAP_MPROTECT 1 +_ACEOF + + fi +fi + if test "${enable_backtrace}" = "yes" ; then GC2OPTIONS="$GC2OPTIONS -DMZ_GC_BACKTRACE" fi diff --git a/src/racket/configure.ac b/src/racket/configure.ac index f6568e5446..10c803f530 100644 --- a/src/racket/configure.ac +++ b/src/racket/configure.ac @@ -469,6 +469,13 @@ if test "${enable_shared}" = "yes" ; then LIBRACKET_DEP="${LIBRACKET_DEP} libmzgc.la" fi +if test "${enable_foreign}" = "yes" ; then + check_for_mprotect=yes +fi +if test "${enable_jit}" = "yes" ; then + check_for_mprotect=yes +fi + ############## platform tests ################ # for flags we don't want to use in config tests: @@ -578,6 +585,7 @@ case "$host_os" in EXE_SUFFIX=".exe" COLLECTS_PATH="collects" skip_iconv_check=yes + check_for_mprotect=no AC_DEFINE(HAVE_STDINT_H,1,[Have stdint.h]) if `which ${host}-windres > /dev/null` ; then WINDRES="${host}-windres" @@ -976,6 +984,24 @@ if test "${enable_libffi}" = "yes" ; then fi fi +if test "${check_for_mprotect}" = "yes" ; then + [ msg="for mmap and mprotect" ] + AC_MSG_CHECKING($msg) + AC_TRY_RUN( + [ #include ] + [ #include ] + int main() { + void *p; + p = mmap(0, 2 << 16, PROT_READ | PROT_WRITE, MAP_PRIVATE, open("/dev/zero", O_RDWR), 0); + mprotect(p, 2 << 16, PROT_READ | PROT_WRITE | PROT_EXEC); + return 0; + }, use_mprotect=yes, use_mprotect=no, use_mprotect=no) + AC_MSG_RESULT($use_mprotect) + if test "${use_mprotect}" = "yes" ; then + AC_DEFINE(HAVE_MMAP_MPROTECT,1,[Have mmap and mprotect]) + fi +fi + if test "${enable_backtrace}" = "yes" ; then GC2OPTIONS="$GC2OPTIONS -DMZ_GC_BACKTRACE" fi diff --git a/src/racket/mzconfig.h.in b/src/racket/mzconfig.h.in index 68993db32a..37ffa88cf0 100644 --- a/src/racket/mzconfig.h.in +++ b/src/racket/mzconfig.h.in @@ -61,6 +61,9 @@ typedef unsigned long uintptr_t; #undef HAVE_EPOLL_SYSCALL #undef HAVE_KQUEUE_SYSCALL +/* When mmap() and mprotect() are available: */ +#undef HAVE_MMAP_MPROTECT + /* Enable futures: */ #undef MZ_USE_FUTURES diff --git a/src/racket/src/salloc.c b/src/racket/src/salloc.c index 6f22193cfe..d896caab21 100644 --- a/src/racket/src/salloc.c +++ b/src/racket/src/salloc.c @@ -39,7 +39,11 @@ # define MALLOC malloc #endif -#ifdef MZ_JIT_USE_MPROTECT +#if defined(MZ_JIT_USE_MPROTECT) || defined(HAVE_MMAP_MPROTECT) +# define MZ_CODE_ALLOC_USE_MPROTECT +#endif + +#ifdef MZ_CODE_ALLOC_USE_MPROTECT # include # include # ifndef MAP_ANON @@ -851,14 +855,14 @@ THREAD_LOCAL_DECL(static void *code_allocation_page_list); THREAD_LOCAL_DECL(intptr_t scheme_code_page_total); -#if defined(MZ_JIT_USE_MPROTECT) && !defined(MAP_ANON) +#if defined(MZ_CODE_ALLOC_USE_MPROTECT) && !defined(MAP_ANON) static int fd, fd_created; #endif #define LOG_CODE_MALLOC(lvl, s) /* if (lvl > 1) s */ #define CODE_PAGE_OF(p) ((void *)(((uintptr_t)p) & ~(page_size - 1))) -#if defined(MZ_JIT_USE_MPROTECT) || defined(MZ_JIT_USE_WINDOWS_VIRTUAL_ALLOC) +#if defined(MZ_CODE_ALLOC_USE_MPROTECT) || defined(MZ_JIT_USE_WINDOWS_VIRTUAL_ALLOC) struct free_list_entry { intptr_t size; /* size of elements in this bucket */ @@ -1030,7 +1034,7 @@ static intptr_t free_list_find_bucket(intptr_t size) void *scheme_malloc_code(intptr_t size) { -#if defined(MZ_JIT_USE_MPROTECT) || defined(MZ_JIT_USE_WINDOWS_VIRTUAL_ALLOC) +#if defined(MZ_CODE_ALLOC_USE_MPROTECT) || defined(MZ_JIT_USE_WINDOWS_VIRTUAL_ALLOC) intptr_t size2, bucket, sz, page_size; void *p, *pg, *prev; @@ -1109,7 +1113,7 @@ void *scheme_malloc_permanent_code(intptr_t size) /* allocate code that will never be freed and that can be used in multiple places */ { -#if defined(MZ_USE_PLACES) && (defined(MZ_JIT_USE_MPROTECT) || defined(MZ_JIT_USE_WINDOWS_VIRTUAL_ALLOC)) +#if defined(MZ_USE_PLACES) && (defined(MZ_CODE_ALLOC_USE_MPROTECT) || defined(MZ_JIT_USE_WINDOWS_VIRTUAL_ALLOC)) void *p; intptr_t page_size; @@ -1148,7 +1152,7 @@ void *scheme_malloc_permanent_code(intptr_t size) void scheme_free_code(void *p) { -#if defined(MZ_JIT_USE_MPROTECT) || defined(MZ_JIT_USE_WINDOWS_VIRTUAL_ALLOC) +#if defined(MZ_CODE_ALLOC_USE_MPROTECT) || defined(MZ_JIT_USE_WINDOWS_VIRTUAL_ALLOC) intptr_t size, size2, bucket, page_size; int per_page, n; void *prev; @@ -1234,7 +1238,7 @@ void scheme_free_code(void *p) void scheme_free_all_code(void) { -#if defined(MZ_JIT_USE_MPROTECT) || defined(MZ_JIT_USE_WINDOWS_VIRTUAL_ALLOC) +#if defined(MZ_CODE_ALLOC_USE_MPROTECT) || defined(MZ_JIT_USE_WINDOWS_VIRTUAL_ALLOC) void *p, *next; intptr_t page_size; @@ -1260,7 +1264,7 @@ void scheme_free_all_code(void) currently takes advantage of that combination, so we support it with scheme_malloc_gcable_code() --- but only in CGC mode. */ -#if defined(MZ_JIT_USE_MPROTECT) || defined(MZ_JIT_USE_WINDOWS_VIRTUAL_ALLOC) +#if defined(MZ_CODE_ALLOC_USE_MPROTECT) || defined(MZ_JIT_USE_WINDOWS_VIRTUAL_ALLOC) static uintptr_t jit_prev_page = 0, jit_prev_length = 0; #endif @@ -1269,7 +1273,7 @@ void *scheme_malloc_gcable_code(intptr_t size) void *p; p = scheme_malloc(size); -#if defined(MZ_JIT_USE_MPROTECT) || defined(MZ_JIT_USE_WINDOWS_VIRTUAL_ALLOC) +#if defined(MZ_CODE_ALLOC_USE_MPROTECT) || defined(MZ_JIT_USE_WINDOWS_VIRTUAL_ALLOC) { /* [This chunk of code moved from our copy of GNU lightning to here.] */ uintptr_t page, length, page_size; @@ -1324,7 +1328,7 @@ void *scheme_malloc_gcable_code(intptr_t size) void scheme_notify_code_gc() { -#if defined(MZ_JIT_USE_MPROTECT) || defined(MZ_JIT_USE_WINDOWS_VIRTUAL_ALLOC) +#if defined(MZ_CODE_ALLOC_USE_MPROTECT) || defined(MZ_JIT_USE_WINDOWS_VIRTUAL_ALLOC) jit_prev_page = 0; jit_prev_length = 0; #endif