Fwd: Re: [putty]Winelib support + patch

Francois Gouget fgouget at free.fr
Fri Nov 29 13:45:51 CST 2002

`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.

Francois Gouget         fgouget at free.fr        http://fgouget.free.fr/
  Good judgment comes from experience, and experience comes from bad judgment
                               -- Barry LePatner

More information about the wine-devel mailing list