Mail Archives: cygwin-developers/1998/10/28/16:09:18
Here's some analysis of the problem I had reported earlier on not being
able to load a cygwin DLL correctly from a non-cygwin main app (such as
mingw or msvc or borland).
This is applicable in both cases of using a DLL -- linking against an
import library or loading it dynamically using LoadLibrary/GetProcAddress
API.
Here're the 3 common scenarios:
# Main App DLL Result
=== ======== ========= ========
1 cygwin cygwin OK
2 cygwin non-cygwin OK
3 non-cygwin cygwin CRASH!
The last one is standing in the way of using EGCS/Cygwin as a viable
replacement for MSVC for various applications, such as for JAVA JNI
(and with that I conclude the marketing portion of this message ;-).
I'll assume the use of DECLARE_CYGWIN_DLL(DllMain) here, and so the
entry point, _cygwin32_dll_entry AT 12, is the key here. Please see
<cygwin32/cygwin_dll.h> for the body of _cygwin32_dll_entry AT 12 if
you're not familiar with it.
In all 3 cases, the entry point is the first step in the DLL
initialization, which then in turn calls cygwin32_attach_dll to get
things rolling.
Here's what happens during DLL initialization in cases 1 and 3 (Case 2
is irrelevant for the purposes of this bug):
Case 1. We start at _cygwin32_dll_entry AT 12:
-> _cygwin32_dll_entry AT 12 [ case DLL_PROCESS_ATTACH ]
-> cygwin32_attach_dll [ HANDLE, User DLL Main ]
-> cygwin_crt0_common
-> dll_dllcrt0 [ HANDLE, per_process * ]
-> the_.recordDll [ HANDLE, per_process * ]
Case 3. Ditto.
-> _cygwin32_dll_entry AT 12 [ case DLL_PROCESS_ATTACH ]
-> cygwin32_attach_dll [ HANDLE, User DLL Main ]
-> cygwin_crt0_common
-> dll_dllcrt0 [ HANDLE, per_process * ]
[ >>>>> POSSIBLE FIX WILL KICK-START CYGWIN DLL HERE <<<<<< ]
-> the_.recordDll [ HANDLE, per_process * ]
They look the same so far, so where's the problem? Let's take a look
inside ``DllList::recordDll (HANDLE, per_process *)''
int
DllList::recordDll (HANDLE, per_process *)
{
// ...
if (_initCalled) // main module is already initialized
{
if (!initOneDll (p))
ret = -1;
}
// ...
}
The variable _initCalled is 1 for Case 1 -- which means that the user
and process info are already initialized for Case 1 (makes sense since
the main program is also dependent on Cygwin DLL and dcrt0 did the right
thing by calling ``DllList::initAll()''), *BUT*, it's 0 for Case 3 --
which means that various stuff that's done in DllList::initAll() is now
MISSING here.
Looking in more detail, things such as the reentrant data, application
heap, signals, threads stuff, etc are also not initialized in Case 3
either, and that points me towards what dll_dcrt0_1 does when a Cygwin
app is kicked from crt0.
So, basically we need something similar to dll_crt0_1 that is called from
dll_dllcrt0 to initialize the various state information in Cygwin when
a Cygwin DLL is loaded for the first time by a non-cygwin app.
My pitiful attempts to figure out what needs to be initialized by copying
various portions of dll_crt0_1 into dll_dllcrt0 have failed miserably so
far; I'm hoping others familiar with winsup internals will know the fix
right away.
Regards,
Mumit
- Raw text -