[project @ 2004-08-21 12:49:14 by panne]
[ghc-hetmet.git] / ghc / rts / Adjustor.c
index 9187d2b..bf9e02b 100644 (file)
@@ -38,20 +38,58 @@ Haskell side.
 */
 #include "PosixSource.h"
 #include "Rts.h"
+#include "RtsExternal.h"
 #include "RtsUtils.h"
-#include "RtsFlags.h"
 #include <stdlib.h>
 
 #if defined(_WIN32)
 #include <windows.h>
 #endif
 
-#if defined(i386_TARGET_ARCH)
-static rtsBool execPage (void* addr, int writable);
+/* Heavily arch-specific, I'm afraid.. */
+
+typedef enum { 
+    pageExecuteRead, 
+    pageExecuteReadWrite 
+} pageMode;
+
+/*
+ * Function: execPage()
+ *
+ * Set the executable bit on page containing addr.
+ *
+ * TODO: Can the code span more than one page? If yes, we need to make two
+ * pages executable!
+ */
+static rtsBool
+execPage (void* addr, pageMode mode)
+{
+#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,
+                         ( mode == pageExecuteReadWrite ? PAGE_EXECUTE_READWRITE : PAGE_EXECUTE_READ),
+                         &dwOldProtect) == 0 ) {
+# if 1
+       DWORD rc = GetLastError();
+       prog_belch("execPage: failed to protect 0x%p; error=%lu; old protection: %lu\n", addr, rc, dwOldProtect);
+# endif
+       return rtsFalse;
+    }
+    return rtsTrue;
+#else
+    (void)addr;   (void)mode;   /* keep gcc -Wall happy */
+    return rtsTrue;
 #endif
+}
 
-/* Heavily arch-specific, I'm afraid.. */
 
+static unsigned char __obscure_ccall_ret_code [] = 
 #if defined(i386_TARGET_ARCH)
 /* Now here's something obscure for you:
 
@@ -72,10 +110,12 @@ static rtsBool execPage (void* addr, int writable);
    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)
@@ -154,10 +194,7 @@ createAdjustor(int cconv, StgStablePtr hptr, StgFunPtr wptr)
        adj_code[0x0c] = (unsigned char)0xff; /* jmp %eax */
        adj_code[0x0d] = (unsigned char)0xe0;
        
-#if 0
-       /* not yet */
-       execPage(adjustor,rtsTrue);
-#endif
+       execPage(adjustor, pageExecuteReadWrite);
     }
 #endif
     break;
@@ -203,10 +240,7 @@ createAdjustor(int cconv, StgStablePtr hptr, StgFunPtr wptr)
        adj_code[0x0f] = (unsigned char)0xff; /* jmp *%eax */
        adj_code[0x10] = (unsigned char)0xe0; 
 
-#if 0
-       /* not yet */
-       execPage(adjustor,rtsTrue);
-#endif
+       execPage(adjustor, pageExecuteReadWrite);
     }
 #elif defined(sparc_TARGET_ARCH)
   /* Magic constant computed by inspecting the code length of the following
@@ -493,7 +527,7 @@ freeHaskellFunctionPtr(void* ptr)
 #if defined(i386_TARGET_ARCH)
  if ( *(unsigned char*)ptr != 0x68 &&
       *(unsigned char*)ptr != 0x58 ) {
-   fprintf(stderr, "freeHaskellFunctionPtr: not for me, guv! %p\n", ptr);
+   prog_belch("freeHaskellFunctionPtr: not for me, guv! %p\n", ptr);
    return;
  }
 
@@ -505,7 +539,7 @@ freeHaskellFunctionPtr(void* ptr)
  }    
 #elif defined(sparc_TARGET_ARCH)
  if ( *(unsigned long*)ptr != 0x9C23A008UL ) {
-   fprintf(stderr, "freeHaskellFunctionPtr: not for me, guv! %p\n", ptr);
+   prog_belch("freeHaskellFunctionPtr: not for me, guv! %p\n", ptr);
    return;
  }
 
@@ -513,7 +547,7 @@ freeHaskellFunctionPtr(void* ptr)
  freeStablePtr(*((StgStablePtr*)((unsigned long*)ptr + 11)));
 #elif defined(alpha_TARGET_ARCH)
  if ( *(StgWord64*)ptr != 0xa77b0018a61b0010L ) {
-   fprintf(stderr, "freeHaskellFunctionPtr: not for me, guv! %p\n", ptr);
+   prog_belch("freeHaskellFunctionPtr: not for me, guv! %p\n", ptr);
    return;
  }
 
@@ -521,7 +555,7 @@ freeHaskellFunctionPtr(void* ptr)
  freeStablePtr(*((StgStablePtr*)((unsigned char*)ptr + 0x10)));
 #elif defined(powerpc_TARGET_ARCH)
  if ( *(StgWord*)ptr != 0x7d0a4378 ) {
-   fprintf(stderr, "freeHaskellFunctionPtr: not for me, guv! %p\n", ptr);
+   prog_belch("freeHaskellFunctionPtr: not for me, guv! %p\n", ptr);
    return;
  }
  freeStablePtr(*((StgStablePtr*)((unsigned char*)ptr + 4*12)));
@@ -530,7 +564,7 @@ freeHaskellFunctionPtr(void* ptr)
  StgWord64 *code = (StgWord64 *)(fdesc+1);
 
  if (fdesc->ip != (StgWord64)code) {
-   fprintf(stderr, "freeHaskellFunctionPtr: not for me, guv! %p\n", ptr);
+   prog_belch("freeHaskellFunctionPtr: not for me, guv! %p\n", ptr);
    return;
  }
  freeStablePtr((StgStablePtr)code[16]);
@@ -544,39 +578,6 @@ freeHaskellFunctionPtr(void* ptr)
  stgFree(ptr);
 }
 
-#if defined(i386_TARGET_ARCH)
-/*
- * Function: execPage()
- *
- * Set the executable bit on page containin
- */
-static
-rtsBool
-execPage (void* addr, int writable)
-{
-#if defined(_WIN32)
-    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
-    return rtsTrue;
-#endif
-}
-#endif
 
 /*
  * Function: initAdjustor()
@@ -586,9 +587,5 @@ execPage (void* addr, int writable)
 rtsBool
 initAdjustor(void)
 {
-#if defined(i386_TARGET_ARCH) && defined(_WIN32)
-    return execPage(__obscure_ccall_ret_code, rtsFalse);
-#else
-    return rtsTrue;
-#endif
+    return execPage(__obscure_ccall_ret_code, pageExecuteRead);
 }