[project @ 2004-08-15 20:28:02 by panne]
[ghc-hetmet.git] / ghc / rts / Adjustor.c
index e9fc769..b488d43 100644 (file)
@@ -40,11 +40,51 @@ Haskell side.
 #include "Rts.h"
 #include "RtsUtils.h"
 #include "RtsFlags.h"
-
 #include <stdlib.h>
 
+#if defined(_WIN32)
+#include <windows.h>
+#endif
+
 /* Heavily arch-specific, I'm afraid.. */
 
+/*
+ * Function: execPage()
+ *
+ * Set the executable bit on page containing addr. CURRENTLY DISABLED.
+ *
+ * TODO: Can the code span more than one page? If yes, we need to make two
+ * pages executable!
+ */
+static rtsBool
+execPage (void* addr, int writable)
+{
+#if defined(i386_TARGET_ARCH) && defined(_WIN32) && 0
+    SYSTEM_INFO sInfo;
+    DWORD dwOldProtect = 0;
+
+    /* doesn't return a result, so presumably it can't fail... */
+    GetSystemInfo(&sInfo);
+    
+    if ( VirtualProtect ( (void*)((unsigned long)addr & (sInfo.dwPageSize - 1)),
+                         sInfo.dwPageSize,
+                         ( writable ? PAGE_EXECUTE_READWRITE : PAGE_EXECUTE_READ),
+                         &dwOldProtect) == 0 ) {
+# if 1
+       DWORD rc = GetLastError();
+       fprintf(stderr, "execPage: failed to protect 0x%p; error=%lu; old protection: %lu\n", addr, rc, dwOldProtect);
+# endif
+       return rtsFalse;
+    }
+    return rtsTrue;
+#else
+    (void)addr;   (void)writable;   /* keep gcc -Wall happy */
+    return rtsTrue;
+#endif
+}
+
+
+static unsigned char __obscure_ccall_ret_code [] = 
 #if defined(i386_TARGET_ARCH)
 /* Now here's something obscure for you:
 
@@ -65,10 +105,12 @@ Haskell side.
    For this to work we make the assumption that bytes in .data
    are considered executable.
 */
-static unsigned char __obscure_ccall_ret_code [] = 
   { 0x83, 0xc4, 0x04 /* addl $0x4, %esp */
   , 0xc3             /* ret */
   };
+#else
+/* No such mind-twisters on non-Intel platforms */
+  { };
 #endif
 
 #if defined(alpha_TARGET_ARCH)
@@ -146,6 +188,8 @@ createAdjustor(int cconv, StgStablePtr hptr, StgFunPtr wptr)
 
        adj_code[0x0c] = (unsigned char)0xff; /* jmp %eax */
        adj_code[0x0d] = (unsigned char)0xe0;
+       
+       execPage(adjustor,rtsTrue);
     }
 #endif
     break;
@@ -190,6 +234,8 @@ createAdjustor(int cconv, StgStablePtr hptr, StgFunPtr wptr)
 
        adj_code[0x0f] = (unsigned char)0xff; /* jmp *%eax */
        adj_code[0x10] = (unsigned char)0xe0; 
+
+       execPage(adjustor,rtsTrue);
     }
 #elif defined(sparc_TARGET_ARCH)
   /* Magic constant computed by inspecting the code length of the following
@@ -527,3 +573,16 @@ freeHaskellFunctionPtr(void* ptr)
  stgFree(ptr);
 }
 
+
+/*
+ * Function: initAdjustor()
+ *
+ * Perform initialisation of adjustor thunk layer (if needed.)
+ *
+ * TODO: Call this at RTS initialisation time.
+ */
+rtsBool
+initAdjustor(void)
+{
+    return execPage(__obscure_ccall_ret_code, rtsFalse);
+}