http://bugs.winehq.org/show_bug.cgi?id=58377
Bug ID: 58377 Summary: winegcc -m32 fails to link when using the new WoW64 mode Product: Wine Version: 10.9 Hardware: x86-64 OS: Linux Status: UNCONFIRMED Severity: normal Priority: P2 Component: winelib Assignee: wine-bugs@winehq.org Reporter: mail@robbertvanderhelm.nl Distribution: ---
Created attachment 78787 --> http://bugs.winehq.org/attachment.cgi?id=78787 winegcc command output
Prompted by Arch switching to the new WoW64 mode in their packages. 32-bit winelib binaries seem to fail to link with the new WoW64 mode. I attached the output of compiling the following file with winegcc from a Wine build configured with `--enable-archs=i386,x86_64`:
/* main.c */ int main() { return 0; }
/* compiled with: LANG=C wineg++ -v -m32 -lole32 -o main main.c */
Swapping `-m32` out for `-m64` the winelib binary builds as expected. Most notably, the underlying GCC invocations include both `-m64` and `-m32` in that order (though it may have always done that), and the core Windows libraries cannot be found (which kind of makes sense since Wine no longer ships actual 32-bit libraries).
On a related note: is it possible to detect whether Wine has been configured with the new WoW64 mode? I may need to detect this at runtime to be able to distribute a build of yabridge that works with both the old and new WoW64 modes.
http://bugs.winehq.org/show_bug.cgi?id=58377
--- Comment #1 from Alexandre Julliard julliard@winehq.org --- 32-bit ELF dlls cannot be built in new wow64 mode, since the whole idea is to not use 32-bit Unix libraries.
If you want to support new wow64 with a 32-bit binary, the only way is to build it as PE. If you need to make Unix calls you have to create a separate Unix library and use the WINE_UNIX_CALL interface. This is still a work in progress as far as Winelib is concerned though.
http://bugs.winehq.org/show_bug.cgi?id=58377
Ken Sharp imwellcushtymelike@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Keywords| |download, source, testcase, | |wow64
http://bugs.winehq.org/show_bug.cgi?id=58377
Zeb Figura z.figura12@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Keywords|download, testcase |
http://bugs.winehq.org/show_bug.cgi?id=58377
Ken Sharp imwellcushtymelike@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Keywords| |download
http://bugs.winehq.org/show_bug.cgi?id=58377
Zeb Figura z.figura12@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |z.figura12@gmail.com
--- Comment #2 from Zeb Figura z.figura12@gmail.com ---
Ken Sharp imwellcushtymelike@gmail.com changed:
What |Removed |Added
Keywords| |download
"download" means that the software that the user is trying to run with Wine can be downloaded. How is that the case here?
http://bugs.winehq.org/show_bug.cgi?id=58377
--- Comment #3 from Austin English austinenglish@gmail.com --- (In reply to Zeb Figura from comment #2)
Ken Sharp imwellcushtymelike@gmail.com changed:
What |Removed |Added
Keywords| |download
"download" means that the software that the user is trying to run with Wine can be downloaded. How is that the case here?
It's not a binary download, but there is source available, so I think 'download' is appropriate. To me 'download' means anyone should be able to test the bug, everything needed is downloadable.
http://bugs.winehq.org/show_bug.cgi?id=58377
Alexandre Julliard julliard@winehq.org changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|UNCONFIRMED |RESOLVED Resolution|--- |WONTFIX
--- Comment #4 from Alexandre Julliard julliard@winehq.org --- In any case I don't think there's anything to fix here, it's working as designed. `gcc -m32` will fail similarly if you don't have 32-bit development libraries.
http://bugs.winehq.org/show_bug.cgi?id=58377
--- Comment #5 from Robbert van der Helm mail@robbertvanderhelm.nl --- Does there happen to be any documentation on the interaction between that WINE_UNIX_CALL interface and Winelib binaries? My end goal here is not necessarily to create a 32-bit binary or to interact with 32-bit ELF libraries, but I am looking for some solution that lets me load PE32/PE32+ libraries while being able to interact with X11, Unix domain sockets, and some other Linux APIs from a single process. Previously winebuild/winegcc offered a simple and seamless way to get this behavior, with only minor command line argument changes required to get a variant that could load 32-bit PE32 libraries.
http://bugs.winehq.org/show_bug.cgi?id=58377
--- Comment #6 from Zeb Figura z.figura12@gmail.com --- (In reply to Robbert van der Helm from comment #5)
Does there happen to be any documentation on the interaction between that WINE_UNIX_CALL interface and Winelib binaries? My end goal here is not necessarily to create a 32-bit binary or to interact with 32-bit ELF libraries, but I am looking for some solution that lets me load PE32/PE32+ libraries while being able to interact with X11, Unix domain sockets, and some other Linux APIs from a single process. Previously winebuild/winegcc offered a simple and seamless way to get this behavior, with only minor command line argument changes required to get a variant that could load 32-bit PE32 libraries.
Unfortunately no, and I'm not sure the interface is stable enough to document either, but in case it is, or in case you can deal with the instability, here's how it works:
* Accessing the Unix side must be done essentially by making ioctls. It's still in the same process, but we need to switch contexts, switch stacks, and potentially switch from 32-bit to 64-bit.
* Once you are in the Unix side, you *cannot* call PE functions. You can still call ntdll exports, since those are in the "kernel". Some Rtl functions are also available, but the actual set is probably not very stable. Possibly the best way to find which ones is to "nm --defined-only -D ntdll.so".
* You also cannot directly call back to the PE side from the Unix side. Nor can you arbitrarily pass function pointers; that will break. You need to go through the ioctl interface. If you need to "call back", you will instead probably want to use a thread that listens for events.
* You can share pointers and NT handles between the PE and Unix side. However, if you want to support wow64, be aware you cannot pass 64-bit pointers back to the PE side.
* PE side can be built with winegcc, but you need to use "-b x86_64-w64-mingw32" or "-b i686-w64-mingw32" to signal to build a real PE DLL. I don't know how stable this is; it was already changed from "-mno-cygwin", which doesn't work anymore.
* Include "wine/unixlib.h" (and link to winecrt0, but winegcc already does this.) This is not a public header, so you'll need to grab it from the Wine tree.
* Before making any calls, call __wine_init_unix_call().
* Unix calls are ioctl-like. On the PE side, do
NTSTATUS ret = WINE_UNIX_CALL(<ioctl index>, <pointer-sized value>);
Usually we define an enumeration for the ioctl, and pass a pointer in the value. The index is arbitrary, but you'll be defining an array of vectors, so you want a 0-based integer. Return value is defined as NTSTATUS (i.e. int) but can be arbitrary.
* The Unix side can be simply built with gcc. You will need to define WINE_UNIX_LIB, and again include wine/unixlib.h. It must be built as a .so with the same name as the corresponding .dll (e.g. test.dll vs test.so), and should be put in /usr/local/lib/wine/x86_64-unix/.
* Unix side of the corresponding vectors is an exported array __wine_unix_call_funcs[]. The signature is in wine/unixlib.h and should hopefully be self-explanatory. The array is indexed by the ioctl index.
Please let me know if you would like further explanation, or if you need help on how to interact between sides, or how to use the relatively undocumented ntdll interfaces.
http://bugs.winehq.org/show_bug.cgi?id=58377
--- Comment #7 from Zeb Figura z.figura12@gmail.com --- (In reply to Zeb Figura from comment #6)
- Unix side of the corresponding vectors is an exported array
__wine_unix_call_funcs[]. The signature is in wine/unixlib.h and should hopefully be self-explanatory. The array is indexed by the ioctl index.
Oh right, forgot about wow64:
* wow64 vectors are a separate exported array __wine_unix_call_wow64_funcs[]. These will receive the arguments passed from 32-bit code. Wine doesn't interpret or convert arguments other than zero-extending the pointer. If you embed pointers or pointer-sized types you have to convert them manually. If you use the same arguments regardless of code, you can just put the same functions in both arrays [but you do still need both exports].
* Also, be aware that some types are different between PE and Unix. Avoid "long". Also, be careful about uint64_t, which doesn't always have the same alignment.
http://bugs.winehq.org/show_bug.cgi?id=58377
--- Comment #8 from Alexandre Julliard julliard@winehq.org --- (In reply to Zeb Figura from comment #6)
- PE side can be built with winegcc, but you need to use "-b
x86_64-w64-mingw32" or "-b i686-w64-mingw32" to signal to build a real PE DLL. I don't know how stable this is; it was already changed from "-mno-cygwin", which doesn't work anymore.
They are different things. "-mno-cygwin" is used when building ELF dlls, and AFAIK still works fine.
http://bugs.winehq.org/show_bug.cgi?id=58377
--- Comment #9 from Zeb Figura z.figura12@gmail.com --- (In reply to Alexandre Julliard from comment #8)
(In reply to Zeb Figura from comment #6)
- PE side can be built with winegcc, but you need to use "-b
x86_64-w64-mingw32" or "-b i686-w64-mingw32" to signal to build a real PE DLL. I don't know how stable this is; it was already changed from "-mno-cygwin", which doesn't work anymore.
They are different things. "-mno-cygwin" is used when building ELF dlls, and AFAIK still works fine.
My mistake, sorry. I assumed that this was the right argument to use; I didn't realize makedep was interpreting it and translating it to -b.