Add feature to change temporary to write access for relocation code.



git-svn-id: svn+ssh://svn.code.sf.net/p/mingw-w64/code/trunk@567 4407c894-4637-0410-b4f5-ada5f102cad1
diff --git a/mingw-w64-crt/crt/pseudo-reloc.c b/mingw-w64-crt/crt/pseudo-reloc.c
index 9592f5f..fd2dfd7 100644
--- a/mingw-w64-crt/crt/pseudo-reloc.c
+++ b/mingw-w64-crt/crt/pseudo-reloc.c
@@ -1,5 +1,7 @@
 #include <windows.h>
 #include <stdio.h>
+#include <stdlib.h>
+#include <memory.h>
 
 extern char __RUNTIME_PSEUDO_RELOC_LIST__;
 extern char __RUNTIME_PSEUDO_RELOC_LIST_END__;
@@ -22,6 +24,24 @@
 	DWORD version;
 } runtime_pseudo_reloc_v2;
 
+static void
+__write_memory (void *addr,const void *src,size_t len)
+{
+  MEMORY_BASIC_INFORMATION b;
+  DWORD oldprot;
+  if (!len)
+    return;
+  if (!VirtualQuery (addr, &b, sizeof(b)))
+    abort ();
+  // Protect
+  if (b.Protect != PAGE_EXECUTE_READWRITE && b.Protect != PAGE_READWRITE)
+    VirtualProtect (b.BaseAddress, b.RegionSize, PAGE_EXECUTE_READWRITE,
+		  &oldprot);
+  memcpy (addr, src, len);
+  if (b.Protect != PAGE_EXECUTE_READWRITE && b.Protect != PAGE_READWRITE)
+    VirtualProtect (b.BaseAddress, b.RegionSize, oldprot, &oldprot);
+}
+
 #define RP_VERSION_V1 0
 #define RP_VERSION_V2 1
 
@@ -45,8 +65,10 @@
       runtime_pseudo_reloc_item_v1 *o;
       for (o = (runtime_pseudo_reloc_item_v1 *) v2_hdr; o < (runtime_pseudo_reloc_item_v1 *)end; o++)
         {
+          DWORD newval;
 	  reloc_target = (ptrdiff_t) base + o->target;
-	  *((DWORD*) reloc_target) += o->addend;
+	  newval = (*((DWORD*) reloc_target)) + o->addend;
+	  __write_memory ((void *) reloc_target, &newval, sizeof(DWORD));
         }
       return;
     }
@@ -100,17 +122,17 @@
       switch ((r->flags & 0xff))
         {
          case 8:
-	   *((unsigned char*)reloc_target)=(unsigned char) reldata;
+           __write_memory ((void *) reloc_target, &reldata, 1);
 	   break;
 	 case 16:
-	   *((unsigned short*)reloc_target)=(unsigned short) reldata;
+           __write_memory ((void *) reloc_target, &reldata, 2);
 	   break;
 	 case 32:
-	   *((unsigned int*)reloc_target)=(unsigned int) reldata;
+           __write_memory ((void *) reloc_target, &reldata, 4);
 	   break;
 #ifdef _WIN64
 	 case 64:
-	   *((unsigned long long*)reloc_target)=(unsigned long long) reldata;
+           __write_memory ((void *) reloc_target, &reldata, 8);
 	   break;
 #endif
         }