mirror of
git://sourceware.org/git/newlib-cygwin.git
synced 2025-02-21 00:07:36 +08:00
* 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>
|
2009-06-05 Dave Korn <dave.korn.cygwin@gmail.com>
|
||||||
|
|
||||||
* winbase.h (ilockexch): Fix asm constraints.
|
* winbase.h (ilockexch): Fix asm constraints.
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/* dll_init.cc
|
/* 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
|
This software is a copyrighted work licensed under the terms of the
|
||||||
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
||||||
@ -19,6 +20,7 @@ details. */
|
|||||||
#include "pinfo.h"
|
#include "pinfo.h"
|
||||||
#include "cygtls.h"
|
#include "cygtls.h"
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
|
#include <alloca.h>
|
||||||
|
|
||||||
extern void __stdcall check_sanity_and_sync (per_process *);
|
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];
|
WCHAR name[NT_MAX_PATH];
|
||||||
DWORD namelen = GetModuleFileNameW (h, name, sizeof (name));
|
DWORD namelen = GetModuleFileNameW (h, name, sizeof (name));
|
||||||
|
size_t d_size = sizeof (dll) + namelen * sizeof (WCHAR);
|
||||||
|
|
||||||
/* Already loaded? */
|
/* Already loaded? */
|
||||||
dll *d = dlls[name];
|
dll *d = dlls[name];
|
||||||
@ -144,8 +147,8 @@ dll_list::alloc (HINSTANCE h, per_process *p, dll_type type)
|
|||||||
n = ((n - r) + s1.dwAllocationGranularity);
|
n = ((n - r) + s1.dwAllocationGranularity);
|
||||||
|
|
||||||
/* First reserve the area of memory, then commit it. */
|
/* First reserve the area of memory, then commit it. */
|
||||||
if (VirtualAlloc ((void *) n, sizeof (dll), MEM_RESERVE, PAGE_READWRITE))
|
if (VirtualAlloc ((void *) n, d_size, MEM_RESERVE, PAGE_READWRITE))
|
||||||
d = (dll *) VirtualAlloc ((void *) n, sizeof (dll), MEM_COMMIT,
|
d = (dll *) VirtualAlloc ((void *) n, d_size, MEM_COMMIT,
|
||||||
PAGE_READWRITE);
|
PAGE_READWRITE);
|
||||||
if (d)
|
if (d)
|
||||||
break;
|
break;
|
||||||
@ -265,11 +268,12 @@ release_upto (const PWCHAR name, DWORD here)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
size = mb.RegionSize;
|
size = mb.RegionSize;
|
||||||
if (!(mb.State == MEM_RESERVE && mb.AllocationProtect == PAGE_NOACCESS &&
|
if (!(mb.State == MEM_RESERVE && mb.AllocationProtect == PAGE_NOACCESS
|
||||||
(((void *) start < cygheap->user_heap.base
|
&& (((void *) start < cygheap->user_heap.base
|
||||||
|| (void *) start > cygheap->user_heap.top) &&
|
|| (void *) start > cygheap->user_heap.top)
|
||||||
((void *) start < (void *) cygheap
|
&& ((void *) start < (void *) cygheap
|
||||||
|| (void *) start > (void *) ((char *) cygheap + CYGHEAPSIZE)))))
|
|| (void *) start
|
||||||
|
> (void *) ((char *) cygheap + CYGHEAPSIZE)))))
|
||||||
continue;
|
continue;
|
||||||
if (!VirtualFree ((void *) start, 0, MEM_RELEASE))
|
if (!VirtualFree ((void *) start, 0, MEM_RELEASE))
|
||||||
api_fatal ("couldn't release memory %p(%d) for '%W' alignment, %E\n",
|
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
|
/* Reload DLLs after a fork. Iterates over the list of dynamically loaded
|
||||||
and attempts to load them in the same place as they were loaded in the parent. */
|
DLLs and attempts to load them in the same place as they were loaded in
|
||||||
|
the parent. */
|
||||||
void
|
void
|
||||||
dll_list::load_after_fork (HANDLE parent, dll *first)
|
dll_list::load_after_fork (HANDLE parent, dll *first)
|
||||||
{
|
{
|
||||||
int try2 = 0;
|
int try2 = 0;
|
||||||
dll d;
|
dll *d = (dll *) alloca (sizeof (dll) + (NT_MAX_PATH - 1) * sizeof (WCHAR));
|
||||||
|
|
||||||
void *next = first;
|
void *next = first;
|
||||||
while (next)
|
while (next)
|
||||||
{
|
{
|
||||||
DWORD nb;
|
DWORD nb;
|
||||||
/* Read the dll structure from the parent. */
|
/* Read 4K of the dll structure from the parent. A full page has
|
||||||
if (!ReadProcessMemory (parent, next, &d, sizeof (dll), &nb) ||
|
been allocated anyway and this covers most, if not all DLL paths.
|
||||||
nb != sizeof (dll))
|
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;
|
return;
|
||||||
|
|
||||||
/* We're only interested in dynamically loaded dlls.
|
/* We're only interested in dynamically loaded dlls.
|
||||||
Hopefully, this function wouldn't even have been called unless
|
Hopefully, this function wouldn't even have been called unless
|
||||||
the parent had some of those. */
|
the parent had some of those. */
|
||||||
if (d.type == DLL_LOAD)
|
if (d->type == DLL_LOAD)
|
||||||
{
|
{
|
||||||
bool unload = true;
|
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)
|
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
|
/* See if DLL will load in proper place. If so, free it and reload
|
||||||
it the right way.
|
it the right way.
|
||||||
It sort of stinks that we can't invert the order of the FreeLibrary
|
It sort of stinks that we can't invert the order of the
|
||||||
and LoadLibrary since Microsoft documentation seems to imply that that
|
FreeLibrary and LoadLibrary since Microsoft documentation seems
|
||||||
should do what we want. However, since the library was loaded above,
|
to imply that that should do what we want. However, since the
|
||||||
the second LoadLibrary does not execute it's startup code unless it
|
library was loaded above, the second LoadLibrary does not execute
|
||||||
is first unloaded. */
|
it's startup code unless it is first unloaded. */
|
||||||
else if (h == d.handle)
|
else if (h == d->handle)
|
||||||
{
|
{
|
||||||
if (unload)
|
if (unload)
|
||||||
{
|
{
|
||||||
FreeLibrary (h);
|
FreeLibrary (h);
|
||||||
LoadLibraryW (d.name);
|
LoadLibraryW (d->name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (try2)
|
else if (try2)
|
||||||
api_fatal ("unable to remap %W to same address as parent(%p) != %p",
|
api_fatal ("unable to remap %W to same address as parent(%p) != %p",
|
||||||
d.name, d.handle, h);
|
d->name, d->handle, h);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* It loaded in the wrong place. Dunno why this happens but it always
|
/* It loaded in the wrong place. Dunno why this happens but it
|
||||||
seems to happen when there are multiple DLLs attempting to load into
|
always seems to happen when there are multiple DLLs attempting
|
||||||
the same address space. In the "forked" process, the second DLL always
|
to load into the same address space. In the "forked" process,
|
||||||
loads into a different location. */
|
the second DLL always loads into a different location. */
|
||||||
FreeLibrary (h);
|
FreeLibrary (h);
|
||||||
/* Block all of the memory up to the new load address. */
|
/* 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 */
|
try2 = 1; /* And try */
|
||||||
continue; /* again. */
|
continue; /* again. */
|
||||||
}
|
}
|
||||||
/* If we reached here, and try2 is set, then there is a lot of memory to
|
/* If we reached here, and try2 is set, then there is a lot of
|
||||||
release. */
|
memory to release. */
|
||||||
if (try2)
|
if (try2)
|
||||||
{
|
{
|
||||||
release_upto (d.name, (DWORD) d.handle);
|
release_upto (d->name, (DWORD) d->handle);
|
||||||
try2 = 0;
|
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;
|
in_forkee = false;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/* dll_init.h
|
/* 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.
|
This file is part of Cygwin.
|
||||||
|
|
||||||
@ -51,7 +52,7 @@ struct dll
|
|||||||
int count;
|
int count;
|
||||||
dll_type type;
|
dll_type type;
|
||||||
int namelen;
|
int namelen;
|
||||||
WCHAR name[NT_MAX_PATH];
|
WCHAR name[ANYSIZE_ARRAY];
|
||||||
void detach ();
|
void detach ();
|
||||||
int init ();
|
int init ();
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user