Index: /trunk/include/iprt/mem.h
===================================================================
--- /trunk/include/iprt/mem.h	(revision 101141)
+++ /trunk/include/iprt/mem.h	(revision 101142)
@@ -507,6 +507,9 @@
 /** Try prevent the memory from ending up in a dump/core. */
 #define RTMEMPAGEALLOC_F_ADVISE_NO_DUMP RT_BIT_32(2)
+/** Allocate pages that are readable, writeable and executable.
+ * @note This may fail on some platforms for security policy reasons. */
+#define RTMEMPAGEALLOC_F_EXECUTABLE     RT_BIT_32(3)
 /** Valid bit mask. */
-#define RTMEMPAGEALLOC_F_VALID_MASK     UINT32_C(0x00000007)
+#define RTMEMPAGEALLOC_F_VALID_MASK     UINT32_C(0x0000000f)
 /** @} */
 
Index: /trunk/src/VBox/Runtime/r3/posix/rtmempage-exec-mmap-heap-posix.cpp
===================================================================
--- /trunk/src/VBox/Runtime/r3/posix/rtmempage-exec-mmap-heap-posix.cpp	(revision 101141)
+++ /trunk/src/VBox/Runtime/r3/posix/rtmempage-exec-mmap-heap-posix.cpp	(revision 101142)
@@ -550,7 +550,11 @@
 
 /**
- * Allocates one or more pages off the heap.
+ * Frees an allocation.
  *
  * @returns IPRT status code.
+ * @retval  VERR_NOT_FOUND if pv isn't within any of the memory blocks in the
+ *          heap.
+ * @retval  VERR_INVALID_POINTER if the given memory range isn't exactly one
+ *          allocation block.
  * @param   pHeap           The page heap.
  * @param   pv              Pointer to what RTHeapPageAlloc returned.
@@ -652,5 +656,5 @@
         }
         else
-            rc = VERR_INVALID_POINTER;
+            rc = VERR_NOT_FOUND; /* Distinct return code for this so rtMemPagePosixFree and others can try alternative heaps. */
 
         RTCritSectLeave(&pHeap->CritSect);
@@ -737,9 +741,10 @@
  * Free memory allocated by rtMemPagePosixAlloc.
  *
- * @param   pv                  The address of the memory to free.
- * @param   cb                  The size.
- * @param   pHeap               The heap.
- */
-static void rtMemPagePosixFree(void *pv, size_t cb, PRTHEAPPAGE pHeap)
+ * @param   pv      The address of the memory to free.
+ * @param   cb      The size.
+ * @param   pHeap1  The most probable heap.
+ * @param   pHeap2  The less probable heap.
+ */
+static void rtMemPagePosixFree(void *pv, size_t cb, PRTHEAPPAGE pHeap1, PRTHEAPPAGE pHeap2)
 {
     /*
@@ -763,5 +768,7 @@
     else
     {
-        int rc = RTHeapPageFree(pHeap, pv, cb >> PAGE_SHIFT);
+        int rc = RTHeapPageFree(pHeap1, pv, cb >> PAGE_SHIFT);
+        if (rc == VERR_NOT_FOUND)
+            rc = RTHeapPageFree(pHeap2, pv, cb >> PAGE_SHIFT);
         AssertRC(rc);
     }
@@ -787,5 +794,6 @@
 {
     AssertReturn(!(fFlags & ~RTMEMPAGEALLOC_F_VALID_MASK), NULL);
-    return rtMemPagePosixAlloc(cb, pszTag, fFlags, &g_MemPagePosixHeap);
+    return rtMemPagePosixAlloc(cb, pszTag, fFlags,
+                               !(fFlags & RTMEMPAGEALLOC_F_EXECUTABLE) ? &g_MemPagePosixHeap : &g_MemExecPosixHeap);
 }
 
@@ -793,5 +801,5 @@
 RTDECL(void) RTMemPageFree(void *pv, size_t cb) RT_NO_THROW_DEF
 {
-    return rtMemPagePosixFree(pv, cb, &g_MemPagePosixHeap);
-}
-
+    rtMemPagePosixFree(pv, cb, &g_MemPagePosixHeap, &g_MemExecPosixHeap);
+}
+
Index: /trunk/src/VBox/Runtime/r3/posix/rtmempage-exec-mmap-posix.cpp
===================================================================
--- /trunk/src/VBox/Runtime/r3/posix/rtmempage-exec-mmap-posix.cpp	(revision 101141)
+++ /trunk/src/VBox/Runtime/r3/posix/rtmempage-exec-mmap-posix.cpp	(revision 101142)
@@ -173,5 +173,5 @@
 {
     AssertReturn(!(fFlags & ~RTMEMPAGEALLOC_F_VALID_MASK), NULL);
-    return rtMemPagePosixAlloc(cb, pszTag, fFlags, 0);
+    return rtMemPagePosixAlloc(cb, pszTag, fFlags, !(fFlags & RTMEMPAGEALLOC_F_EXECUTABLE) ? 0 : PROT_EXEC);
 }
 
Index: /trunk/src/VBox/Runtime/r3/win/alloc-win.cpp
===================================================================
--- /trunk/src/VBox/Runtime/r3/win/alloc-win.cpp	(revision 101141)
+++ /trunk/src/VBox/Runtime/r3/win/alloc-win.cpp	(revision 101142)
@@ -56,4 +56,8 @@
 
 
+/** @todo merge the page alloc code with the heap-based mmap stuff as
+ *        _aligned_malloc just isn't well suited for exec. */
+
+
 RTDECL(void *) RTMemPageAllocTag(size_t cb, const char *pszTag) RT_NO_THROW_DEF
 {
@@ -77,9 +81,19 @@
 
 #ifdef USE_VIRTUAL_ALLOC
-    void *pv = VirtualAlloc(NULL, cbAligned, MEM_COMMIT, PAGE_READWRITE);
+    void *pv = VirtualAlloc(NULL, cbAligned, MEM_COMMIT,
+                            !(fFlags & RTMEMPAGEALLOC_F_EXECUTABLE) ? PAGE_READWRITE : PAGE_EXECUTE_READWRITE);
 #else
     void *pv = _aligned_malloc(cbAligned, PAGE_SIZE);
 #endif
     AssertMsgReturn(pv, ("cb=%d lasterr=%d\n", cb, GetLastError()), NULL);
+
+#ifdef USE_VIRTUAL_ALLOC
+    if (fFlags & RTMEMPAGEALLOC_F_EXECUTABLE)
+    {
+        DWORD      fIgn = 0;
+        BOOL const fRc  = VirtualProtect(pv, cbAligned, PAGE_EXECUTE_READWRITE, &fIgn);
+        AssertMsgReturnStmt(fRc, ("%p LB %#zx: %#u\n", pv, cbAligned, GetLastError()), _aligned_free(pv), NULL);
+    }
+#endif
 
     if (fFlags & RTMEMPAGEALLOC_F_ADVISE_LOCKED)
@@ -127,4 +141,14 @@
             AssertMsgFailed(("pv=%p lasterr=%d\n", pv, GetLastError()));
 #else
+        /** @todo The exec version of this doesn't really work well... */
+        MEMORY_BASIC_INFORMATION MemInfo = { NULL }
+        SIZE_T cbRet = VirtualQuery(pv, &MemInfo, cb);
+        Assert(cbRet > 0)
+        if (cbRet >= 0 && MemInfo.Protect == PAGE_EXECUTE_READWRITE)
+        {
+            DWORD      fIgn = 0;
+            BOOL const fRc  = VirtualProtect(pv, cb, PAGE_READWRITE, &fIgn);
+            Assert(fRc); RT_NOREF(fRc);
+        }
         _aligned_free(pv);
 #endif
