Hello, some legacy applications depend on the carry flag state after calling system functions. I've noticed that certain apps work correctly when using Wine installed from packages, but fail when Wine is built from sources. After investigating, I found that Wine from Debian packages is compiled with certain flags that stabilize ESP at the end of system function calls (e.g., sub ESP, 0x10), which, as a side effect, clears the carry flag, making the application happy. I tried using fno-omit-frame-pointer, but it generates lea instructions, which don't impact the carry flag.
Has anyone else encountered same behavior? How frequently do older applications rely on the carry flag after system function calls? Also, which specific flags are used to compile the Wine version available in Debian packages?
I don't know about anything except possibly the answer to your last question . You can get the sources for the binaries you have from e.g. https://packages.debian.org/sid/wine (Or the equivalent in debian testing etc) Look at the side panel on the right - typically they rename the upstream tar ball to *.orig.*, And the debian-specific build machineries in *.debian.* . The build machinery files should unpack to a debian directory which is typically to be housed inside the source's top level directory to be used, and consists of some shell-script -like files with CFLAGS, etc.
Or, instead of downloading manually from debian 's server like above, if you are on the debian system itself, you can use `apt-get source ...` to get at the source files corresponding to your binaries. Read about "apt-get source ...".
The compiler flags etc should be somewhere in the debian/ directory once unpacked, either way.
On Tuesday 24 September 2024 at 04:39:32 BST, robert.ayrapetyan@gmail.com wrote:
Hello, some legacy applications depend on the carry flag state after calling system functions. I've noticed that certain apps work correctly when using Wine installed from packages, but fail when Wine is built from sources. After investigating, I found that Wine from Debian packages is compiled with certain flags that stabilize ESP at the end of system function calls (e.g., sub ESP, 0x10), which, as a side effect, clears the carry flag, making the application happy. I tried using fno-omit-frame-pointer, but it generates lea instructions, which don't impact the carry flag.
Has anyone else encountered same behavior? How frequently do older applications rely on the carry flag after system function calls? Also, which specific flags are used to compile the Wine version available in Debian packages?
I was not able to find any configure or CFLAGS definitions at your links... Also I thought winehq provides builds which differ from Debian official builds. However I found compile flags in the output here: https://build.opensuse.org/package/live_build_log/Emulators:Wine:Debian/wine... (which is referenced from winehq). Options are similar to mine, but the stack frame cleanup code differs (lea in the manually built Wine vs sub in the packaged version), likely due to different compiler versions. It seems the old game app in question was compiled with some exotic compiler, as I found explicit "clc" instructions in all function call wrapper epilogues, except for one, which led to the issue. In any case relying on the Carry flag seems wrong since it's fragile and can be easily influenced by various compiler options. Assuming it's an app bug, closing this thread.
What app is it, is it a 16bit program?
Also, what exactly does system function call mean? Is it one affected function or multiple?
Does it work reliably on windows?
IMHO it wouldn't hurt to open a bug report, be it just for others who have the same issue. You could try to come up with a patch, either as workaround or possibly as upstream-able change.
Regards, Fabian Maurer
It was a 32-bit executable of the Polish version of the Galador game (The Prince and The Coward). It contains wrappers around calls to kernel32 functions (e.g. _llseek). The very last instruction in most of the wrappers is clc, but not in all of them. One of them, wrapping _llseek, contained no clc instruction, causing random behaviour, when different versions of wine behaved differently depending on how the Carry flag was set based on a side effect of a stack frame cleanup code. At least in Windows XP it didn't work because it uses instructions which always set the Carry flag to true in the epilog of the SetFilePointer function. I don't think this is something we can fix in wine, if the application relies on the state of the Carry flag and doesn't explicitly clear it in case of success - it's a bug of that app, which may accidentally work in some specific Windows versions. I can provide a patch for this particular game which NOPs JB call after _llseek, but I don't think it's appropriate for winehq..
On Wed, Sep 25, 2024 at 10:16 AM Fabian Maurer dark.shadow4@web.de wrote:
What app is it, is it a 16bit program?
Also, what exactly does system function call mean? Is it one affected function or multiple?
Does it work reliably on windows?
IMHO it wouldn't hurt to open a bug report, be it just for others who have the same issue. You could try to come up with a patch, either as workaround or possibly as upstream-able change.
Regards, Fabian Maurer
On 9/25/24 12:27, Robert Ayrapetyan wrote:
It was a 32-bit executable of the Polish version of the Galador game (The Prince and The Coward). It contains wrappers around calls to kernel32 functions (e.g. _llseek). The very last instruction in most of the wrappers is clc, but not in all of them. One of them, wrapping _llseek, contained no clc instruction, causing random behaviour, when different versions of wine behaved differently depending on how the Carry flag was set based on a side effect of a stack frame cleanup code. At least in Windows XP it didn't work because it uses instructions which always set the Carry flag to true in the epilog of the SetFilePointer function. I don't think this is something we can fix in wine, if the application relies on the state of the Carry flag and doesn't explicitly clear it in case of success - it's a bug of that app, which may accidentally work in some specific Windows versions. I can provide a patch for this particular game which NOPs JB call after _llseek, but I don't think it's appropriate for winehq..
If this is just one msvcrt._llseek() and the behaviour is consistent on Windows (e. g., carry flags always ends up reflecting the error status), maybe an asm wrapper for this function in msvcrt is an option?