https://bugs.winehq.org/show_bug.cgi?id=48291
Bug ID: 48291 Summary: Detroit: Become Human crashes on launch Product: Wine Version: 5.0-rc1 Hardware: x86 OS: Linux Status: UNCONFIRMED Severity: normal Priority: P2 Component: -unknown Assignee: wine-bugs@winehq.org Reporter: sashok.olen@gmail.com Distribution: ---
Created attachment 65990 --> https://bugs.winehq.org/attachment.cgi?id=65990 backtrace
For now I've only uploaded a backtrace, but it's a bit unusual: 0x0000000000000000: -- no code accessible -- Let me know if you need anything else.
https://bugs.winehq.org/show_bug.cgi?id=48291
Alexandr Oleynikov sashok.olen@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |sashok.olen@gmail.com
--- Comment #1 from Alexandr Oleynikov sashok.olen@gmail.com --- Created attachment 65991 --> https://bugs.winehq.org/attachment.cgi?id=65991 +relay,+seh
+relay,+seh could be useful too i guess
https://bugs.winehq.org/show_bug.cgi?id=48291
--- Comment #2 from Alexandr Oleynikov sashok.olen@gmail.com --- Installing native vcrun2015 seems to fix at least the crash (game still doesn't launch unfortunately).
https://bugs.winehq.org/show_bug.cgi?id=48291
Alexandr Oleynikov sashok.olen@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Hardware|x86 |x86-64
https://bugs.winehq.org/show_bug.cgi?id=48291
maniikarabera@protonmail.ch changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |maniikarabera@protonmail.ch
https://bugs.winehq.org/show_bug.cgi?id=48291
Paul Gofman gofmanp@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |gofmanp@gmail.com
--- Comment #3 from Paul Gofman gofmanp@gmail.com --- (In reply to Alexandr Oleynikov from comment #2)
Installing native vcrun2015 seems to fix at least the crash (game still doesn't launch unfortunately).
The initial crash is likely because it could not find mfc140.dll which it loaded through LoadLibrary(), which you probably fixed with native vcrun2015.
Could you please give any details and log how it does not launch now?
https://bugs.winehq.org/show_bug.cgi?id=48291
--- Comment #4 from Alexandr Oleynikov sashok.olen@gmail.com --- Created attachment 66013 --> https://bugs.winehq.org/attachment.cgi?id=66013 +DetroitBecomeHuman.exe:+relay,+DetroitBecomeHuman.exe:+seh
Huh, so Wine doesn't implement mfc140.dll? Ok then. And right now, it basically just gets stuck. In the logs with +relay and +seh channels, I see that it's just spamming 0139:Call ntdll.NtDelayExecution(00000000,0185f538) ret=7109bcdc 0139:Ret ntdll.NtDelayExecution() retval=00000000 ret=7109bcdc 0139:Ret KERNEL32.Sleep() retval=00000000 ret=00e93ec4 0139:Call KERNEL32.Sleep(000001f4) ret=00e93ec4 over and over again Here's a full +relay,+seh log.
https://bugs.winehq.org/show_bug.cgi?id=48291
--- Comment #5 from Paul Gofman gofmanp@gmail.com --- The minimum system requirements I could find involve Windows 10, and the main thread exits right after GetVersionInfo(), so I wonder if setting Win version to 10 in winecfg change anything?
https://bugs.winehq.org/show_bug.cgi?id=48291
--- Comment #6 from Alexandr Oleynikov sashok.olen@gmail.com --- It's actually already set to 10 for every app in the prefix except for EGS, as the latter only launches with Win version set to 7.
https://bugs.winehq.org/show_bug.cgi?id=48291
--- Comment #7 from Alexandr Oleynikov sashok.olen@gmail.com --- And there are also reports online that it works just fine on Windows 7 after installing vcrun2015.
https://bugs.winehq.org/show_bug.cgi?id=48291
--- Comment #8 from Paul Gofman gofmanp@gmail.com --- (In reply to Alexandr Oleynikov from comment #6)
It's actually already set to 10 for every app in the prefix except for EGS, as the latter only launches with Win version set to 7.
Then maybe you can test it in a clean Wineprefix (with winetricks vcrun2015), with clean game install, without any custom patches applied on top of Wine, without changing default Win version from 7, and if it still does not start provide the same logs from such start? It is also worth giving it a try with Wine Staging.
Please don't use custom settings / workarounds when providing test results, or, if some of such settings helped you to bypass some problems, please clearly describe what has been altered.
I am not sure that the reason can be guessed from logs in this case, but we could try. Without following the requirements above looking into those logs most often turns into just the waste of time.
https://bugs.winehq.org/show_bug.cgi?id=48291
--- Comment #9 from Alexandr Oleynikov sashok.olen@gmail.com --- Oh, but the first log I attached to this issue was made without installing vcrun2015. Should have made it more clear sorry. I'll make another clean one but this time with version set to 7. Should note that I will still need to install native dotnet as EGS launcher just doesn't install without it, however, I didn't notice the game itself loading it?
https://bugs.winehq.org/show_bug.cgi?id=48291
--- Comment #10 from Alexandr Oleynikov sashok.olen@gmail.com --- And it was tested with Wine Staging 5?0 rc1. Regular Wine doesn't work with EGS.
https://bugs.winehq.org/show_bug.cgi?id=48291
--- Comment #11 from Paul Gofman gofmanp@gmail.com --- It is all OK if you mention all these details. Your log did not have a line about Wine staging, which makes me think that maybe something got mixed up or the log was not recorded from the very beginning. On a clean prefix (with that workarounds needed to install the game applied and vcrun2015 for MFC), could you please make sure that you are starting the game with debug channels before any other processes were started for your Wine prefix? If you are using some wrapper to start Wine, can you please not and start it from the command line so we are sure this is a full log. And record the log with: WINEDEBUG=warn+all,+relay,+seh,+loaddll,+module,+process
https://bugs.winehq.org/show_bug.cgi?id=48291
--- Comment #12 from Paul Gofman gofmanp@gmail.com --- (In reply to Paul Gofman from comment #11)
It is all OK if you mention all these details. Your log did not have a line about Wine staging, which makes me think that maybe something got mixed up or the log was not recorded from the very beginning. On a clean prefix (with that workarounds needed to install the game applied and vcrun2015 for MFC), could you please make sure that you are starting the game with debug channels before any other processes were started for your Wine prefix? If you are using some wrapper to start Wine, can you please not and start it from the command line so we are sure this is a full log. And record the log with: WINEDEBUG=warn+all,+relay,+seh,+loaddll,+module,+process
Forgot to say, if you installed something via Winetricks, it could mess up the Windows version, could you please make sure that it is set to Windows 7 in winecfg before trying to run the game and recording the log?
https://bugs.winehq.org/show_bug.cgi?id=48291
--- Comment #13 from Alexandr Oleynikov sashok.olen@gmail.com ---
Forgot to say, if you installed something via Winetricks, it could mess up the Windows version, could you please make sure that it is set to Windows 7 in winecfg before trying to run the game and recording the log?
Yep, of course. So sorry for not providing all information from the start, and that I forgot to leave the wine version in the logs when I trimmed it to when the game itself starts. If you don't mind, I'll use TKG PKGBUILD to build wine, but of course I will disable absolutely every patchset that is applied to these by default to eliminate interference from other patches.
https://bugs.winehq.org/show_bug.cgi?id=48291
--- Comment #14 from Paul Gofman gofmanp@gmail.com --- (In reply to Alexandr Oleynikov from comment #13)
Forgot to say, if you installed something via Winetricks, it could mess up the Windows version, could you please make sure that it is set to Windows 7 in winecfg before trying to run the game and recording the log?
Yep, of course. So sorry for not providing all information from the start, and that I forgot to leave the wine version in the logs when I trimmed it to when the game itself starts.
Please, don't trim it, ever. There should be full log, from the very start. The one of the thread (not necessarily the one which had problems) in your log is waiting on the semaphore, until you terminated the game. Are you sure I should not know if the game has some services started before the game itself, and if they had some problems?
If you don't mind, I'll use TKG PKGBUILD to build wine
No. Please stick to Wine development or Staging.
https://bugs.winehq.org/show_bug.cgi?id=48291
--- Comment #15 from Alexandr Oleynikov sashok.olen@gmail.com ---
(with that workarounds needed to install the game applied and vcrun2015 for MFC)
Oh, my existing prefix only has vcrun2015 and native dotnet for EGS installation, and nothing extra was used when creating previous logs except for usage of Esync and DXVK, but just in case I'll remove that and leave only vcrun and dotnet. In that case, here is a WINEDEBUG=warn+all,+relay,+seh,+loaddll,+module,+process log made with Wine Staging 4.21 from Arch Linux repositories made in that prefix. And I made sure that the version is set to Windows 7. I let it run for some time to make sure the issue was fully recorded and then terminated the app with wineserver -k. It's too large for WineHQ so here's a link to google drive: https://drive.google.com/open?id=1fxeL8BAcfAjW4mxUwuo6Obv6fwduRY__ Hopefully this will be more helpful :)
https://bugs.winehq.org/show_bug.cgi?id=48291
--- Comment #16 from Alexandr Oleynikov sashok.olen@gmail.com --- As I am beginning to doubt line reports regarding game working on Windows 7, here's also a similar log but this time with prefix version set to Windows 10 with override for EGS launcher executable that sets it to Windows 7, as the launcher crashes work with version set to Windows 10. https://drive.google.com/open?id=1pDq8TXoNyNbiZb_yDqoWdfkzYrJ6wKkb
https://bugs.winehq.org/show_bug.cgi?id=48291
Leopard yurnerolinux@yandex.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |yurnerolinux@yandex.com
--- Comment #17 from Leopard yurnerolinux@yandex.com --- Game has a free demo available that can be used for testing purposes.
https://www.epicgames.com/store/product/detroit-become-human/demo
https://bugs.winehq.org/show_bug.cgi?id=48291
Louis Lenders xerox.xerox2000x@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |xerox.xerox2000x@gmail.com
--- Comment #18 from Louis Lenders xerox.xerox2000x@gmail.com --- (In reply to Leopard from comment #17)
Game has a free demo available that can be used for testing purposes.
https://www.epicgames.com/store/product/detroit-become-human/demo
The demo starts here but i get 1 frame per three seconds because i guess my graphics card is too cheap. I installed in an existing prefix, i`ll try in fresh prefix later
https://bugs.winehq.org/show_bug.cgi?id=48291
--- Comment #19 from Alexandr Oleynikov sashok.olen@gmail.com --- I can confirm that the Demo works. However, the full game still crashes, now even with native vcrun.
https://bugs.winehq.org/show_bug.cgi?id=48291
--- Comment #20 from Leopard yurnerolinux@yandex.com --- Both demo and full game doesn't work for me.
https://bugs.winehq.org/show_bug.cgi?id=48291
--- Comment #21 from Leopard yurnerolinux@yandex.com --- Sorry for my previous comment , demo of the game indeed works with vcrun2015.
However performance is really bad , even in the intro videos and main menu.
My specs are not the issue btw ; i7 7700HQ 8 threads and gtx 1050 4gb with 440 driver.
https://bugs.winehq.org/show_bug.cgi?id=48291
--- Comment #22 from Paul Gofman gofmanp@gmail.com --- Created attachment 66085 --> https://bugs.winehq.org/attachment.cgi?id=66085 POC patch
I've tested the full game. The attached patch allowed me to start the game. It contains 2-3 unrelated changes on top of Wine Staging (this patch heavily depends on some other staging patches).
I should note that after I got it running already it stopped working again after some cleanups in the patch and updating affected binaries only (saying "Something went wrong..." in a message Window). I ended up doing a full reinstall and then it worked again. Be sure to do a full Wine build / install before trying to launch it, so the Wine prefix gets fully updated, it might be important. It also did not work on Win 7 right away for me (with the same error message) but somehow started working later, seemingly without any changes from my side.
https://bugs.winehq.org/show_bug.cgi?id=48291
--- Comment #23 from Alexandr Oleynikov sashok.olen@gmail.com --- Thanks so much! And that error message you've experienced (Something Went Wrong...) is caused by DRM and happens not due to your patch but due to changing wine version too many times. Unrelated, but compared to Windows, the performance in this game under Wine is just horrendous. I'm talking about actual slideshow vs buttery smooth picture on Windows. And this even with Esync or Fsync enabled. So, should I open a different another bug report about it needing mfc140.dll? I actually tried running it in a prefix with just that dll and without actual vcrun2015 installed and it worked.
https://bugs.winehq.org/show_bug.cgi?id=48291
--- Comment #24 from Nikolay Sivov bunglehead@gmail.com --- We have a report to track mfc140.dll, see bug 44856.
https://bugs.winehq.org/show_bug.cgi?id=48291
--- Comment #25 from Paul Gofman gofmanp@gmail.com --- Created attachment 66094 --> https://bugs.winehq.org/attachment.cgi?id=66094 Don't use fast_wait_cv in conditional variable waits
Attached patch fixes the terrible performance issue for me (both on demo and full game). I did not test performance in details but that impossibly slow poerformance is gone with this patch.
I didn't yet fully analyzed what exactly is wrong with the fast_wait_cv() for this case, I suppose it was helping in some other cases, I didn't yet analyse what exactly is specifics here.
To summarize, the following is covered by the previous and this patch:
1. The game requires x64 syscalls emulation (supported in the previously attached patch using seccomp). Unfortunately seccomp is Linux specific, it won't work on Mac. The emulation of syscalls might be useful for some other DRMs.
2. The game requires processor features to be set more accurately. Somehow some features are currently set for AMD CPUs only, while Intel can have the same. The previous patch addresses that.
3. User shared data area has NumberOfPhysicalPages not filled in
4. Performance issue (use of fast_wait_cv).
The issues 1-3 are in the previous patch.
I suggest to make this bug about issue 1 (x64 syscalls emulation). The other 3 needs separate bugs to be created.
https://bugs.winehq.org/show_bug.cgi?id=48291
Paul Gofman gofmanp@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Attachment #66094|0 |1 is obsolete| |
--- Comment #26 from Paul Gofman gofmanp@gmail.com --- Created attachment 66102 --> https://bugs.winehq.org/attachment.cgi?id=66102 Don't use futexes for unaligned addresses
Regarding p. 4., the reason is the game is passing unaligned addresses for condition variables. That works somehow on Windows and in Wine fallback path, but not with futexes. I am attaching a bit better patch which fixes the issue.
With this patch, I played the game about 10 min and it seems to work flawlessly. Previously I had some random crashes which I suspected to be caused by some race conditions (not entirely sure though). I don't see them now yet. It might be related to this updated patch or maybe there are some other factors influencing it.
https://bugs.winehq.org/show_bug.cgi?id=48291
Zebediah Figura z.figura12@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |z.figura12@gmail.com
--- Comment #27 from Zebediah Figura z.figura12@gmail.com --- (In reply to Paul Gofman from comment #26)
Created attachment 66102 [details] Don't use futexes for unaligned addresses
Regarding p. 4., the reason is the game is passing unaligned addresses for condition variables. That works somehow on Windows and in Wine fallback path, but not with futexes. I am attaching a bit better patch which fixes the issue.
Nice find!
On 64-bit machines, we actually have 8 bits to work with, which means we could manually align the address upward, at least for condition variables and SRW locks.
Note also that address waits are hashed, so we don't need to use the server path for those even if they're unaligned.
https://bugs.winehq.org/show_bug.cgi?id=48291
--- Comment #28 from Alexandr Oleynikov sashok.olen@gmail.com --- Thanks, those patches improved performance significantly! However, at least on my machine (overclocked i7-2600K with Hyper Threading enabled, Nvidia GTX 1070), the performance is still noticeably worse than on Windows when I move from one room to the other in the first mission (both Windows and Linux the graphics drivers that I currently use were released before the Game-Ready driver that addressed issues in this game, so the difference is probably not in that). On Linux, it stutters heavily and drops to 10-20 fps, while on Windows, in the same scenes, it maintains more or less stable framerate (around 40-50 fps) even when my character moves. Although when my character stands still, the fps is pretty similar. Should be noted that I used Esync when testing the game, but I've also tried Fsync and doesn't seem to improve the situation. Also, this is probably unrelated to mouse polling rate issue some have reported for other games, as I experience performance drops even when using a controller. It's still pretty cool that it runs like this right now, but perhaps something else can be improved in Wine to more or less match native performance :D
https://bugs.winehq.org/show_bug.cgi?id=48291
Alistair Leslie-Hughes leslie_alistair@hotmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Keywords| |patch
https://bugs.winehq.org/show_bug.cgi?id=48291
Paul Gofman gofmanp@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Attachment #66102|0 |1 is obsolete| |
--- Comment #29 from Paul Gofman gofmanp@gmail.com --- Created attachment 66111 --> https://bugs.winehq.org/attachment.cgi?id=66111 Handle unaligned addresses in for condition variables.
I've made a patch which aligns the addresses and still use futexes for 64 bit, as Zebediah suggested in Comment #27. There is a chance it will improve performance a bit further.
I should note that the game works almost perfectly smooth for me with any of these patches). Maybe there is some small stuttering at transition between the locations but that doesn't happen often for me.
https://bugs.winehq.org/show_bug.cgi?id=48291
Paul Gofman gofmanp@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Attachment #66111|0 |1 is obsolete| |
--- Comment #30 from Paul Gofman gofmanp@gmail.com --- Created attachment 66112 --> https://bugs.winehq.org/attachment.cgi?id=66112 Handle unaligned addresses in for condition variables.
Fixed a bug in the previous patch.
https://bugs.winehq.org/show_bug.cgi?id=48291
--- Comment #31 from Alexandr Oleynikov sashok.olen@gmail.com --- Thanks, will check performance with this later!
I should note that the game works almost perfectly smooth for me with any of these patches). Maybe there is some small stuttering at transition between the locations but that doesn't happen often for me.
This is probably because the Wine overhead in this Game is far less noticeable on beefier CPUs, especially since there is hard fps lock to either 30 or 60 fps. Glad to hear it runs well on more modern systems though :D
https://bugs.winehq.org/show_bug.cgi?id=48291
--- Comment #32 from Alexandr Oleynikov sashok.olen@gmail.com --- By using last patch + installing native vcrun2019, performance is now more or less on par with Windows <3
https://bugs.winehq.org/show_bug.cgi?id=48291
Vijay Kamuju infyquest@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |infyquest@gmail.com
--- Comment #33 from Vijay Kamuju infyquest@gmail.com --- Please send the patch to be included in wine 5.0
https://bugs.winehq.org/show_bug.cgi?id=48291
--- Comment #34 from Zebediah Figura z.figura12@gmail.com --- Created attachment 66132 --> https://bugs.winehq.org/attachment.cgi?id=66132 alternate patch for futex alignment
Can you please test the attached patch also? It should be functionally identical to Paul's latest patch for condition variables, but is written a bit differently. (From a structural perspective I prefer leaving use_futexes() as it is, and I think I also prefer restricting the alignment logic to the futex path.)
https://bugs.winehq.org/show_bug.cgi?id=48291
--- Comment #35 from Alexandr Oleynikov sashok.olen@gmail.com --- That last one works well it seems, though I haven't tested it for very long.
https://bugs.winehq.org/show_bug.cgi?id=48291
David Torok dt@zeroitlab.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |dt@zeroitlab.com
--- Comment #36 from David Torok dt@zeroitlab.com --- Created attachment 66143 --> https://bugs.winehq.org/attachment.cgi?id=66143 seccomp filter to trap based on the program counter value
@Paul Gofman : Thank you for your work on x64 syscall emulation! I would like to discuss your approach a bit further to hopefully generalize this idea. I see you incremented the syscall numbers in the nt syscall thunks and subtracted accordingly before the dispatcher. My understanding is that this will not work in cases where the application looks up the NT build (from the PEB for instance) and uses a syscall number based on the build information. (Examples include Red Dead Redemption 2, similar issue: https://bugs.winehq.org/show_bug.cgi?id=47198 )
Assuming that my thinking is correct, we would need to set the syscall numbers accordingly in wine, which results in conflicts with linux syscall numbers. I've been thinking about ways to go about this, and thought we could rewrite the seccomp filter to trap only on virtual addresses outside of glibc. (see the attachment)
What are your thoughts, would that work well for us?
https://bugs.winehq.org/show_bug.cgi?id=48291
--- Comment #37 from Paul Gofman gofmanp@gmail.com --- (In reply to David Torok from comment #36)
idea. I see you incremented the syscall numbers in the nt syscall thunks and subtracted accordingly before the dispatcher. My understanding is that this will not work in cases where the application looks up the NT build (from the PEB for instance) and uses a syscall number based on the build information.
Yes, my patch won't work in that case.
I've been thinking about ways to go about this, and thought we could rewrite the seccomp filter to trap only on virtual addresses outside of glibc. (see the attachment)
What are your thoughts, would that work well for us?
Please note the following:
- Linux programs and libraries are doing syscalls directly whenever they want often bypassing glibc wrappers. Some syscalls don't even have such wrappers. Wine does a number of syscalls directly, so do a lot of native libraries. So the address range from where you can get a native syscall is absolutely not limited by glibc code segments.
- glibc (and other libraries) can be loaded at different addresses, and you can't ever change seccomp filters: once set, they are inherited by the child processes and can't be removed or replaced, only new filters can be added. Maybe there is an exception for process having admin caps (CAP_SYS_ADMIN), but that's not something I would mess with in Wine.
So the generic solution in this direction would probably imply intercepting every syscall and doing some address checks in the handler, which can probably work somehow but is going to have a terrible performance impact.
So I suppose you can make an app specific patch which will work for RDR2 (e. g., by using specific syscall numbers in seccomp filter and the address range which is correct for RDR2), but I don't yet see any acceptable generic solution.
https://bugs.winehq.org/show_bug.cgi?id=48291
--- Comment #38 from Paul Gofman gofmanp@gmail.com --- I have split off Bug #48386, Bug #48387 from this bug (p. 2, 3 from Comment #25). This bug is about p. 1, that is, syscall emulation.
There is currently no bug record for unaligned use of futexes (performance issue here), not sure if we need it.
https://bugs.winehq.org/show_bug.cgi?id=48291
Zebediah Figura z.figura12@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Blocks| |48389
https://bugs.winehq.org/show_bug.cgi?id=48291
--- Comment #39 from Zebediah Figura z.figura12@gmail.com --- (In reply to Paul Gofman from comment #38)
There is currently no bug record for unaligned use of futexes (performance issue here), not sure if we need it.
It's probably ideal, so we have something to link the patch to. I've filed bug 48389.
https://bugs.winehq.org/show_bug.cgi?id=48291
--- Comment #40 from Zebediah Figura z.figura12@gmail.com --- Ultimately, if we really want to pursue making direct syscalls work (and I still wince that the idea isn't immediately thrown out as absurd), I think we'll need to start talking to the Linux kernel about giving us a custom interface that makes it easy and performant.
I'm not a kernel developer, but I'll just throw some things out here. Knowing that we're going to have to start introducing some universal thunking at PE <-> Unix boundaries anyway (for e.g. ARM64's x18), the most ideal thing would be to make part of that a way to toggle whether syscalls should be trapped or not. That toggle of course wouldn't be able to involve a syscall itself; it would probably have to point to some bit of global memory that is registered at an early point in the process.
https://bugs.winehq.org/show_bug.cgi?id=48291
qsniyg qsniyg@mail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |qsniyg@mail.com
--- Comment #41 from qsniyg qsniyg@mail.com --- (In reply to Zebediah Figura from comment #40)
Ultimately, if we really want to pursue making direct syscalls work (and I still wince that the idea isn't immediately thrown out as absurd)
IIRC there are a few DRM and anticheat systems that use syscalls directly, apparently RDR2 does as well (https://github.com/ValveSoftware/Proton/issues/3291#issuecomment-562993403). While I agree that this is crazy, I don't know if there's any other way. That being said, I don't believe wine necessarily needs to switch internally to using syscalls instead of IPC, "only" support syscalls as well, so the performance or compatibility impact for any application not using syscalls directly (i.e. nearly all of them) shouldn't be affected.
I think we'll need to start talking to the Linux kernel about giving us a custom interface that makes it easy and performant.
Is there an issue with seccomp? I've used it in the past, and while at the time it didn't support what I was looking for (passing fds, although the one who posted the patch was interested in pursuing this at the time), it was quite easy to use and as far as I could tell, there wasn't much overhead either.
https://bugs.winehq.org/show_bug.cgi?id=48291
--- Comment #42 from Zebediah Figura z.figura12@gmail.com --- (In reply to qsniyg from comment #41)
(In reply to Zebediah Figura from comment #40)
Ultimately, if we really want to pursue making direct syscalls work (and I still wince that the idea isn't immediately thrown out as absurd)
IIRC there are a few DRM and anticheat systems that use syscalls directly, apparently RDR2 does as well (https://github.com/ValveSoftware/Proton/issues/3291#issuecomment-562993403). While I agree that this is crazy, I don't know if there's any other way. That being said, I don't believe wine necessarily needs to switch internally to using syscalls instead of IPC, "only" support syscalls as well, so the performance or compatibility impact for any application not using syscalls directly (i.e. nearly all of them) shouldn't be affected.
Yes, it's more of a matter of establishing a fence, past which we can say, "if you want your application to work on Wine, then *don't do this*." But I know that's not a hugely productive thing to do in practice :-/
I think we'll need to start talking to the Linux kernel about giving us a custom interface that makes it easy and performant.
Is there an issue with seccomp? I've used it in the past, and while at the time it didn't support what I was looking for (passing fds, although the one who posted the patch was interested in pursuing this at the time), it was quite easy to use and as far as I could tell, there wasn't much overhead either.
Partly as stated above, but moreover, some applications (and Red Dead Redemption 2 is one) make the excellent choice of hardcoding syscall numbers, which obviously then coincide with Linux syscalls. Solving this in a non-generic fashion isn't pretty and probably isn't sustainable either; solving it in a generic fashion would mean trapping *every* syscall before using heuristics to determine whose it is, which is of course a big performance problem. The fact that seccomp can't be removed once applied rules out the approach of turning it off whenever we exit PE code, and even if we could that would require a syscall at every transition.
https://bugs.winehq.org/show_bug.cgi?id=48291
--- Comment #43 from qsniyg qsniyg@mail.com --- (In reply to Zebediah Figura from comment #42)
Partly as stated above
Ah my apologies, for some reason I forgot to ctrl+f before asking haha
Solving this in a non-generic fashion isn't pretty and probably isn't sustainable either; solving it in a generic fashion would mean trapping *every* syscall before using heuristics to determine whose it is, which is of course a big performance problem. The fact that seccomp can't be removed once applied rules out the approach of turning it off whenever we exit PE code, and even if we could that would require a syscall at every transition.
Right, for some reason it eluded me that seccomp would also affect wine's syscalls haha. Turning it off and on would also likely incur a performance cost as well.
I guess an experiment could be to replace all IPC with syscalls (possibly through an inline function or macro, so as to allow an IPC fallback without a ton of #ifdefs), so the PE'd process would never actually run any posix functions. It would be interesting to see what the performance implications are.
Obviously quite a few components of wine would have to be rewritten to allow for this (shell32 comes to mind).
If I have time, I'll try taking a crack at this myself, but I think this will have to be more than just a one person job, as quite a lot of code would have to be rewritten for this.
https://bugs.winehq.org/show_bug.cgi?id=48291
--- Comment #44 from qsniyg qsniyg@mail.com --- After doing a little more thinking and investigation, here are my thoughts:
* A seccomp-based solution could indeed work, if no linux syscalls are sent. * The implementation of ntdll would have to be moved to wineserver, shell32 would have to be partly rewritten to use windows functions, etc. * From what I've read, the overhead is pretty small. Although I haven't tried this yet, in theory a big BPF tree (where apparently most of the performance overhead currently lies) shouldn't be needed if all syscalls are trapped. * Differences in syscall numbers could be handled through a LUT present in both wineserver and userspace, based on the Windows version selected. * Since seccomp can be turned off in userspace, support for it cannot be hardcoded through #ifdefs, it has to instead be able to detect support at runtime. * Obviously IPC has to be supported as well, but the current solution will have to be rewritten if duplication of code is to be avoided. For most cases, this shouldn't be much of an issue, but how about cases where memory has to be written (e.g. NtOpenFile returning a handle)? Would write_process_memory be a valid option? It would be a pretty terrible option performance-wise (and possibly compatibility-wise as well) if the ptrace path has to be used. The alternative would be to write a custom struct for every syscall, which would quite obviously be a chore.
Any thoughts on this?
https://bugs.winehq.org/show_bug.cgi?id=48291
--- Comment #45 from Zebediah Figura z.figura12@gmail.com --- (In reply to qsniyg from comment #44)
After doing a little more thinking and investigation, here are my thoughts:
- A seccomp-based solution could indeed work, if no linux syscalls are sent.
- The implementation of ntdll would have to be moved to wineserver,
shell32 would have to be partly rewritten to use windows functions, etc.
- From what I've read, the overhead is pretty small. Although I haven't
tried this yet, in theory a big BPF tree (where apparently most of the performance overhead currently lies) shouldn't be needed if all syscalls are trapped.
- Differences in syscall numbers could be handled through a LUT present in
both wineserver and userspace, based on the Windows version selected.
- Since seccomp can be turned off in userspace, support for it cannot be
hardcoded through #ifdefs, it has to instead be able to detect support at runtime.
- Obviously IPC has to be supported as well, but the current solution will
have to be rewritten if duplication of code is to be avoided. For most cases, this shouldn't be much of an issue, but how about cases where memory has to be written (e.g. NtOpenFile returning a handle)? Would write_process_memory be a valid option? It would be a pretty terrible option performance-wise (and possibly compatibility-wise as well) if the ptrace path has to be used. The alternative would be to write a custom struct for every syscall, which would quite obviously be a chore.
Any thoughts on this?
You'd need to do IPC without syscalls, which strikes me as pretty much impossible.
shell32 I think is mostly almost there, it's only using environment variables and Unix file I/O that we can access from Win32 code. It just hasn't been done yet. Unfortunately it's more than just ntdll and shell32, it's everything that needs to access an external library, or do e.g. unix ioctls.
Not to mention that relying on IPC for everything that could involve a system call would be enormously expensive. The degree to which we do already is bad enough.
https://bugs.winehq.org/show_bug.cgi?id=48291
--- Comment #46 from qsniyg qsniyg@mail.com --- (In reply to Zebediah Figura from comment #45)
You'd need to do IPC without syscalls, which strikes me as pretty much impossible.
Unless you're speaking about another part of wine, IPC would only be used if seccomp cannot be used, which means it shouldn't matter if it uses syscalls or not. The existing implementation could theoretically even be kept, if duplication of code doesn't matter.
Not to mention that relying on IPC for everything that could involve a system call would be enormously expensive. The degree to which we do already is bad enough.
That's a good point. In _theory_ (part of) the implementation for syscalls could reside somewhere else in the wine source code, and both wineserver and the userspace dlls could access it, so it wouldn't change anything performance-wise if using IPC. This would obviously increase the complexity of both the userspace dlls and wineserver, but I guess it could be a compromise, if it could be properly pulled off.
https://bugs.winehq.org/show_bug.cgi?id=48291
--- Comment #47 from Zebediah Figura z.figura12@gmail.com --- (In reply to qsniyg from comment #46)
(In reply to Zebediah Figura from comment #45)
You'd need to do IPC without syscalls, which strikes me as pretty much impossible.
Unless you're speaking about another part of wine, IPC would only be used if seccomp cannot be used, which means it shouldn't matter if it uses syscalls or not. The existing implementation could theoretically even be kept, if duplication of code doesn't matter.
You proposed that the implementation of ntdll be moved to wineserver. That's a separate process; how exactly are you proposing we communicate with it? We currently do so via sockets; that's IPC and requires system calls.
(In reply to qsniyg from comment #46)
(In reply to Zebediah Figura from comment #45)
Not to mention that relying on IPC for everything that could involve a system call would be enormously expensive. The degree to which we do already is bad enough.
That's a good point. In _theory_ (part of) the implementation for syscalls could reside somewhere else in the wine source code, and both wineserver and the userspace dlls could access it, so it wouldn't change anything performance-wise if using IPC. This would obviously increase the complexity of both the userspace dlls and wineserver, but I guess it could be a compromise, if it could be properly pulled off.
I'm not sure what you're even proposing here. ntdll runs in a given client process, wineserver runs in a different process. One of these has to execute, say, an NtReadFile() call and the underlying read() call that this probably implies. Making the wineserver do that incurs a lot of overhead no matter how it's done—it inheres just from counting the extra context switches and scheduling.
https://bugs.winehq.org/show_bug.cgi?id=48291
--- Comment #48 from qsniyg qsniyg@mail.com --- (In reply to Zebediah Figura from comment #47)
You proposed that the implementation of ntdll be moved to wineserver. That's a separate process; how exactly are you proposing we communicate with it? We currently do so via sockets; that's IPC and requires system calls.
If seccomp is used, ntdll uses syscalls, as (afaics) that's how windows works: https://j00ru.vexillium.org/syscalls/nt/64/ . IPC isn't used.
If seccomp is not used, IPC is used, and it doesn't matter that it uses linux syscalls because syscalls aren't being trapped :)
I'm not sure what you're even proposing here. ntdll runs in a given client process, wineserver runs in a different process. One of these has to execute, say, an NtReadFile() call and the underlying read() call that this probably implies. Making the wineserver do that incurs a lot of overhead no matter how it's done—it inheres just from counting the extra context switches and scheduling.
Sorry, I'm not very good at explaining, so let me use code instead. For the example you gave, let's say at user_kernel_shared/file.c, there's this function:
NTSTATUS Internal_NtReadFile(Internal_HANDLE ihandle, ...) { ... fread(buffer, 1, length, get_fp_from_ihandle(ihandle)); ... return STATUS_SUCCESS; }
Then in wineserver:
void handle_NtReadFile_syscall(struct seccomp_data data, struct seccomp_notif_resp* resp) { ... Internal_HANDLE ihandle = get_ihandle_from_handle(data.args[0]); resp->val = Internal_NtReadFile(ihandle, ...); ... }
And ntdll:
NTSTATUS WINAPI NtReadFile(HANDLE hFile, ...) { if (use_syscalls) { // perform syscall } else { return Internal_NtReadFile(get_ihandle_from_handle(hFile), ...); } }
Obviously this is all pseudocode, but that would be the general idea. In some cases, less code would be able to be shared (e.g. when IPC would be needed, as that code would only apply to ntdll), but it would help reduce some code duplication.
https://bugs.winehq.org/show_bug.cgi?id=48291
Leopard yurnerolinux@yandex.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC|yurnerolinux@yandex.com |
https://bugs.winehq.org/show_bug.cgi?id=48291
--- Comment #49 from Zebediah Figura z.figura12@gmail.com --- (In reply to qsniyg from comment #48)
(In reply to Zebediah Figura from comment #47)
You proposed that the implementation of ntdll be moved to wineserver. That's a separate process; how exactly are you proposing we communicate with it? We currently do so via sockets; that's IPC and requires system calls.
If seccomp is used, ntdll uses syscalls, as (afaics) that's how windows works: https://j00ru.vexillium.org/syscalls/nt/64/ . IPC isn't used.
Okay, now I'm even more confused. As I described, this approach means we trap on every syscall, which isn't performant.
If seccomp is not used, IPC is used, and it doesn't matter that it uses linux syscalls because syscalls aren't being trapped :)
...so what do we do about the syscalls that the application makes, if we're not trapping them?
https://bugs.winehq.org/show_bug.cgi?id=48291
--- Comment #50 from qsniyg qsniyg@mail.com --- (In reply to Zebediah Figura from comment #49)
Okay, now I'm even more confused. As I described, this approach means we trap on every syscall, which isn't performant.
This is why I wrote that it would be an experiment to see the performance impact. However seccomp - unlike ptrace - does not stop the process when it traps a syscall (it will pause the thread calling it obviously, but that's to be expected). Seccomp's performance overhead per-syscall is also apparently quite minimal according to various sources, so I'm not sure if the performance impact would be very significant. There's actually also the possibility that it will be faster, as it doesn't encode/decode anything, neither does it use sockets.
...so what do we do about the syscalls that the application makes, if we're not trapping them?
If seccomp is disabled, I'm not sure if there's anything that can be done (other than ptrace, which is probably out of the question for performance reasons).
That being said, I've been investigating this further, and I don't think it's possible for the moment, because of a few syscalls that must be performed in the client application, such as memory allocation. One possible solution would be to have a ptrace-like extension for seccomp, where the response would include a syscall to execute on the tracee.
https://bugs.winehq.org/show_bug.cgi?id=48291
Andrew Wesie awesie@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |awesie@gmail.com
--- Comment #51 from Andrew Wesie awesie@gmail.com --- (In reply to Paul Gofman from comment #37)
(In reply to David Torok from comment #36)
I've been thinking about ways to go about this, and thought we could rewrite the seccomp filter to trap only on virtual addresses outside of glibc. (see the attachment)
What are your thoughts, would that work well for us?
Please note the following:
- Linux programs and libraries are doing syscalls directly whenever they
want often bypassing glibc wrappers. Some syscalls don't even have such wrappers. Wine does a number of syscalls directly, so do a lot of native libraries. So the address range from where you can get a native syscall is absolutely not limited by glibc code segments.
I think filtering on the instruction pointer could work on 64-bit, because you don't need to reuse address space; 32-bit is a different matter. Wine already runs out of address space with some programs.
You can load one seccomp filter per windows DLL / exec mapping and trap if the instruction pointer is within the address range. For better performance, if you can reserve a "large enough" area of memory for these mappings, you would only need one seccomp filter in the fast case. This would avoid the problem of trying to guess which Linux libraries use syscalls.
On 32-bit, you might be able to get away with using VDSO to detect Linux syscalls. I know that glibc will use VDSO for syscalls if possible, not sure about other libraries we may be concerned about.
- glibc (and other libraries) can be loaded at different addresses, and you
can't ever change seccomp filters: once set, they are inherited by the child processes and can't be removed or replaced, only new filters can be added. Maybe there is an exception for process having admin caps (CAP_SYS_ADMIN), but that's not something I would mess with in Wine.
Honestly, wine should not generally be using exec* system calls. I am not saying that it doesn't, just that if we think about the semantics of creating a new process on Windows, the new process should be forked from wineserver or something.
Since seccomp appears to be per-thread, maybe you could create an unconstrained thread that will be used for fork and exec*. This would avoid adding more cruft to wineserver or additional IPC.
https://bugs.winehq.org/show_bug.cgi?id=48291
Zebediah Figura z.figura12@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Staged patchset| |https://github.com/wine-sta | |ging/wine-staging/tree/mast | |er/patches/ntdll-Syscall_Em | |ulation Component|-unknown |ntdll Summary|Detroit: Become Human |Detroit: Become Human |crashes on launch |crashes on launch (direct | |use of x86_64 SYSCALL | |instruction) Status|UNCONFIRMED |STAGED Ever confirmed|0 |1 Blocks| |48386, 48387
https://bugs.winehq.org/show_bug.cgi?id=48291
mirh mirh@protonmail.ch changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |mirh@protonmail.ch
https://bugs.winehq.org/show_bug.cgi?id=48291
Brendan Shanks bshanks@codeweavers.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |bshanks@codeweavers.com
--- Comment #52 from Brendan Shanks bshanks@codeweavers.com --- I've been working on supporting Red Dead Redemption 2, and now have a hack-y solution to handle its syscallls using seccomp.
RDR2 and the Rockstar Launcher use direct syscalls (with Windows syscall numbers) for some isolated uses. The launcher calls NtCreateFile/NtWriteFile. RDR2 calls NtQueryInformationProcess/NtQuerySystemInformation/NtGetContextThread for anti-debug checks, and sometimes NtCreateFile/NtReadFile/NtClose. Major/minor/build numbers are pulled from the PEB and used to branch to code that sets the right number and does the syscall.
I started out by trapping the specific syscall numbers in BPF, and then having the SIGSYS handler decide whether to execute the native syscall or have Wine handle it. This did work for the anti-debug calls, but had numerous problems:
- The arguments of some calls make it obvious whether they're meant for Linux or Windows, like R10/ProcessHandle of NtQueryInformationProcess often being -1. Most calls (like the file I/O calls) are not that easy.
- Once enabled, seccomp applies to the current thread, any threads that thread creates, and any child processes it spawns. Of course those spawned processes will not have a SIGSYS handler defined, and terminate when they execute a trapped syscall. I'm not sure how common it is for Wine to spawn non-Wine processes (I do remember seeing a recent patch that spawned 'ping'), but it's still not a great thing to break. I even had this problem with Wine itself, server_init_process() calls setsockopt(/NtQuerySystemInformation) and was crashing. My workaround was to call install_bpf() at the top of __wine_process_init().
- Windows system call numbers changing based on the version are problematic with every approach, but especially when they're hardcoded in the BPF program (can't be changed after it's enabled).
What I'm using now is to have BPF filter on the instruction pointer, since the game and launcher both load at 0x14000000. It's working well in this case, but clearly a hack.
My latest WIP branch is at https://github.com/mrpippy/wine/tree/rdr2-2 for anyone curious. There's a patch there (and I'll attach here) which adds symbols for Wine's syscall numbers, I think it could belong in the winebuild-Fake_Dlls staging patchset.
https://bugs.winehq.org/show_bug.cgi?id=48291
--- Comment #53 from Brendan Shanks bshanks@codeweavers.com --- Created attachment 67179 --> https://bugs.winehq.org/attachment.cgi?id=67179 0001-winebuild-Add-symbols-for-syscall-numbers-on-64-bit.patch
https://bugs.winehq.org/show_bug.cgi?id=48291
--- Comment #54 from Zebediah Figura z.figura12@gmail.com --- (In reply to Brendan Shanks from comment #53)
Created attachment 67179 [details] 0001-winebuild-Add-symbols-for-syscall-numbers-on-64-bit.patch
I'm not sure this patch makes sense by itself, and I'm not happy about including any of the other patches in Staging.
What does deserve examination is how this can be made to work in (upstream) Wine, if indeed it can.
Determining whether a syscall comes from PE or Unix code will probably become easier as time goes on and the boundary between PE and Unix becomes clearer. However, will the SIGSYS handler be fast enough, or will it cause a noticeable slowdown? My suspicion is the latter, but that's just armchair analysis.
If not, I imagine we're going to need to introduce support in the kernel in order to make this work.
https://bugs.winehq.org/show_bug.cgi?id=48291
Erich E. Hoover erich.e.hoover@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |erich.e.hoover@gmail.com
https://bugs.winehq.org/show_bug.cgi?id=48291
--- Comment #55 from Brendan Shanks bshanks@codeweavers.com --- Something that may be useful in the future: I wrote a script to parse j00ru's Windows syscall tables and generate version-specific Windows->Wine syscall number conversion functions.
https://github.com/mrpippy/wine/commit/6846ade935a493cf6620630f7c556140ebd2e...
https://bugs.winehq.org/show_bug.cgi?id=48291
Zebediah Figura z.figura12@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Summary|Detroit: Become Human |Multiple applications crash |crashes on launch (direct |due to direct use of x86_64 |use of x86_64 SYSCALL |SYSCALL instruction |instruction) |(Detroit: Become Human, Red | |Dead Redemption 2)
https://bugs.winehq.org/show_bug.cgi?id=48291
GloriousEggroll@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |GloriousEggroll@gmail.com
--- Comment #56 from GloriousEggroll@gmail.com --- Created attachment 68650 --> https://bugs.winehq.org/attachment.cgi?id=68650 rdr2 5.20 patches (not working)
Is there any hope of getting rdr2 working on upstream wine any time soon? I've tried porting over the win7->10 update patches and syscall patches to upstream, but sadly it still fails. Attached is the current patchset I'm applying to 5.21-staging. RDR2.exe just silently runs then fails in the background.
https://bugs.winehq.org/show_bug.cgi?id=48291
Fabian Maurer dark.shadow4@web.de changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |dark.shadow4@web.de
https://bugs.winehq.org/show_bug.cgi?id=48291
Ker noa blue-t@web.de changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |blue-t@web.de
https://bugs.winehq.org/show_bug.cgi?id=48291
Harold felineswift+wine@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |felineswift+wine@gmail.com
--- Comment #57 from Harold felineswift+wine@gmail.com --- Cannot confirm how this works under wine, but Detroit: BH does work under Proton 6.x. I'm also not entirely sure if proton experimental would work. It seems to be something Vulkan related (context creation might fail on specific proton versions).
https://bugs.winehq.org/show_bug.cgi?id=48291
--- Comment #58 from Andrey Gusev andrey.goosev@gmail.com --- RDR 2 with vanilla 8.2-110-g4d0d7e49b9b worked normally. API in game was set to Vulkan by default.
https://bugs.winehq.org/show_bug.cgi?id=48291
soredake broaden_acid002@simplelogin.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC|broaden_acid002@simplelogin | |.com |