--- a/Modules/_ctypes/libffi/configure.ac +++ b/Modules/_ctypes/libffi/configure.ac @@ -379,6 +379,12 @@ AC_DEFINE(USING_PURIFY, 1, [Define this if you are using Purify and want to suppress spurious messages.]) fi) +AC_ARG_ENABLE(emutramp, +[ --enable-emutramp enable emulated trampolines], + if test "$enable_emutramp" = "yes"; then + AC_DEFINE(FFI_EMUTRAMP, 1, [Define this if you want to enable emulated trampolines]) + fi) + if test -n "$with_cross_host" && test x"$with_cross_host" != x"no"; then toolexecdir='$(exec_prefix)/$(target_alias)' --- a/Modules/_ctypes/libffi/src/closures.c +++ b/Modules/_ctypes/libffi/src/closures.c @@ -61,6 +61,10 @@ # endif #endif +#if FFI_EMUTRAMP +# define FFI_MMAP_EXEC_EMUTRAMP 1 +#endif + #if FFI_CLOSURES # if FFI_MMAP_EXEC_WRIT @@ -167,6 +171,29 @@ #endif /* !FFI_MMAP_EXEC_SELINUX */ +#ifdef FFI_MMAP_EXEC_EMUTRAMP +#include + +static int emutramp_enabled = -1; + +static int +emutramp_enabled_check (void) +{ + if (getenv ("FFI_DISABLE_EMUTRAMP") == NULL) + return 1; + else + return 0; +} + +#define is_emutramp_enabled() (emutramp_enabled >= 0 ? emutramp_enabled \ + : (emutramp_enabled = emutramp_enabled_check ())) + +#else + +#define is_emutramp_enabled() 0 + +#endif /* FFI_MMAP_EXEC_EMUTRAMP */ + #elif defined (__CYGWIN__) #include @@ -453,6 +480,12 @@ printf ("mapping in %zi\n", length); #endif + if (execfd == -1 && is_emutramp_enabled ()) + { + ptr = mmap (start, length, prot & ~PROT_EXEC, flags, fd, offset); + return ptr; + } + if (execfd == -1 && !is_selinux_enabled ()) { ptr = mmap (start, length, prot | PROT_EXEC, flags, fd, offset); --- a/Modules/_ctypes/malloc_closure.c +++ b/Modules/_ctypes/malloc_closure.c @@ -8,6 +8,9 @@ # if !defined(MAP_ANONYMOUS) && defined(MAP_ANON) # define MAP_ANONYMOUS MAP_ANON # endif +# if CTYPES_EMUTRAMP +# include +# endif #endif #include "ctypes.h" @@ -34,6 +37,20 @@ { ITEM *item; int count, i; +#ifndef MS_WIN32 + int prot = PROT_READ | PROT_WRITE | PROT_EXEC; +#if CTYPES_EMUTRAMP + static int emutramp_enabled = -1; + if (emutramp_enabled = -1) { + if (getenv("FFI_DISABLE_EMUTRAMP") == NULL) { + emutramp_enabled = 1; + prot = PROT_READ | PROT_WRITE; + } else { + emutramp_enabled = 0; + } + } +# endif +#endif /* determine the pagesize */ #ifdef MS_WIN32 @@ -66,7 +83,7 @@ #else item = (ITEM *)mmap(NULL, count * sizeof(ITEM), - PROT_READ | PROT_WRITE | PROT_EXEC, + prot, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); --- a/configure.in +++ b/configure.in @@ -4267,6 +4267,22 @@ ], [AC_MSG_RESULT(no value specified)]) +# Check for --enable-emutramp +AC_MSG_CHECKING(for --enable-emutramp) +AC_ARG_ENABLE(emutramp, + AS_HELP_STRING( + [--enable-emutramp], + [allocate non-executable memory for trampolines in _ctypes module] + ), +[ + AC_DEFINE( + CTYPES_EMUTRAMP, 1, + [Define if you want to allocate non-executable memory for trampolines in _ctypes module] + ) + AC_MSG_RESULT(yes) +], +[AC_MSG_RESULT(no)]) + case $ac_sys_system in AIX*) AC_DEFINE(HAVE_BROKEN_PIPE_BUF, 1, [Define if the system reports an invalid PIPE_BUF value.]) ;; --- a/setup.py +++ b/setup.py @@ -1683,6 +1683,8 @@ from distutils.dir_util import mkpath mkpath(ffi_builddir) config_args = [] + if sysconfig.get_config_vars("CTYPES_EMUTRAMP"): + config_args.append("--enable-emutramp") # Pass empty CFLAGS because we'll just append the resulting # CFLAGS to Python's; -g or -O2 is to be avoided.