]> sourceware.org Git - newlib-cygwin.git/commitdiff
* dll_init.cc (dll_list::alloc): Initialize dll::image_size.
authorChristopher Faylor <me@cgf.cx>
Sat, 28 May 2011 20:55:34 +0000 (20:55 +0000)
committerChristopher Faylor <me@cgf.cx>
Sat, 28 May 2011 20:55:34 +0000 (20:55 +0000)
(reserve_at): Don't reserve space needed by the target dll if the latter
overlaps the free region to be blocked.
(dll_list::load_after_fork): Use new version of reserve_at.
* dll_init.h (dll::image_size): New member.
(pefile): New struct.

winsup/cygwin/ChangeLog
winsup/cygwin/dll_init.cc
winsup/cygwin/dll_init.h

index 1670f7f8f412beff1e2edc513eff1efdf4e7ca1c..3edbad158803afb996d3c59afeac3f860ed9737a 100644 (file)
@@ -1,3 +1,12 @@
+2011-05-28  Ryan Johnson  <ryan.johnson@cs.utoronto.ca>
+
+       * dll_init.cc (dll_list::alloc): Initialize dll::image_size.
+       (reserve_at): Don't reserve space needed by the target dll if the
+       latter overlaps the free region to be blocked.
+       (dll_list::load_after_fork): Use new version of reserve_at.
+       * dll_init.h (dll::image_size): New member.
+       (pefile): New struct.
+
 2011-05-28  Christopher Faylor  <me.cygwin2011@cgf.cx>
            Ryan Johnson  <ryan.johnson@cs.utoronto.ca>
 
index 68a974b7bdc58aed02d1b702cd43eaf0f6b6135e..060ff497e3b8b5fbd463d605f1a999f734110483 100644 (file)
@@ -161,6 +161,7 @@ dll_list::alloc (HINSTANCE h, per_process *p, dll_type type)
       d->handle = h;
       d->has_dtors = true;
       d->p = p;
+      d->image_size = ((pefile*)h)->optional_hdr ()->SizeOfImage;
       d->type = type;
       if (end == NULL)
        end = &start;   /* Point to "end" of dll chain. */
@@ -292,21 +293,33 @@ release_upto (const PWCHAR name, DWORD here)
       }
 }
 
-/* Mark one page at "here" as reserved.  This may force
-   Windows NT to load a DLL elsewhere. */
+/* Reserve the chunk of free address space starting _here_ and (usually)
+   covering at least _dll_size_ bytes. However, we must take care not
+   to clobber the dll's target address range because it often overlaps.
+ */
 static DWORD
-reserve_at (const PWCHAR name, DWORD here)
+reserve_at (const PWCHAR name, DWORD here, DWORD dll_base, DWORD dll_size)
 {
   DWORD size;
   MEMORY_BASIC_INFORMATION mb;
 
   if (!VirtualQuery ((void *) here, &mb, sizeof (mb)))
-    size = 64 * 1024;
-
+    api_fatal ("couldn't examine memory at %08lx while mapping %W, %E",
+              here, name);
   if (mb.State != MEM_FREE)
     return 0;
 
   size = mb.RegionSize;
+  
+  // don't clobber the space where we want the dll to land
+  DWORD end = here + size;
+  DWORD dll_end = dll_base + dll_size;
+  if (dll_base < here && dll_end > here)
+      here = dll_end; // the dll straddles our left edge
+  else if (dll_base >= here && dll_base < end)
+      end = dll_base; // the dll overlaps partly or fully to our right
+  
+  size = end - here;
   if (!VirtualAlloc ((void *) here, size, MEM_RESERVE, PAGE_NOACCESS))
     api_fatal ("couldn't allocate memory %p(%d) for '%W' alignment, %E\n",
                here, size, name);
@@ -384,7 +397,8 @@ dll_list::load_after_fork (HANDLE parent)
              can in the child, due to differences in the load ordering.
              Block memory at it's preferred address and try again. */
           if ((DWORD) h > (DWORD) d->handle)
-            preferred_block = reserve_at (d->name, (DWORD) h);
+            preferred_block = reserve_at (d->name, (DWORD) h,
+                                         (DWORD) d->handle, d->image_size);
 
        }
 }
index d14cc6cb9e95783f38fbc758062918326db11d1b..dc5c5703883db376e97d56e72d6535f203ceb543 100644 (file)
@@ -52,6 +52,7 @@ struct dll
   int count;
   bool has_dtors;
   dll_type type;
+  DWORD image_size;
   WCHAR name[1];
   void detach ();
   int init ();
@@ -109,6 +110,24 @@ public:
   dll_list () { protect.init ("dll_list"); }
 };
 
+/* References:
+   http://msdn.microsoft.com/en-us/windows/hardware/gg463125
+   http://msdn.microsoft.com/en-us/library/ms809762.aspx
+*/
+struct pefile
+{
+  IMAGE_DOS_HEADER dos_hdr;
+
+  char* rva (long offset) { return (char*) this + offset; }
+  PIMAGE_NT_HEADERS32 pe_hdr () { return (PIMAGE_NT_HEADERS32) rva (dos_hdr.e_lfanew); }
+  PIMAGE_OPTIONAL_HEADER32 optional_hdr () { return &pe_hdr ()->OptionalHeader; }
+  PIMAGE_DATA_DIRECTORY idata_dir (DWORD which)
+  {
+    PIMAGE_OPTIONAL_HEADER32 oh = optional_hdr ();
+    return (which < oh->NumberOfRvaAndSizes)? oh->DataDirectory + which : 0;
+  }
+};
+
 extern dll_list dlls;
 void dll_global_dtors ();
 
This page took 0.036701 seconds and 5 git commands to generate.