https://bugs.winehq.org/show_bug.cgi?id=38780
Bug ID: 38780 Summary: AArch64 platforms: register X18 must remain reserved for Wine to run 64-bit ARM Windows applications (Distro aarch64 toolchains need '-ffixed-x18' default, loader/libc/userland) Product: Wine Version: 1.7.45 Hardware: aarch64 OS: Linux Status: NEW Severity: normal Priority: P2 Component: -unknown Assignee: wine-bugs@winehq.org Reporter: focht@gmx.net Distribution: ---
Hello folks,
split off from bug 38719 ("64-bit ARM Windows applications from Windows SDK for Windows 10 crash when accessing TEB/PEB members (AArch64 platform specific register X18 must be reserved for TEB)")
Resolution is 'upstream' here, the Wine part is bug 38719
http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.p...
Chapter 5 "THE BASE PROCEDURE CALL STANDARD"
--- quote --- The role of register r18 is platform specific. If a platform ABI has need of a dedicated general purpose register to carry interprocedural state (for example, the thread context) then it should use this register for that purpose. If the platform ABI has no such requirements, then it should use r18 as an additional temporary register. The platform ABI specification must document the usage for this register.
Note
Software developers creating platform independent code are advised to avoid using r18 if at all possible. Most compilers provide a mechanism to prevent specific registers from being used for general allocation; portable hand-coded assembler should avoid it entirely. It should not be assumed that treating the register as callee saved will be sufficient to satisfy the requirements of the platform. Virtualization code must, of course, treat the register as they would any other resource provided to the virtual machine. --- quote ---
Regards
https://bugs.winehq.org/show_bug.cgi?id=38780
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- Keywords| |download URL| |http://go.microsoft.com/fwl | |ink/p/?LinkId=536682 CC| |nerv@dawncrow.de See Also| |https://bugs.winehq.org/sho | |w_bug.cgi?id=38719
https://bugs.winehq.org/show_bug.cgi?id=38780
--- Comment #1 from Anastasius Focht focht@gmx.net --- Hello folks,
upstream tickets shall be created in major distro bug trackers. Politely explain the situation and ask for their cooperation in resolving the problem.
Add links to the upstream tickets here as needed.
Regards
https://bugs.winehq.org/show_bug.cgi?id=38780
André H. nerv@dawncrow.de changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|NEW |RESOLVED Resolution|--- |UPSTREAM
--- Comment #2 from André H. nerv@dawncrow.de --- marking upstream
https://bugs.winehq.org/show_bug.cgi?id=38780
--- Comment #3 from André H. nerv@dawncrow.de --- (In reply to Anastasius Focht from comment #5 from bug 38719)
No special treatment, it's really used as general purpose register.
The _dl_tlsdesc* X18 references result from NSAVEXREGPAIRS macro usage:
https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/aarch64/dl-tlsdesc. S;h=be9b9b394c1aea8f3dfc1f0a9c4c32e002004822;hb=HEAD
First we should note that x18 is either the "platform register" or a temporary register. I think the macros in the linked code are fine, they just save and restore x18 and others (push/pop). The problem really is the compiler here as already mentioned by you.
https://bugs.winehq.org/show_bug.cgi?id=38780
--- Comment #4 from André H. nerv@dawncrow.de --- It seems to me that the key is to configure gcc with: --with-specs=%{!ffixed-x18:-ffixed-x18} Can someone confirm? So that we can guide people how to do it...
https://bugs.winehq.org/show_bug.cgi?id=38780
--- Comment #5 from Anastasius Focht focht@gmx.net --- Hello André,
--- quote --- It seems to me that the key is to configure gcc with: --with-specs=%{!ffixed-x18:-ffixed-x18} Can someone confirm? So that we can guide people how to do it... --- quote ---
that would be one way.
Ultimately it's the distro gcc package maintainer to decide how to implement it - not the end users.
For Fedora (the distro I use) the contact would be Jakub Jelinek
https://admin.fedoraproject.org/pkgdb/package/gcc/
Gcc package repository:
http://pkgs.fedoraproject.org/cgit/gcc.git/tree/
The .spec file to add the option for '%ifarch aarch64':
http://pkgs.fedoraproject.org/cgit/gcc.git/tree/gcc.spec
But ... I've had a look at the aarch64 config for gcc and noticed this:
https://github.com/gcc-mirror/gcc/blob/master/gcc/config/aarch64/aarch64.h#L...
--- snip --- #define STATIC_CHAIN_REGNUM R18_REGNUM --- snip ---
Whoops. To avoid multiple files changed/patched for this "feature" (gcc arch config header and the .spec file which is distro/build system specific anyway) one could put a small patch together which only affects one file:
gcc/config/aarch64/aarch64.h
'ffixed-x18' can also be realized by modifying FIXED_REGISTERS, CALL_USED_REGISTERS register allocator bitmaps (1 = exclude from general use)
https://github.com/gcc-mirror/gcc/blob/master/gcc/config/aarch64/aarch64.h#L...
Regards
https://bugs.winehq.org/show_bug.cgi?id=38780
--- Comment #6 from André H. nerv@dawncrow.de --- Created attachment 51808 --> https://bugs.winehq.org/attachment.cgi?id=51808 gcc patch
Thanks for the guidance!
Something like that? Is R17 a good choice? Should that simply be upstreamed? Further links: https://gcc.gnu.org/ml/gcc/2015-06/msg00046.html
--snip-- I suspect that using one of the IP regs is not brilliant; there are some concerns around the use of trampolines and closures that could lead to problems if you do. Ideally, you just want a call-clobbered register that's not used for parameter passing (unfortunately on ARM the only such register is r12). In AArch64 there are plenty of registers in that category you can chose from. --snip--
Ok, so R17 is bad, what about something from R9-R15?
https://bugs.winehq.org/show_bug.cgi?id=38780
Austin English austinenglish@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|RESOLVED |CLOSED
--- Comment #7 from Austin English austinenglish@gmail.com --- Closing.
https://bugs.winehq.org/show_bug.cgi?id=38780
--- Comment #8 from André H. nerv@dawncrow.de --- (In reply to Austin English from comment #7)
Closing.
I thought we only close "upstream" bugs here when they are fixed upstream?
https://bugs.winehq.org/show_bug.cgi?id=38780
--- Comment #9 from Anastasius Focht focht@gmx.net --- Hello André
--- quote --- I thought we only close "upstream" bugs here when they are fixed upstream? --- quote ---
this is a grey area because various bugs reported at upstream are also suffering "bitrot" (no one bothers). They might block the Wine bug indefinitely from closure then.
The definition of "upstream" is hard here. All FOSS projects that provide aarch64 images of their distros? The major five ones? Everyone's favourite? Technically we will likely never see this happen rolled out on large scale because most distro projects simply don't bother with this.
Regards
https://bugs.winehq.org/show_bug.cgi?id=38780
--- Comment #10 from Austin English austinenglish@gmail.com --- (In reply to André H. from comment #8)
(In reply to Austin English from comment #7)
Closing.
I thought we only close "upstream" bugs here when they are fixed upstream?
Didn't mean to choose this one, but I'll leave it to you two to decide
https://bugs.winehq.org/show_bug.cgi?id=38780
André H. nerv@dawncrow.de changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|CLOSED |REOPENED Resolution|NOTOURBUG |---
--- Comment #11 from André H. nerv@dawncrow.de --- I'd say reopen until at least one major distro ships it as needed, because at some point users will ask about the problem and I don't want to point them on a closed bug report then.
https://bugs.winehq.org/show_bug.cgi?id=38780
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|REOPENED |NEW Summary|AArch64 platforms: register |AArch64 platforms: register |X18 must remain reserved |X18 (TEB) must remain |for Wine to run 64-bit ARM |reserved for Wine to run |Windows applications |64-bit ARM Windows |(Distro aarch64 toolchains |applications (Distro |need '-ffixed-x18' default, |aarch64 toolchains need |loader/libc/userland) |'-ffixed-x18' default, | |loader/libc/userland)
--- Comment #12 from Anastasius Focht focht@gmx.net --- Hello folks,
setting status again to 'NEW'.
It's also documented now in Microsoft docs:
https://docs.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions?vie...
--- quote --- ... Integer registers
The AArch64 architecture supports 32 integer registers, summarized below:
Register Volatile? Role
x0 Volatile Parameter/scratch register 1, result register x1-x7 Volatile Parameter/scratch register 2-8 x8-x15 Volatile Scratch registers x16-x17 Volatile Intra-procedure-call scratch registers x18 Non-volatile Platform register: in kernel mode, points to KPCR for the current processor; in user mode, points to TEB x19-x28 Non-volatile Scratch registers x29/fp Non-volatile Frame pointer x30/lr Non-volatile Link registers --- quote ---
Regards
https://bugs.winehq.org/show_bug.cgi?id=38780
Zebediah Figura z.figura12@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |z.figura12@gmail.com
--- Comment #13 from Zebediah Figura z.figura12@gmail.com --- Is this something we could fix entirely on the Wine side? I'm not an ARM enthusiast (yet), but I guess we could do one of two things:
(1) unconditionally save and restore x18 in the function prologue, and also restore it around WINAPI callbacks; (2) save and restore it around all inferior function calls.
Both would require modification to GCC, I think, but maybe would be more feasible than trying to get distributions to compile everything with -ffixed-x18?
https://bugs.winehq.org/show_bug.cgi?id=38780
André H. nerv@dawncrow.de changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |martin@martin.st
--- Comment #14 from André H. nerv@dawncrow.de --- (In reply to Zebediah Figura from comment #13)
Is this something we could fix entirely on the Wine side? I'm not an ARM enthusiast (yet), but I guess we could do one of two things:
(1) unconditionally save and restore x18 in the function prologue, and also restore it around WINAPI callbacks; (2) save and restore it around all inferior function calls.
Both would require modification to GCC, I think, but maybe would be more feasible than trying to get distributions to compile everything with -ffixed-x18?
Well, rather in clang then. Martin? :) Can we add it to the aarch64 ms_abi attribute (maybe only on non-windows targets)?
https://bugs.winehq.org/show_bug.cgi?id=38780
--- Comment #15 from Martin Storsjö martin@martin.st --- (In reply to André H. from comment #14)
(In reply to Zebediah Figura from comment #13)
Is this something we could fix entirely on the Wine side? I'm not an ARM enthusiast (yet), but I guess we could do one of two things:
(1) unconditionally save and restore x18 in the function prologue, and also restore it around WINAPI callbacks; (2) save and restore it around all inferior function calls.
Both would require modification to GCC, I think, but maybe would be more feasible than trying to get distributions to compile everything with -ffixed-x18?
Well, rather in clang then. Martin? :) Can we add it to the aarch64 ms_abi attribute (maybe only on non-windows targets)?
I guess it could be doable to back it up in the prologue and restore it the epilogue in functions on non-windows that are marked with the ms_abi attribute. For restoring/setting it up around WINAPI callbacks, where would the compiler get the value to set into x18? I'm not sure how far in the compiler WINAPI is visible on non-i386 platforms where stdcall is a no-op. I don't quite follow what was suggested to be done in point (2) above though.
https://bugs.winehq.org/show_bug.cgi?id=38780
--- Comment #16 from Zebediah Figura z.figura12@gmail.com --- (In reply to Martin Storsjö from comment #15)
I guess it could be doable to back it up in the prologue and restore it the epilogue in functions on non-windows that are marked with the ms_abi attribute. For restoring/setting it up around WINAPI callbacks, where would the compiler get the value to set into x18?
From the spilled location?
I'm not sure how far in the compiler WINAPI is visible on non-i386 platforms where stdcall is a no-op.
Well, it'd be part of the ms_abi attribute, presumably.
I don't quite follow what was suggested to be done in point (2) above though.
Essentially, to treat it as a caller-saved register (even though it's not being used as a scratch register).
https://bugs.winehq.org/show_bug.cgi?id=38780
--- Comment #17 from Martin Storsjö martin@martin.st --- (In reply to Zebediah Figura from comment #16)
(In reply to Martin Storsjö from comment #15)
I guess it could be doable to back it up in the prologue and restore it the epilogue in functions on non-windows that are marked with the ms_abi attribute. For restoring/setting it up around WINAPI callbacks, where would the compiler get the value to set into x18?
From the spilled location?
When the windows code calls a wine function (compiled for linux, with ms_abi attribute on the entry point), this prologue can indeed treat it as a callee-save register and back it up.
This function then goes on to call other host environment functions (glibc etc) which clobber x18, and a number of other wine-internal functions, which don't have the ms_abi attribute set, which don't back up and restore x18 (which could be garbage at this point anyway). Deep in this call stack, some function calls a WINAPI callback. How does that nested context find what the real x18 value was on entry into the wine code, several stack frames deeper?
https://bugs.winehq.org/show_bug.cgi?id=38780
--- Comment #18 from Zebediah Figura z.figura12@gmail.com --- (In reply to Martin Storsjö from comment #17)
(In reply to Zebediah Figura from comment #16)
(In reply to Martin Storsjö from comment #15)
I guess it could be doable to back it up in the prologue and restore it the epilogue in functions on non-windows that are marked with the ms_abi attribute. For restoring/setting it up around WINAPI callbacks, where would the compiler get the value to set into x18?
From the spilled location?
When the windows code calls a wine function (compiled for linux, with ms_abi attribute on the entry point), this prologue can indeed treat it as a callee-save register and back it up.
This function then goes on to call other host environment functions (glibc etc) which clobber x18, and a number of other wine-internal functions, which don't have the ms_abi attribute set, which don't back up and restore x18 (which could be garbage at this point anyway). Deep in this call stack, some function calls a WINAPI callback. How does that nested context find what the real x18 value was on entry into the wine code, several stack frames deeper?
Ah, yes, that would sort of rule out that approach, then.
https://bugs.winehq.org/show_bug.cgi?id=38780
--- Comment #19 from Martin Storsjö martin@martin.st --- (In reply to Zebediah Figura from comment #18)
(In reply to Martin Storsjö from comment #17)
(In reply to Zebediah Figura from comment #16)
(In reply to Martin Storsjö from comment #15)
I guess it could be doable to back it up in the prologue and restore it the epilogue in functions on non-windows that are marked with the ms_abi attribute. For restoring/setting it up around WINAPI callbacks, where would the compiler get the value to set into x18?
From the spilled location?
When the windows code calls a wine function (compiled for linux, with ms_abi attribute on the entry point), this prologue can indeed treat it as a callee-save register and back it up.
This function then goes on to call other host environment functions (glibc etc) which clobber x18, and a number of other wine-internal functions, which don't have the ms_abi attribute set, which don't back up and restore x18 (which could be garbage at this point anyway). Deep in this call stack, some function calls a WINAPI callback. How does that nested context find what the real x18 value was on entry into the wine code, several stack frames deeper?
Ah, yes, that would sort of rule out that approach, then.
Currently I'm running with this patch: https://source.winehq.org/patches/data/137759
This pretty much gets the same effect as the suggested compiler handling for prologues/epilogues, but without compiler support - but it doesn't fix callbacks either. This (together with https://source.winehq.org/patches/data/135165) has been a good enough workaround for me so far though.
https://bugs.winehq.org/show_bug.cgi?id=38780
--- Comment #20 from Zebediah Figura z.figura12@gmail.com --- (In reply to Martin Storsjö from comment #19)
Currently I'm running with this patch: https://source.winehq.org/patches/data/137759
This pretty much gets the same effect as the suggested compiler handling for prologues/epilogues, but without compiler support - but it doesn't fix callbacks either. This (together with https://source.winehq.org/patches/data/135165) has been a good enough workaround for me so far though.
Sure, I'd just like to see this fixed in a generic way.
Is there any obvious infeasibility about my proposal #2? It's weird, but seems plausible, and maybe wouldn't even be that hard, if we can leverage the same sort of code that -fcall-used-reg uses [disclaimer: I am not a compiler enthusiast yet, either]. Plus it means we can use inline TEB access in Wine code :-)
https://bugs.winehq.org/show_bug.cgi?id=38780
--- Comment #21 from Martin Storsjö martin@martin.st --- (In reply to Zebediah Figura from comment #20)
(In reply to Martin Storsjö from comment #19)
Currently I'm running with this patch: https://source.winehq.org/patches/data/137759
This pretty much gets the same effect as the suggested compiler handling for prologues/epilogues, but without compiler support - but it doesn't fix callbacks either. This (together with https://source.winehq.org/patches/data/135165) has been a good enough workaround for me so far though.
Sure, I'd just like to see this fixed in a generic way.
Is there any obvious infeasibility about my proposal #2? It's weird, but seems plausible, and maybe wouldn't even be that hard, if we can leverage the same sort of code that -fcall-used-reg uses [disclaimer: I am not a compiler enthusiast yet, either]. Plus it means we can use inline TEB access in Wine code :-)
Ah, with the reference to -fcall-used-reg, I understand what you mean. Hmm, I'll have to think about it and poke around and see what's possible.
It turns out that clang doesn't support this flag at all so far, but I'll see if it is possible to do something to the same effect in LLVM's calling convention handling.
https://bugs.winehq.org/show_bug.cgi?id=38780
--- Comment #22 from Martin Storsjö martin@martin.st --- (In reply to Zebediah Figura from comment #16)
Essentially, to treat it as a caller-saved register (even though it's not being used as a scratch register).
After poking around a bit in the AArch64 target in llvm, this doesn't seem all that easy, necessarily, but I might of course be wrong.
To achieve what's wanted here (having x18 correct when calling callback functions from anywhere within wine code), the compiler would need to back up x18 before every single function call (which might be to a glibc function which could clobber x18), and restore it immediately afterwards on return. That's not how normal caller saved registers are used though; the register allocator (primarily) moves anything that needs to be stored across function calls into a callee saved register instead and uses it from there; it doesn't move it back into the caller save register unless it needs to.
So it's of course not impossible, but so far I didn't find any existing mechanism where I could just add x18 to the list and have it all work out automatically.
https://bugs.winehq.org/show_bug.cgi?id=38780
Tim Northover t.p.northover@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |t.p.northover@gmail.com
https://bugs.winehq.org/show_bug.cgi?id=38780
Martin Storsjö martin@martin.st changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |leslie_alistair@hotmail.com
https://bugs.winehq.org/show_bug.cgi?id=38780
--- Comment #23 from Martin Storsjö martin@martin.st --- Created attachment 64286 --> https://bugs.winehq.org/attachment.cgi?id=64286 Patchset for practically working around the issue
As a full compiler based workaround isn't available yet (and isn't entirely trivial, and in addition to implementing it, could be controversial to be accepted upstream - it has been discussed upstream in llvm at http://lists.llvm.org/pipermail/llvm-dev/2019-April/131978.html), I'd suggest adding the attached patchset to Wine Staging at least.
Both patches have been sent to the list before, but haven't been picked up back then.
The first patch is correct and shouldn't have any drawbacks, and is a partial solution (but probably wasn't picked up as it isn't a full solution). The second patch is less clean but an effective workaround for what remains to be fixed after the first patch. (The third patch is just regenerating configure.)
https://bugs.winehq.org/show_bug.cgi?id=38780
Alistair Leslie-Hughes leslie_alistair@hotmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Keywords| |patch
https://bugs.winehq.org/show_bug.cgi?id=38780
Alistair Leslie-Hughes leslie_alistair@hotmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Staged patchset| |https://github.com/wine-sta | |ging/wine-staging/tree/mast | |er/patches/ntdll-aarch-TEB Status|NEW |STAGED
https://bugs.winehq.org/show_bug.cgi?id=38780
Brendan Shanks bshanks@codeweavers.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |bshanks@codeweavers.com
--- Comment #24 from Brendan Shanks bshanks@codeweavers.com --- Just something interesting: Android's arm64 ABI also reserves x18 for the LLVM ShadowCallStack security feature, hence this kernel patch to ensure the vDSO reserves x18: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/ar...
https://developer.android.com/ndk/guides/abis#arm64-v8a
https://bugs.winehq.org/show_bug.cgi?id=38780
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- URL|http://go.microsoft.com/fwl |https://web.archive.org/web |ink/p/?LinkId=536682 |/20150519080735/http://down | |load.microsoft.com/download | |/9/1/D/91DB6FE6-93B7-413E-9 | |1E2-E6FEA7355342/standalone | |sdk/sdksetup.exe
https://bugs.winehq.org/show_bug.cgi?id=38780
--- Comment #25 from Martin Storsjö martin@martin.st --- FWIW, the patches in wine-staging for this issue aren't really needed any longer. There's been lots of work ongoing in wine (both the PE transition, but also by switching to the kernel stack for syscalls) that has made the issue go away more or less; with Wine 6.14 at least, the issue isn't present for me any longer, and both PE builds and full-ELF builds run fine for my set of test programs at least. Additionally, Clang (since 11.0) has got some support for automatically backing up and restoring x18 in the ELF functions that implement a windows calling convention (i.e. the ones in the boundary interface).
Therefore, I'd suggest to remove the patches from wine-staging/patches/ntdll-aarch-TEB; things work without them, and they're probably not helping anything any longer.
https://bugs.winehq.org/show_bug.cgi?id=38780
--- Comment #26 from Martin Storsjö martin@martin.st --- To expand on the matter a bit:
In the current state of things (current master around 6.14), things generally seem to work pretty nicely.
PE modules built in Wine still link against ntdll.dll's NtCurrentTeb(), and that doesn't exist on actual Windows. This means that e.g. test executables built in Wine don't run on real Windows.
It's trivial to add a proper inline version of NtCurrentTeb() in winnt.h, e.g. like this:
+#elif defined(__aarch64__) && defined(__MINGW32__) && !defined(_NTSYSTEM_) +static FORCEINLINE struct _TEB * WINAPI NtCurrentTeb(void) +{ + struct _TEB *teb; + __asm__("mov %0, x18" : "=r" (teb)); + return teb; +}
However this still fails when there's ELF code involved, e.g. an ELF winemenubuilder.exe can call a system API which clobbers x18 and then go on and call a PE DLL which expects to have a pristine x18 in place.
So for all things that are converted entirely to PE, things work great, and for cases Where PE modules call ELF modules, things work great. Things don't work when ELF modules call PE modules.
So the non-inlined NtCurrentTeb() manages to avoid many issues relating to this in practice, but it would be great to use an inline NtCurrentTeb() for test executables at least.
https://bugs.winehq.org/show_bug.cgi?id=38780
Alistair Leslie-Hughes leslie_alistair@hotmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|STAGED |NEW Staged patchset|https://github.com/wine-sta | |ging/wine-staging/tree/mast | |er/patches/ntdll-aarch-TEB |
--- Comment #27 from Alistair Leslie-Hughes leslie_alistair@hotmail.com --- Staging patch has been removed.
https://bugs.winehq.org/show_bug.cgi?id=38780
Fabian Maurer dark.shadow4@web.de changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |dark.shadow4@web.de
--- Comment #28 from Fabian Maurer dark.shadow4@web.de --- What's the state as of wine-8.10?
https://bugs.winehq.org/show_bug.cgi?id=38780
--- Comment #29 from Martin Storsjö martin@martin.st --- (In reply to Fabian Maurer from comment #28)
What's the state as of wine-8.10?
IMO, this bug can be closed - it's been practically fixed for a couple years now.
https://bugs.winehq.org/show_bug.cgi?id=38780
André Z. nerv@dawncrow.de changed:
What |Removed |Added ---------------------------------------------------------------------------- Resolution|--- |FIXED Status|NEW |RESOLVED
--- Comment #30 from André Z. nerv@dawncrow.de --- (In reply to Martin Storsjö from comment #29)
(In reply to Fabian Maurer from comment #28)
What's the state as of wine-8.10?
IMO, this bug can be closed - it's been practically fixed for a couple years now.
marking as fixed
https://bugs.winehq.org/show_bug.cgi?id=38780
Alexandre Julliard julliard@winehq.org changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|RESOLVED |CLOSED
--- Comment #31 from Alexandre Julliard julliard@winehq.org --- Closing bugs fixed in 9.0-rc5.