These prefixes are redundant. We're restoring the context from 32-bit code, so %ss = %ds already, and if we're on this side of the code then our %ss = the target %ss. Still, why was the patch written? Before 44fbc018ed, there was a single path to restore contexts, and it looked like this: output( "2:\tpushl 0x94(%%ecx)\n"); /* SegEs */ output( "\tpopl %%es\n" ); output( "\tpushl 0x90(%%ecx)\n"); /* SegFs */ output( "\tpopl %%fs\n" ); output( "\tpushl 0x8c(%%ecx)\n"); /* SegGs */ output( "\tpopl %%gs\n" ); output( "\tmovl 0x9c(%%ecx),%%edi\n"); /* Edi */ output( "\tmovl 0xa0(%%ecx),%%esi\n"); /* Esi */ output( "\tmovl 0xa8(%%ecx),%%edx\n"); /* Edx */ output( "\tmovl 0xa4(%%ecx),%%ebx\n"); /* Ebx */ output( "\tmovl 0xb0(%%ecx),%%eax\n"); /* Eax */ output( "\tmovl 0xb4(%%ecx),%%ebp\n"); /* Ebp */ output( "\tpushl 0xc8(%%ecx)\n"); /* SegSs */ output( "\tpopl %%ss\n" ); output( "\tmovl 0xc4(%%ecx),%%esp\n"); /* Esp */ output( "\tpushl 0xc0(%%ecx)\n"); /* EFlags */ output( "\tpushl 0xbc(%%ecx)\n"); /* SegCs */ output( "\tpushl 0xb8(%%ecx)\n"); /* Eip */ output( "\tpushl 0x98(%%ecx)\n"); /* SegDs */ output( "\tmovl 0xac(%%ecx),%%ecx\n"); /* Ecx */ output( "\tpopl %%ds\n" ); output( "\tiret\n" ); Very simple: we restore most registers (but not %ds), then switch stacks, then push control registers and %ds to the current (target) stack, then pop %ds and iret. This was vulnerable to signal races: + /* As soon as we have switched stacks the context structure could + * be invalid (when signal handlers are executed for example). Copy + * values on the target stack before changing ESP. */ so 44fbc018ed changed the path to a different one: output( "\tpushl 0xc8(%%ecx)\n" ); /* SegSs */ output( "\tpopl %%es\n" ); output( "\tmovl 0xc4(%%ecx),%%eax\n" ); /* Esp */ output( "\tleal -4*4(%%eax),%%eax\n" ); output( "\tmovl 0xc0(%%ecx),%%edx\n" ); /* EFlags */ output( "\t.byte 0x26\n\tmovl %%edx,3*4(%%eax)\n" ); output( "\tmovl 0xbc(%%ecx),%%edx\n" ); /* SegCs */ output( "\t.byte 0x26\n\tmovl %%edx,2*4(%%eax)\n" ); output( "\tmovl 0xb8(%%ecx),%%edx\n" ); /* Eip */ output( "\t.byte 0x26\n\tmovl %%edx,1*4(%%eax)\n" ); output( "\tmovl 0xb0(%%ecx),%%edx\n" ); /* Eax */ output( "\t.byte 0x26\n\tmovl %%edx,0*4(%%eax)\n" ); output( "\tpushl %%es\n" ); output( "\tpushl 0x98(%%ecx)\n" ); /* SegDs */ output(" \tpushl 0x94(%%ecx)\n" ); /* SegEs */ output( "\tpopl %%es\n" ); output( "\tpushl 0x90(%%ecx)\n"); /* SegFs */ output( "\tpopl %%fs\n" ); output( "\tpushl 0x8c(%%ecx)\n"); /* SegGs */ output( "\tpopl %%gs\n" ); output( "\tmovl 0x9c(%%ecx),%%edi\n" ); /* Edi */ output( "\tmovl 0xa0(%%ecx),%%esi\n" ); /* Esi */ output( "\tmovl 0xa4(%%ecx),%%ebx\n" ); /* Ebx */ output( "\tmovl 0xa8(%%ecx),%%edx\n" ); /* Edx */ output( "\tmovl 0xb4(%%ecx),%%ebp\n" ); /* Ebp */ output( "\tmovl 0xac(%%ecx),%%ecx\n" ); /* Ecx */ output( "\tpopl %%ds\n" ); output( "\tpopl %%ss\n" ); output( "\tmovl %%eax,%%esp\n" ); output( "\tpopl %%eax\n" ); output( "\tiret\n" ); That is, we set %es to the target %ss, write control regs onto the target stack using %es, switch to the target stack, then pop + iret. In this case the %es overrides make perfect sense: the target stack might be different from ours (i.e. we are returning to 16-bit code). Evidently this was invalid: + /* Restore the context when the stack segment changes. We can't use + * the same code as above because we do not know if the stack segment + * is 16 or 32 bit, and 'movl' will throw an exception when we try to + * access memory above the limit. */ In 4c8b3f63be1 slackner introduced two different paths. If we need to switch stacks, we use the original path. (I think it's still vulnerable to signal races, but we have no way of preventing those.) Meanwhile the other path can be simplified a bit, since we're already on the target stack: - output( "\tpushl 0xc8(%%ecx)\n" ); /* SegSs */ - output( "\tpopl %%es\n" ); output( "\tmovl 0xc4(%%ecx),%%eax\n" ); /* Esp */ output( "\tleal -4*4(%%eax),%%eax\n" ); output( "\tmovl 0xc0(%%ecx),%%edx\n" ); /* EFlags */ - output( "\t.byte 0x26\n\tmovl %%edx,3*4(%%eax)\n" ); + output( "\t.byte 0x36\n\tmovl %%edx,3*4(%%eax)\n" ); output( "\tmovl 0xbc(%%ecx),%%edx\n" ); /* SegCs */ - output( "\t.byte 0x26\n\tmovl %%edx,2*4(%%eax)\n" ); + output( "\t.byte 0x36\n\tmovl %%edx,2*4(%%eax)\n" ); output( "\tmovl 0xb8(%%ecx),%%edx\n" ); /* Eip */ - output( "\t.byte 0x26\n\tmovl %%edx,1*4(%%eax)\n" ); + output( "\t.byte 0x36\n\tmovl %%edx,1*4(%%eax)\n" ); output( "\tmovl 0xb0(%%ecx),%%edx\n" ); /* Eax */ - output( "\t.byte 0x26\n\tmovl %%edx,0*4(%%eax)\n" ); + output( "\t.byte 0x36\n\tmovl %%edx,0*4(%%eax)\n" ); - output( "\tpushl %%es\n" ); output( "\tpushl 0x98(%%ecx)\n" ); /* SegDs */ @@ -890,11 +889,37 @@ static void build_call_from_regs_x86(void) output( "\tmovl 0xac(%%ecx),%%ecx\n" ); /* Ecx */ output( "\tpopl %%ds\n" ); - output( "\tpopl %%ss\n" ); output( "\tmovl %%eax,%%esp\n" ); output( "\tpopl %%eax\n" ); output( "\tiret\n" ); Sebastian got rid of the setting of %es, and replaced the %es prefixes with %ss prefixes. What I think happened is that he made a subtle mistake—or, well, not a mistake, but a redundancy. %es: was changed to %ss: by analogy, but it's actually not necessary: we're operating on the source stack, and we know the source stack is 32-bit, and we haven't set %ds yet, so %ds == %ss already, and we can use the %implicit %ds prefix. Alexandre presumably saw this in bab6ece63, and silently removed them. My guess is that Sebastian saw that, wasn't sure, but (in the best case) didn't want to submit his fix upstream until he had checked whether it was actually correct, and never got around to checking. (Alternatively, he thought that the %ss should have been retained for clarity, and decided not to try to submit that upstream.)
What is Wine Staging?
Wine Staging is the testing area of winehq.org. It contains bug fixes and features, which have not been integrated into the development branch yet. The idea of Wine Staging is to provide experimental features faster to end users and to give developers the possibility to discuss and improve their patches before they are integrated into the main branch. More information about Wine Staging can also be found on the WineHQ wiki.
Installation
Ready-to-use packages for Wine Staging are available for a variety of Linux distributions and for Mac OS X. Just follow the installation instructions for your operating system.
On most distributions the wine-staging
package is installed to
/opt/wine-staging
, such that multiple Wine versions can be installed in
parallel. If this is the case for your distribution, you will have to type
/opt/wine-staging/bin/wine
instead of just wine
. The same also applies for
other wine-specific programs like winecfg
. To learn more about how to use
Wine Staging, please take a look at the
usage instructions.
Building
Wine Staging is maintained as a set of patches which has to be applied on top of the development branch. In order to build Wine Staging, the first step is to setup a build environment for Wine, including all required dependencies. A lot of information about that is collected in the WineHQ Wiki.
In order to apply all Wine Staging patches it is recommended to use the
patchinstall.sh
utility which takes care of applying all patches in the
correct order. For reference, the possible commandline arguments are:
Usage: ./patchinstall.sh [DESTDIR=path] [--all] [-W patchset] [patchset ...]
Autogenerated script to apply all Wine Staging patches on your Wine
source tree.
Configuration:
DESTDIR=path Specify the path to the wine source tree
--all Select all patches
--force-autoconf Run autoreconf and tools/make_requests after each patch
--help Display this help and exit
--no-autoconf Do not run autoreconf and tools/make_requests
--no-patchlist Do not apply patchlist (needed for 'wine --patches')
--upstream-commit Print the upstream Wine commit SHA1 and exit
--version Show version information and exit
-W patchset Exclude a specific patchset
Backends:
--backend=patch Use regular 'patch' utility to apply patches (default)
--backend=eapply Use 'eapply' to apply patches (Gentoo only)
--backend=epatch Use 'epatch' to apply patches (Gentoo only, deprecated)
--backend=git-am Use 'git am' to apply patches
--backend=git-apply Use 'git apply' to apply patches
--backend=stg Import the patches using stacked git
If you want to apply all patches with the patch
utility, the commandline
should look similar to this:
./patches/patchinstall.sh DESTDIR="/path/to/wine" --all
Before you proceed with the compilation, please make sure that you installed all
additional build dependencies required for the Wine Staging features you are
interested in (check output of ./configure
). More information about building
Wine Staging, optional build dependencies, and hints for packagers are collected
in our Wiki.
Contributing
For information on contributing to Wine-Staging, please see https://wiki.winehq.org/Wine-Staging_Contributing. Note that GitHub pull requests are strongly dispreferred, especially for patches.
Donations
wine-staging is a large set of experimental patches which provide various improvements to WINE, but are not quite suitable for upstreaming. This set of patches has been continuously managed for many years by a small group of volunteers. The way this works is that we often review patches attached to various bug reports found at https://bugs.winehq.org/ which may fix bugs, but may not be quite suitable to be upstreamed due to needing some cleanup or more proper implementation. In the event that this happens, we add the patches to wine-staging instead, and keep them updated and maintained as well as attempt to clean them up to be upstreamed. We also both write and verify patches which fix various bugs that may not have patches, and in turn allow them run better using WINE. This includes testing on various hardware, games, and applications.
Any expenses for applications, games, or hardware which we do not own comes out of pocket. In order to alleviate these expenses, we are now accepting donations. This in turn allows us to continue to perform testing, provide fixes, and get them upstreamed, ultimately aiming to provide a better experience for all WINE users. All of our work is provided publicly for free and can be found at https://github.com/wine-staging/wine-staging. We do not expect to be paid for any of the work provided, nor will donators receive any special benefits or compensation.
Donations are recieved through Patreon. Anyone interested may donate here: