* dll_init.h (struct dll): Re-add modname.

* dll_init.cc: Throughout, use modname where it was used before.
	(dll_list::operator[]): Use modname.  Move comment from dll_list::alloc
	here and remove hint about GetModuleBaseNameW.
	(dll_list::alloc): Store full path in name, pointer to basename in
	modname.  Search dll using modname.
This commit is contained in:
Corinna Vinschen 2012-02-09 14:41:21 +00:00
parent e59d6a1469
commit 9eba4de269
3 changed files with 36 additions and 28 deletions

View File

@ -1,3 +1,12 @@
2012-02-09 Corinna Vinschen <corinna@vinschen.de>
* dll_init.h (struct dll): Re-add modname.
* dll_init.cc: Throughout, use modname where it was used before.
(dll_list::operator[]): Use modname. Move comment from dll_list::alloc
here and remove hint about GetModuleBaseNameW.
(dll_list::alloc): Store full path in name, pointer to basename in
modname. Search dll using modname.
2012-02-08 Christopher Faylor <me.cygwin2012@cgf.cx> 2012-02-08 Christopher Faylor <me.cygwin2012@cgf.cx>
* dtable.cc (dtable::init_std_file_from_handle): Reinstate opening tty * dtable.cc (dtable::init_std_file_from_handle): Reinstate opening tty

View File

@ -106,13 +106,17 @@ dll::init ()
return ret; return ret;
} }
/* Look for a dll based on name */ /* Look for a dll based on the basename.
Only compare basenames for DLLs. Per MSDN, the Windows loader re-uses
the already loaded DLL, if the new DLL has the same basename as the
already loaded DLL. It will not try to load the new DLL at all. See
http://msdn.microsoft.com/en-us/library/ms682586%28v=vs.85%29.aspx */
dll * dll *
dll_list::operator[] (const PWCHAR name) dll_list::operator[] (const PWCHAR modname)
{ {
dll *d = &start; dll *d = &start;
while ((d = d->next) != NULL) while ((d = d->next) != NULL)
if (!wcscasecmp (name, d->name)) if (!wcscasecmp (modname, d->modname))
return d; return d;
return NULL; return NULL;
@ -124,27 +128,21 @@ dll_list::operator[] (const PWCHAR name)
dll * dll *
dll_list::alloc (HINSTANCE h, per_process *p, dll_type type) dll_list::alloc (HINSTANCE h, per_process *p, dll_type type)
{ {
/* Only use and compare basenames for DLLs. Per MSDN, the Windows loader WCHAR name[NT_MAX_PATH];
re-uses the already loaded DLL, if the new DLL has the same basename GetModuleFileNameW (h, name, sizeof (name));
as the already loaded DLL. It will not try to load the new DLL at all.
See http://msdn.microsoft.com/en-us/library/ms682586%28v=vs.85%29.aspx
Use GetModuleFileNameW + wcsrchr rather than GetModuleBaseNameW since
it's faster per MSDN, and it doesn't require to link against psapi. */
WCHAR buf[NT_MAX_PATH];
GetModuleFileNameW (h, buf, sizeof (buf));
PWCHAR name = wcsrchr (buf, L'\\') + 1;
DWORD namelen = wcslen (name); DWORD namelen = wcslen (name);
PWCHAR modname = wcsrchr (name, L'\\') + 1;
guard (true); guard (true);
/* Already loaded? */ /* Already loaded? */
dll *d = dlls[name]; dll *d = dlls[modname];
if (d) if (d)
{ {
if (!in_forkee) if (!in_forkee)
d->count++; /* Yes. Bump the usage count. */ d->count++; /* Yes. Bump the usage count. */
else if (d->handle != h) else if (d->handle != h)
fabort ("%W: Loaded to different address: parent(%p) != child(%p)", fabort ("%W: Loaded to different address: parent(%p) != child(%p)",
name, d->handle, h); modname, d->handle, h);
d->p = p; d->p = p;
} }
else else
@ -156,6 +154,7 @@ dll_list::alloc (HINSTANCE h, per_process *p, dll_type type)
supplied info about this DLL. */ supplied info about this DLL. */
d->count = 1; d->count = 1;
wcscpy (d->name, name); wcscpy (d->name, name);
d->modname = d->name + (modname - name);
d->handle = h; d->handle = h;
d->has_dtors = true; d->has_dtors = true;
d->p = p; d->p = p;
@ -240,9 +239,9 @@ dll_list::topsort ()
while ((d = d->next)) while ((d = d->next))
{ {
#ifdef DEBUGGING #ifdef DEBUGGING
paranoid_printf ("%W", d->name); paranoid_printf ("%W", d->modname);
for (int i = 1; i < -d->ndeps; i++) for (int i = 1; i < -d->ndeps; i++)
paranoid_printf ("-> %W", d->deps[i - 1]->name); paranoid_printf ("-> %W", d->deps[i - 1]->modname);
#endif #endif
/* It would be really nice to be able to keep this information /* It would be really nice to be able to keep this information
@ -409,7 +408,7 @@ dll_list::reserve_space ()
for (dll* d = dlls.istart (DLL_LOAD); d; d = dlls.inext ()) for (dll* d = dlls.istart (DLL_LOAD); d; d = dlls.inext ())
if (!VirtualAlloc (d->handle, d->image_size, MEM_RESERVE, PAGE_NOACCESS)) if (!VirtualAlloc (d->handle, d->image_size, MEM_RESERVE, PAGE_NOACCESS))
fabort ("address space needed by '%W' (%p) is already occupied", fabort ("address space needed by '%W' (%p) is already occupied",
d->name, d->handle); d->modname, d->handle);
} }
/* Reload DLLs after a fork. Iterates over the list of dynamically loaded /* Reload DLLs after a fork. Iterates over the list of dynamically loaded
@ -455,33 +454,32 @@ void dll_list::load_after_fork_impl (HANDLE parent, dll* d, int retries)
*/ */
if (!retries && !VirtualFree (d->handle, 0, MEM_RELEASE)) if (!retries && !VirtualFree (d->handle, 0, MEM_RELEASE))
fabort ("unable to release protective reservation for %W (%08lx), %E", fabort ("unable to release protective reservation for %W (%08lx), %E",
d->name, d->handle); d->modname, d->handle);
HMODULE h = LoadLibraryExW (d->name, NULL, DONT_RESOLVE_DLL_REFERENCES); HMODULE h = LoadLibraryExW (d->name, NULL, DONT_RESOLVE_DLL_REFERENCES);
if (!h) if (!h)
fabort ("unable to create interim mapping for %W, %E", fabort ("unable to create interim mapping for %W, %E", d->name);
d->name);
if (h != d->handle) if (h != d->handle)
{ {
sigproc_printf ("%W loaded in wrong place: %08lx != %08lx", sigproc_printf ("%W loaded in wrong place: %08lx != %08lx",
d->name, h, d->handle); d->modname, h, d->handle);
FreeLibrary (h); FreeLibrary (h);
DWORD reservation = reserve_at (d->name, (DWORD) h, DWORD reservation = reserve_at (d->modname, (DWORD) h,
(DWORD) d->handle, d->image_size); (DWORD) d->handle, d->image_size);
if (!reservation) if (!reservation)
fabort ("unable to block off %p to prevent %W from loading there", fabort ("unable to block off %p to prevent %W from loading there",
h, d->name); h, d->modname);
if (retries < DLL_RETRY_MAX) if (retries < DLL_RETRY_MAX)
load_after_fork_impl (parent, d, retries+1); load_after_fork_impl (parent, d, retries+1);
else else
fabort ("unable to remap %W to same address as parent (%08lx) - try running rebaseall", fabort ("unable to remap %W to same address as parent (%08lx) - try running rebaseall",
d->name, d->handle); d->modname, d->handle);
/* once the above returns all the dlls are mapped; release /* once the above returns all the dlls are mapped; release
the reservation and continue unwinding */ the reservation and continue unwinding */
sigproc_printf ("releasing blocked space at %08lx", reservation); sigproc_printf ("releasing blocked space at %08lx", reservation);
release_at (d->name, reservation); release_at (d->modname, reservation);
return; return;
} }
} }
@ -497,7 +495,7 @@ void dll_list::load_after_fork_impl (HANDLE parent, dll* d, int retries)
{ {
if (!VirtualFree (d->handle, 0, MEM_RELEASE)) if (!VirtualFree (d->handle, 0, MEM_RELEASE))
fabort ("unable to release protective reservation for %W (%08lx), %E", fabort ("unable to release protective reservation for %W (%08lx), %E",
d->name, d->handle); d->modname, d->handle);
} }
else else
{ {
@ -505,14 +503,14 @@ void dll_list::load_after_fork_impl (HANDLE parent, dll* d, int retries)
to ours or we wouldn't have gotten this far */ to ours or we wouldn't have gotten this far */
if (!FreeLibrary (d->handle)) if (!FreeLibrary (d->handle))
fabort ("unable to unload interim mapping of %W, %E", fabort ("unable to unload interim mapping of %W, %E",
d->name); d->modname);
} }
HMODULE h = LoadLibraryW (d->name); HMODULE h = LoadLibraryW (d->name);
if (!h) if (!h)
fabort ("unable to map %W, %E", d->name); fabort ("unable to map %W, %E", d->name);
if (h != d->handle) if (h != d->handle)
fabort ("unable to map %W to same address as parent: %p != %p", fabort ("unable to map %W to same address as parent: %p != %p",
d->name, d->handle, h); d->modname, d->handle, h);
} }
} }

View File

@ -56,6 +56,7 @@ struct dll
dll** deps; dll** deps;
DWORD image_size; DWORD image_size;
void* preferred_base; void* preferred_base;
PWCHAR modname;
WCHAR name[1]; WCHAR name[1];
void detach (); void detach ();
int init (); int init ();