diff options
Diffstat (limited to 'winsup/cygwin/dll_init.cc')
-rw-r--r-- | winsup/cygwin/dll_init.cc | 499 |
1 files changed, 0 insertions, 499 deletions
diff --git a/winsup/cygwin/dll_init.cc b/winsup/cygwin/dll_init.cc deleted file mode 100644 index a1d217576..000000000 --- a/winsup/cygwin/dll_init.cc +++ /dev/null @@ -1,499 +0,0 @@ -/* dll_init.cc - - Copyright 1998, 1999, 2000 Cygnus Solutions. - -This software is a copyrighted work licensed under the terms of the -Cygwin license. Please consult the file "CYGWIN_LICENSE" for -details. */ - -#include <stdlib.h> -#include "winsup.h" -#include "exceptions.h" -#include "dll_init.h" - -extern void __stdcall check_sanity_and_sync (per_process *); - -#ifdef _MT_SAFE -extern ResourceLocks _reslock NO_COPY; -extern MTinterface _mtinterf NO_COPY; -#endif /*_MT_SAFE*/ - -/* WARNING: debug can't be called before init !!!! */ - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -// the private structure - -typedef enum { NONE, LINK, LOAD } dllType; - -struct dll -{ - per_process *p; - HMODULE handle; - const char *name; - dllType type; -}; - -//----------------------------------------------------------------------------- - -#define MAX_DLL_BEFORE_INIT 100 // FIXME: enough ??? -static dll _list_before_init[MAX_DLL_BEFORE_INIT]; - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -// local variables - -static DllList _the; -static int _last = 0; -static int _max = MAX_DLL_BEFORE_INIT; -static dll *_list = _list_before_init; -static int _initCalled = 0; -static int _numberOfOpenedDlls = 0; -static int _forkeeMustReloadDlls = 0; -static int _in_forkee = 0; -static const char *_dlopenedLib = 0; -static int _dlopenIndex = -1; - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -static int __dll_global_dtors_recorded = 0; - -static void -__dll_global_dtors() -{ - _the.doGlobalDestructorsOfDlls(); -} - -static void -doGlobalCTORS (per_process *p) -{ - void (**pfunc)() = p->ctors; - - /* Run ctors backwards, so skip the first entry and find how many - there are, then run them. */ - - if (pfunc) - { - int i; - for (i = 1; pfunc[i]; i++); - - for (int j = i - 1; j > 0; j-- ) - (pfunc[j]) (); - } -} - -static void -doGlobalDTORS (per_process *p) -{ - if (!p) - return; - void (**pfunc)() = p->dtors; - for (int i = 1; pfunc[i]; i++) - (pfunc[i]) (); -} - -#define INC 500 - -static int -add (HMODULE h, char *name, per_process *p, dllType type) -{ - int ret = -1; - - if (p) - check_sanity_and_sync (p); - - if (_last == _max) - { - if (!_initCalled) // we try to load more than MAX_DLL_BEFORE_INIT - { - small_printf ("try to load more dll than max allowed=%d\n", - MAX_DLL_BEFORE_INIT); - ExitProcess (1); - } - - dll* newArray = new dll[_max+INC]; - if (_list) - { - memcpy (newArray, _list, _max * sizeof (dll)); - if (_list != _list_before_init) - delete []_list; - } - _list = newArray; - _max += INC; - } - - _list[_last].name = name && type == LOAD ? strdup (name) : NULL; - _list[_last].handle = h; - _list[_last].p = p; - _list[_last].type = type; - - ret = _last++; - return ret; -} - -static int -initOneDll (per_process *p) -{ - /* global variable user_data must be initialized */ - if (user_data == NULL) - { - small_printf ("WARNING: process not inited while trying to init a DLL!\n"); - return 0; - } - - /* init impure_ptr */ - *(p->impure_ptr_ptr) = *(user_data->impure_ptr_ptr); - - /* FIXME: init environment (useful?) */ - *(p->envptr) = *(user_data->envptr); - - /* FIXME: need other initializations? */ - - int ret = 1; - if (!_in_forkee) - { - /* global contructors */ - doGlobalCTORS (p); - - /* entry point of dll (use main of per_process with null args...) */ - if (p->main) - ret = (*(p->main)) (0, 0, 0); - } - - return ret; -} - -DllList& -DllList::the () -{ - return _the; -} - -void -DllList::currentDlOpenedLib (const char *name) -{ - if (_dlopenedLib != 0) - small_printf ("WARNING: previous dlopen of %s wasn't correctly performed\n", _dlopenedLib); - _dlopenedLib = name; - _dlopenIndex = -1; -} - -int -DllList::recordDll (HMODULE h, per_process *p) -{ - int ret = -1; - - /* debug_printf ("Record a dll p=%p\n", p); see WARNING */ - dllType type = LINK; - if (_initCalled) - { - type = LOAD; - _numberOfOpenedDlls++; - forkeeMustReloadDlls (1); - } - - if (_in_forkee) - { - ret = 0; // Just a flag - goto out; - } - - char buf[MAX_PATH]; - GetModuleFileName (h, buf, MAX_PATH); - - if (type == LOAD && _dlopenedLib !=0) - { - // it is not the current dlopened lib - // so we insert one empty lib to preserve place for current dlopened lib - if (!strcasematch (_dlopenedLib, buf)) - { - if (_dlopenIndex == -1) - _dlopenIndex = add (0, 0, 0, NONE); - ret = add (h, buf, p, type); - } - else // it is the current dlopened lib - { - if (_dlopenIndex != -1) - { - _list[_dlopenIndex].handle = h; - _list[_dlopenIndex].p = p; - _list[_dlopenIndex].type = type; - ret = _dlopenIndex; - _dlopenIndex = -1; - } - else // it this case the dlopened lib doesn't need other lib - ret = add (h, buf, p, type); - _dlopenedLib = 0; - } - } - else - ret = add (h, buf, p, type); - -out: - if (_initCalled) // main module is already initialized - { - if (!initOneDll (p)) - ret = -1; - } - return ret; -} - -void -DllList::detachDll (int dll_index) -{ - if (dll_index != -1) - { - dll *aDll = &(_list[dll_index]); - doGlobalDTORS (aDll->p); - if (aDll->type == LOAD) - _numberOfOpenedDlls--; - aDll->type = NONE; - } - else - small_printf ("WARNING: try to detach an already detached dll ...\n"); -} - -void -DllList::initAll () -{ - // init for destructors - // because initAll isn't called in forked process, this exit function will - // be recorded only once - if (!__dll_global_dtors_recorded) - { - atexit (__dll_global_dtors); - __dll_global_dtors_recorded = 1; - } - - if (!_initCalled) - { - debug_printf ("call to DllList::initAll"); - for (int i = 0; i < _last; i++) - { - per_process *p = _list[i].p; - if (p) - initOneDll (p); - } - _initCalled = 1; - } -} - -void -DllList::doGlobalDestructorsOfDlls () -{ - // global destructors in reverse order - for (int i = _last - 1; i >= 0; i--) - { - if (_list[i].type != NONE) - { - per_process *p = _list[i].p; - if (p) - doGlobalDTORS (p); - } - } -} - -int -DllList::numberOfOpenedDlls () -{ - return _numberOfOpenedDlls; -} - -int -DllList::forkeeMustReloadDlls () -{ - return _forkeeMustReloadDlls; -} - -void -DllList::forkeeMustReloadDlls (int i) -{ - _forkeeMustReloadDlls = i; -} - -#define A64K (64 * 1024) - -/* Mark every memory address up to "here" as reserved. This may force - Windows NT to load a DLL in the next available, lowest slot. */ -void -reserve_upto (const char *name, DWORD here) -{ - DWORD size; - MEMORY_BASIC_INFORMATION mb; - for (DWORD start = 0x10000; start < here; start += size) - if (!VirtualQuery ((void *) start, &mb, sizeof (mb))) - size = 64 * 1024; - else - { - size = A64K * ((mb.RegionSize + A64K - 1) / A64K); - start = A64K * (((DWORD) mb.BaseAddress + A64K - 1) / A64K); - - if (start + size > here) - size = here - start; - if (mb.State == MEM_FREE && - !VirtualAlloc ((void *) start, size, MEM_RESERVE, PAGE_NOACCESS)) - api_fatal ("couldn't allocate memory %p(%d) for '%s' alignment, %E\n", - start, size, name); - } -} - -/* Release all of the memory previously allocated by "upto" above. - Note that this may also free otherwise reserved memory. If that becomes - a problem, we'll have to keep track of the memory that we reserve above. */ -void -release_upto (const char *name, DWORD here) -{ - DWORD size; - MEMORY_BASIC_INFORMATION mb; - for (DWORD start = 0x10000; start < here; start += size) - if (!VirtualQuery ((void *) start, &mb, sizeof (mb))) - size = 64 * 1024; - else - { - size = mb.RegionSize; - if (!(mb.State == MEM_RESERVE && mb.AllocationProtect == PAGE_NOACCESS && - ((void *) start < user_data->heapbase || (void *) start > user_data->heaptop))) - continue; - if (!VirtualFree ((void *) start, 0, MEM_RELEASE)) - api_fatal ("couldn't release memory %p(%d) for '%s' alignment, %E\n", - start, size, name); - } -} - -/* 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 -DllList::forkeeLoadDlls () -{ - _initCalled = 1; - _in_forkee = 1; - int try2 = 0; - for (int i = 0; i < _last; i++) - if (_list[i].type == LOAD) - { - const char *name = _list[i].name; - HMODULE handle = _list[i].handle; - HMODULE h = LoadLibraryEx (name, NULL, DONT_RESOLVE_DLL_REFERENCES); - - if (h == handle) - { - FreeLibrary (h); - LoadLibrary (name); - } - else if (try2) - api_fatal ("unable to remap %s to same address as parent -- %p", name, h); - else - { - FreeLibrary (h); - reserve_upto (name, (DWORD) handle); - try2 = 1; - i--; - continue; - } - if (try2) - { - release_upto (name, (DWORD) handle); - try2 = 0; - } - } - _in_forkee = 0; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -// iterators - -DllListIterator::DllListIterator (int type) : _type (type), _index (-1) -{ - operator++ (); -} - -DllListIterator::~DllListIterator () -{ -} - -DllListIterator::operator per_process* () -{ - return _list[index ()].p; -} - -void -DllListIterator::operator++ () -{ - _index++; - while (_index < _last && (int) (_list[_index].type) != _type) - _index++; - if (_index == _last) - _index = -1; -} - -LinkedDllIterator::LinkedDllIterator () : DllListIterator ((int) LINK) -{ -} - -LinkedDllIterator::~LinkedDllIterator () -{ -} - -LoadedDllIterator::LoadedDllIterator () : DllListIterator ((int) LOAD) -{ -} - -LoadedDllIterator::~LoadedDllIterator () -{ -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -// the extern symbols - -extern "C" -{ - /* This is an exported copy of environ which can be used by DLLs - which use cygwin.dll. */ - extern struct _reent reent_data; -}; - -extern "C" -int -dll_dllcrt0 (HMODULE h, per_process *p) -{ - /* Partially initialize Cygwin guts for non-cygwin apps. */ - if (dynamically_loaded && (! user_data || user_data->magic_biscuit == 0)) - { - dll_crt0 (p); - } - return _the.recordDll (h, p); -} - -/* OBSOLETE: This function is obsolescent and will go away in the - future. Cygwin can now handle being loaded from a noncygwin app - using the same entry point. */ - -extern "C" -int -dll_noncygwin_dllcrt0 (HMODULE h, per_process *p) -{ - return dll_dllcrt0 (h, p); -} - -extern "C" -void -cygwin_detach_dll (int dll_index) -{ - _the.detachDll (dll_index); -} - -extern "C" -void -dlfork (int val) -{ - _the.forkeeMustReloadDlls (val); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- |