* 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.
This commit is contained in:
parent
611fe46079
commit
1d95e198c1
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 ();
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue