I am using WINE (on 64-bit Linux) to run a 32-bit Windows application which loads a DLL (LoadLibrary
). I would like to re-write the DLL and compile it with winegcc
/winebuild
for that environment, without modifications to the original program. I am not interested in supporting 32-bit Linux hosts but the DLL itself needs to target 32-bit Windows as, as noted in the answer to another question, it is required for process interoperability:
On 64-bit Windows, a 64-bit process cannot load a 32-bit dynamic-link library (DLL).
Additionally, a 32-bit process cannot load a 64-bit DLL.
However, when building for 32-bit Windows, winegcc
(using the -m32
flag) produces an x86 "DLL-wrapping" shared object which links against other 32-bit versions of Linux libraries (e.g. libwinecrt0.a
). This is not the desired behavior as it requires the Linux host to have those 32-bit libraries which hinders easy distribution of the DLL. Furthermore, trying to manually link against the 64-bit versions of the libraries is prevented by the linker itself with the expected error:
/usr/bin/ld: relocatable linking with relocations from
format elf64-x86-64 to format elf32-i386 is not supported
Now, I understand that there is an inherent difference in ISA (even ABI?) between x86 and amd64/x86_64 causing 32-bit Windows applications to be unable to load 64-bit DLLs and the GCC linker to refuse linking 32-bit Linux shared objects to 64-bit libraries. This incompatibility is the reason why modern CPUs are able to be placed in an "x86 mode", allowing 32-bit code to run. That mode switching, in turn, requiring privileges that regular userspace programs do not have, means that having an x86_64-to-x86 compatibility layer in the libraries is not possible (see Why cannot 64-bit shared libraries be used by 32-bit code?); is that right? If not, how would it be done?
Having said that, I notice that 32-bit Windows applications are able to be run by 64-bit WINE without (AFAIK) requiring any 32-bit Linux libraries. Consequently, I guess that WINE performs that through its re-implementation of WoW64 and, by doing so, contains any "32-bit-ness" within the WINE environment. Is there then a way for me to exploit this in my DLL?
The point I am making here is that this is not a regular "calling 64-bit libraries from 32-bit code" problem, as it involves one (even two?) extra layer(s) on top of the OS, which I would like to somehow exploit. The options I have considered, but which do not meet all requirements, are:
- build the DLL with
winegcc -m32
makesLoadLibrary
succeed but links against 32-bit Linux libraries - build the DLL with
winegcc -m64
links against 64-bit Linux libraries but makes it impossible toLoadLibrary
from 32-bit Windows - build the DLL with MinGW (or any Windows-native compiler) leverages WoW64 so that no 32-bit Linux library is required but prevents me from using Linux code at all, which was the whole point of re-writing the library in the first place
What other options do I have? Wrapper code? Particular syscalls? Specific functionality within WINE? ...?