#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
+
#ifdef HAVE_CODEMEM_MMAP
#include <sys/mman.h>
#endif
+
#ifdef HAVE_CODEMEM_VIRTUALALLOC
#include <windows.h>
+ #ifdef ORC_WINAPI_ONLY_APP
+ #define _virtualalloc VirtualAllocFromApp
+ #else
+ #define _virtualalloc VirtualAlloc
+ #endif
#endif
#include <orc/orcinternal.h>
void
orc_code_region_allocate_codemem (OrcCodeRegion *region)
{
- region->write_ptr = VirtualAlloc(NULL, SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
+ /* On UWP, we can't allocate memory as executable from the start. We can only
+ * set that later after compiling and copying the code over. This is a good
+ * idea in general to avoid security issues, so we do it on win32 too. */
+ region->write_ptr = _virtualalloc (NULL, SIZE, MEM_COMMIT, PAGE_READWRITE);
region->exec_ptr = region->write_ptr;
region->size = SIZE;
}
#include <stdlib.h>
#include <stdarg.h>
+#if defined(HAVE_CODEMEM_VIRTUALALLOC)
+#include <windows.h>
+ #ifdef ORC_WINAPI_ONLY_APP
+ #define _virtualprotect VirtualProtectFromApp
+ #else
+ #define _virtualprotect VirtualProtect
+ #endif
+#endif
+
#include <orc/orcprogram.h>
#include <orc/orcdebug.h>
#include <orc/orcinternal.h>
_orc_compiler_flag_emulate = orc_compiler_flag_check ("emulate");
_orc_compiler_flag_debug = orc_compiler_flag_check ("debug");
_orc_compiler_flag_randomize = orc_compiler_flag_check ("randomize");
+
+#if defined(HAVE_CODEMEM_VIRTUALALLOC) && defined(ORC_WINAPI_ONLY_APP)
+ if (!_orc_compiler_flag_backup && !_orc_compiler_flag_emulate) {
+ int can_jit = FALSE;
+ size_t page_size;
+ SYSTEM_INFO info;
+ GetNativeSystemInfo(&info);
+
+ page_size = info.dwPageSize;
+ /* If backup code is not enabled and emulation is not enabled, that means
+ * we will do JIT compilation and call orc_code_region_allocate_codemem().
+ * When targeting Windows Store apps, the codeGeneration capability must
+ * be enabled in the app manifest, or passing PAGE_EXECUTE to
+ * VirtualProtectFromApp will return NULL. In this case, we must force
+ * backup C code, and if that's not available, we must emulate. */
+ void *mem = VirtualAllocFromApp (NULL, page_size, MEM_COMMIT,
+ PAGE_READWRITE);
+ if (mem) {
+ int old_protect;
+ if (VirtualProtectFromApp (mem, page_size, PAGE_EXECUTE, &old_protect) > 0)
+ can_jit = TRUE;
+ VirtualFree (mem, 0, MEM_RELEASE);
+ }
+
+ if (!can_jit) {
+ ORC_WARNING ("Unable to allocate executable pages: using backup code or "
+ "emulation: codeGeneration capability isn't set in the app manifest?");
+ _orc_compiler_flag_backup = TRUE;
+ _orc_compiler_flag_emulate = TRUE;
+ }
+ }
+#endif
}
int
return orc_program_compile_full (program, target, flags);
}
+#if defined(HAVE_CODEMEM_VIRTUALALLOC)
+static const char*
+_get_protect_name (int protect)
+{
+ switch (protect) {
+ /* These are the only two memory protection constants we use */
+ case PAGE_EXECUTE:
+ return "execute";
+ case PAGE_READWRITE:
+ return "readwrite";
+ default:
+ return "unknown";
+ }
+}
+
+static orc_bool
+_set_virtual_protect (void * mem, size_t size, int code_protect)
+{
+ char *msg;
+ DWORD old_protect;
+
+ if (!mem)
+ return FALSE;
+
+ if (_virtualprotect (mem, size, code_protect, &old_protect) > 0)
+ return TRUE;
+
+ FormatMessageA (FORMAT_MESSAGE_ALLOCATE_BUFFER
+ | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, NULL,
+ GetLastError (), 0, (LPTSTR) &msg, 0, NULL);
+ ORC_ERROR ("Couldn't set memory protect on %p from %s to %s: %s", mem,
+ _get_protect_name (old_protect), _get_protect_name (code_protect), msg);
+ LocalFree (msg);
+
+ return FALSE;
+}
+#endif
+
/**
* orc_program_compile_full:
* @program: the OrcProgram to compile
program->orccode->code_size = compiler->codeptr - compiler->code;
orc_code_allocate_codemem (program->orccode, program->orccode->code_size);
+#if defined(HAVE_CODEMEM_VIRTUALALLOC)
+ /* Ensure that code region is writable before memcpy */
+ _set_virtual_protect (program->orccode->code, program->orccode->code_size,
+ PAGE_READWRITE);
+#endif
memcpy (program->orccode->code, compiler->code, program->orccode->code_size);
#ifdef VALGRIND_DISCARD_TRANSLATIONS
compiler->target->flush_cache (program->orccode);
}
+#if defined(HAVE_CODEMEM_VIRTUALALLOC)
+ /* Code region is now ready for execution */
+ if (!_set_virtual_protect (program->orccode->exec, program->orccode->code_size,
+ PAGE_EXECUTE))
+ /* Can't set code as executable, force emulation */
+ program->orccode->exec = (void *)orc_executor_emulate;
+#endif
program->code_exec = program->orccode->exec;
program->asm_code = compiler->asm_code;