X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Frts%2FAdjustor.c;h=b488d43c836e694a16e73f7b9d92ca827f106299;hb=776c0fefa3b3ae9074d5f51ef37c381150726076;hp=ed3cb507dbea8d27395b4461b791ee0b34b6272d;hpb=3b6a5af52cff72d77600b848d6d851f71b162bc2;p=ghc-hetmet.git diff --git a/ghc/rts/Adjustor.c b/ghc/rts/Adjustor.c index ed3cb50..b488d43 100644 --- a/ghc/rts/Adjustor.c +++ b/ghc/rts/Adjustor.c @@ -40,11 +40,51 @@ Haskell side. #include "Rts.h" #include "RtsUtils.h" #include "RtsFlags.h" - #include +#if defined(_WIN32) +#include +#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,15 +105,21 @@ 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) /* To get the definition of PAL_imb: */ -#include +# if defined(linux_TARGET_OS) +# include +# else +# include +# endif #endif #if defined(ia64_TARGET_ARCH) @@ -142,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; @@ -186,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 @@ -366,7 +416,7 @@ TODO: Depending on how much allocation overhead stgMallocBytes uses for while(n--) { __asm__ volatile ("dcbf 0,%0\n\tsync\n\ticbi 0,%0" - : : "g" (p)); + : : "r" (p)); p++; } __asm__ volatile ("sync\n\tisync"); @@ -520,6 +570,19 @@ freeHaskellFunctionPtr(void* ptr) #endif *((unsigned char*)ptr) = '\0'; - free(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); +}