aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2009-06-06 11:47:29 +0000
committerCorinna Vinschen <corinna@vinschen.de>2009-06-06 11:47:29 +0000
commit1d95e198c12ef65b5157da462c9d77908f48597f (patch)
tree602810eec402d63734db2b43b84249dddca805d5
parent611fe46079da132279a9a94af2f3e79b94038d27 (diff)
downloadnewlib-1d95e198c12ef65b5157da462c9d77908f48597f.zip
newlib-1d95e198c12ef65b5157da462c9d77908f48597f.tar.gz
newlib-1d95e198c12ef65b5157da462c9d77908f48597f.tar.bz2
* dll_init.h (struct dll): Set size of name element to ANYSIZE_ARRAY.
* dll_init.cc: Fix formatting. (dll_list::alloc): Only allocate as much memory for struct dll as necessary for given DLL name. (dll_list::load_after_fork): Only read a single page of parent memory. Only read more if namelen indicates that it's necessary.
-rw-r--r--winsup/cygwin/ChangeLog9
-rw-r--r--winsup/cygwin/dll_init.cc82
-rw-r--r--winsup/cygwin/dll_init.h5
3 files changed, 60 insertions, 36 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 14e82b9..478170e 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,12 @@
+2009-06-06 Corinna Vinschen <corinna@vinschen.de>
+
+ * dll_init.h (struct dll): Set size of name element to ANYSIZE_ARRAY.
+ * dll_init.cc: Fix formatting.
+ (dll_list::alloc): Only allocate as much memory for struct dll as
+ necessary for given DLL name.
+ (dll_list::load_after_fork): Only read a single page of parent memory.
+ Only read more if namelen indicates that it's necessary.
+
2009-06-05 Dave Korn <dave.korn.cygwin@gmail.com>
* winbase.h (ilockexch): Fix asm constraints.
diff --git a/winsup/cygwin/dll_init.cc b/winsup/cygwin/dll_init.cc
index acd767d..e42718d 100644
--- a/winsup/cygwin/dll_init.cc
+++ b/winsup/cygwin/dll_init.cc
@@ -1,6 +1,7 @@
/* dll_init.cc
- Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Red Hat, Inc.
+ Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+ 2007, 2008, 2009 Red Hat, Inc.
This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
@@ -19,6 +20,7 @@ details. */
#include "pinfo.h"
#include "cygtls.h"
#include <wchar.h>
+#include <alloca.h>
extern void __stdcall check_sanity_and_sync (per_process *);
@@ -108,6 +110,7 @@ dll_list::alloc (HINSTANCE h, per_process *p, dll_type type)
{
WCHAR name[NT_MAX_PATH];
DWORD namelen = GetModuleFileNameW (h, name, sizeof (name));
+ size_t d_size = sizeof (dll) + namelen * sizeof (WCHAR);
/* Already loaded? */
dll *d = dlls[name];
@@ -144,8 +147,8 @@ dll_list::alloc (HINSTANCE h, per_process *p, dll_type type)
n = ((n - r) + s1.dwAllocationGranularity);
/* First reserve the area of memory, then commit it. */
- if (VirtualAlloc ((void *) n, sizeof (dll), MEM_RESERVE, PAGE_READWRITE))
- d = (dll *) VirtualAlloc ((void *) n, sizeof (dll), MEM_COMMIT,
+ if (VirtualAlloc ((void *) n, d_size, MEM_RESERVE, PAGE_READWRITE))
+ d = (dll *) VirtualAlloc ((void *) n, d_size, MEM_COMMIT,
PAGE_READWRITE);
if (d)
break;
@@ -265,11 +268,12 @@ release_upto (const PWCHAR name, DWORD here)
else
{
size = mb.RegionSize;
- if (!(mb.State == MEM_RESERVE && mb.AllocationProtect == PAGE_NOACCESS &&
- (((void *) start < cygheap->user_heap.base
- || (void *) start > cygheap->user_heap.top) &&
- ((void *) start < (void *) cygheap
- || (void *) start > (void *) ((char *) cygheap + CYGHEAPSIZE)))))
+ if (!(mb.State == MEM_RESERVE && mb.AllocationProtect == PAGE_NOACCESS
+ && (((void *) start < cygheap->user_heap.base
+ || (void *) start > cygheap->user_heap.top)
+ && ((void *) start < (void *) cygheap
+ || (void *) start
+ > (void *) ((char *) cygheap + CYGHEAPSIZE)))))
continue;
if (!VirtualFree ((void *) start, 0, MEM_RELEASE))
api_fatal ("couldn't release memory %p(%d) for '%W' alignment, %E\n",
@@ -277,72 +281,82 @@ release_upto (const PWCHAR name, DWORD here)
}
}
-/* Reload DLLs after a fork. Iterates over the list of dynamically loaded DLLs
- and attempts to load them in the same place as they were loaded in the parent. */
+/* Reload DLLs after a fork. Iterates over the list of dynamically loaded
+ DLLs and attempts to load them in the same place as they were loaded in
+ the parent. */
void
dll_list::load_after_fork (HANDLE parent, dll *first)
{
int try2 = 0;
- dll d;
+ dll *d = (dll *) alloca (sizeof (dll) + (NT_MAX_PATH - 1) * sizeof (WCHAR));
void *next = first;
while (next)
{
DWORD nb;
- /* Read the dll structure from the parent. */
- if (!ReadProcessMemory (parent, next, &d, sizeof (dll), &nb) ||
- nb != sizeof (dll))
+ /* Read 4K of the dll structure from the parent. A full page has
+ been allocated anyway and this covers most, if not all DLL paths.
+ Only if d->namelen indicates that more than 4K are required,
+ read them in a second step. */
+ if (!ReadProcessMemory (parent, next, d, getsystempagesize (), &nb)
+ || nb != getsystempagesize ())
+ return;
+ size_t namelen = d->namelen * sizeof (WCHAR);
+ if (namelen >= getsystempagesize () - sizeof (dll)
+ && (!ReadProcessMemory (parent, next, d->name, namelen, &nb)
+ || nb != namelen))
return;
/* We're only interested in dynamically loaded dlls.
Hopefully, this function wouldn't even have been called unless
the parent had some of those. */
- if (d.type == DLL_LOAD)
+ if (d->type == DLL_LOAD)
{
bool unload = true;
- HMODULE h = LoadLibraryExW (d.name, NULL, DONT_RESOLVE_DLL_REFERENCES);
+ HMODULE h = LoadLibraryExW (d->name, NULL,
+ DONT_RESOLVE_DLL_REFERENCES);
if (!h)
- system_printf ("can't reload %W", d.name);
+ system_printf ("can't reload %W", d->name);
/* See if DLL will load in proper place. If so, free it and reload
it the right way.
- It sort of stinks that we can't invert the order of the FreeLibrary
- and LoadLibrary since Microsoft documentation seems to imply that that
- should do what we want. However, since the library was loaded above,
- the second LoadLibrary does not execute it's startup code unless it
- is first unloaded. */
- else if (h == d.handle)
+ It sort of stinks that we can't invert the order of the
+ FreeLibrary and LoadLibrary since Microsoft documentation seems
+ to imply that that should do what we want. However, since the
+ library was loaded above, the second LoadLibrary does not execute
+ it's startup code unless it is first unloaded. */
+ else if (h == d->handle)
{
if (unload)
{
FreeLibrary (h);
- LoadLibraryW (d.name);
+ LoadLibraryW (d->name);
}
}
else if (try2)
api_fatal ("unable to remap %W to same address as parent(%p) != %p",
- d.name, d.handle, h);
+ d->name, d->handle, h);
else
{
- /* It loaded in the wrong place. Dunno why this happens but it always
- seems to happen when there are multiple DLLs attempting to load into
- the same address space. In the "forked" process, the second DLL always
- loads into a different location. */
+ /* It loaded in the wrong place. Dunno why this happens but it
+ always seems to happen when there are multiple DLLs attempting
+ to load into the same address space. In the "forked" process,
+ the second DLL always loads into a different location. */
FreeLibrary (h);
/* Block all of the memory up to the new load address. */
- reserve_upto (d.name, (DWORD) d.handle);
+ reserve_upto (d->name, (DWORD) d->handle);
try2 = 1; /* And try */
continue; /* again. */
}
- /* If we reached here, and try2 is set, then there is a lot of memory to
- release. */
+ /* If we reached here, and try2 is set, then there is a lot of
+ memory to release. */
if (try2)
{
- release_upto (d.name, (DWORD) d.handle);
+ release_upto (d->name, (DWORD) d->handle);
try2 = 0;
}
}
- next = d.next; /* Get the address of the next DLL. */
+ next = d->next; /* Get the address of the next DLL. */
}
in_forkee = false;
}
diff --git a/winsup/cygwin/dll_init.h b/winsup/cygwin/dll_init.h
index dd7dfb3..b6c24b2 100644
--- a/winsup/cygwin/dll_init.h
+++ b/winsup/cygwin/dll_init.h
@@ -1,6 +1,7 @@
/* dll_init.h
- Copyright 1998, 1999, 2000, 2001 Red Hat, Inc.
+ Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2007, 2008,
+ 2009 Red Hat, Inc.
This file is part of Cygwin.
@@ -51,7 +52,7 @@ struct dll
int count;
dll_type type;
int namelen;
- WCHAR name[NT_MAX_PATH];
+ WCHAR name[ANYSIZE_ARRAY];
void detach ();
int init ();
};