`On Fri, 29 Nov 2002, Dimitrie O. Paun wrote:
On November 25, 2002 05:39 pm, Francois Gouget wrote:
However there is no wrapper involved in the above. if you have a wrapper, then the load sequence is: wine loads mfcapp.exe.so which is the wrapper, and then mfcapp.exe.so then loads mfcapp.dll.so which contains the actual application.
But we have a wrapper already, why do we need two of them? It seems to me one should be enough, if we can instruct wine to load said libs before loading the app, no?
If you modify wine itself then you should be able to remove the wrapper. However, how will you instruct Wine to load just the right libraries? Note that Wine should not load extra libraries, especially not GDI and stuff, unless it's needed. So you need a way to instruct Wine to do that just for this application. You could do that by writting a wrapper script around Wine (hmm, a wrapper again, different level but still a wrapper), or by having Wine get that information from the .so without dlopening it.
I say 'mfcapp' because it's a typical case where you need the arapper. The reason for this one is that because of C++ you need to link to the mfc library in the Unix sense (Winelib does not know how to import virtual table pointers because they are variables, not functions). But this causes MFC static initializers to run before the dlls it depends on have been loaded and initialized.
Sorry, I have to admit: this linking, importing, etc. is all Chinese to me. Is this ignorance of importing variables a limitation of Winelib that we can fix (import libraries?), or is it something fundamentally unfixable?
Linking in the unix sense is the act of doing 'gcc -lfoo'. Unix will take care of loading the library foo. Importing is the act of telling winebuild that you want to import a WineLib library, and the act of loading the library is done by Wine using dlopen just before calling the 'WinMain' of your application (i.e. it's done after all the libraries you link with 'in the Unix sense' have been loaded and initialized).
For instance you 'import' gdi32, you don't link with it: you never use '-lgdi32' when compiling a WineLib application. However, you have to link with Unix libraries like opengl or curses and you cannot import them (because they don't have the required 'PE' information that winebuild adds in the .spec.c file).
So how does it work when you call something like CreateFileA? My understanding of it is that winebuild creates a strampoline for it in the .spec.c file. Then at load time Wine does a dlsym on the appropriate symbol and sets the trampoline to point to the right address. Thus when you call CreateFileA, your code jumps to the trampoline which jumps to the actual CreaFileA implementation.
But you cannot create trampolines for variables. When your code tries to access a variable it accesses a specific address. You cannot store a 'jmp' at that address to force it to read stuff from another address. To solve this problem it seems like we would need to replace all variable declarations with code that looks like '*get_variable()' which besides the compilation issues is impossible if the variable access is generated by the compiler itself which is what happens with class virtual tables.
BTW, can you please take a look here: http://www.dssd.ca/wine/Winelib-Apps.html#visual-mingw It seems I'm running in the same problem.
The way I understand it though is a bit different (or so it seems to me): -- wine calls PROCESS_InitWine (first thing it does in main()) -- PROCESS_InitWine -> open_builtin_exe_file -> wine_dll_load_main_exe -- wine_dll_load_main_exe -> dlopen_dll So this one loads the .so, and this triggers the static initializers to run, thus calling the statically constructed classes, right? And here the problem happens. Why? Because the kernel & friends have not yet been loaded?
Yes, I believe the problem is that dlopening your application exe causes all the libraries it is linked with in the Unix sense to be loaded and initialized immediately. Then your exe's static initializers are run which registers with Wine the list of dlls that your application wants to load. So when the CCriticalSection constructor tries to call a Wine function it is likely that the corresponding library has not yet been loaded or initialized.