On Tue, Apr 19, 2022, 2:03 AM Derek Lesho dlesho@codeweavers.com wrote:
On 18.04.22 12:35, Jinoh Kang wrote:
On 4/18/22 22:37, Derek Lesho wrote:
On 16.04.22 03:58, Jinoh Kang wrote:
On 4/15/22 00:26, Eric Pouech wrote:
For modules requiring linking to .so files, the scheme has to be extended by generating an additional ELF library, tied to the PE module. +-----------------+ +-----------------+ +-----------+ | FOOBAR.dll (PE) | | FOOBAR.so (ELF) | -------------> | helper.so | | | --------> | (unixlib) | ELF dyn link +-----------+ | | | | +-----------------+ +-----------------+
Addind this extra module in the middle allows to:
- do the translation from a entities defined in PE world into entities defined in the ELF world (ABI are different, structures layout are different)
- this provides an abstraction of the library for the PE world.
- decide what to migrate from the existing code into the PE part (remember existing library in old model lives in the ELF world)
One can see the FOOBAR.so like a Wine-"system driver" for providing the required support from the host.
But, it brings constraints too. The ELF part cannot call back into the PE part of the module, nor into other PE modules.
To clarify: the ELF part cannot call back into PE modules *without performance penalty or interference with stack unwinding*.
ELF modules calls back into user-supplied functions just fine, think e.g. window procedures. This however involves KeUserModeCallback(), accompanied by its context-switching overhead.
Perhaps we intend to say: "The ELF part cannot link directly to dlls. Also, calling back to the PE side comes with performance penalty or interferes with stack unwinding, depending on which callback approach is used."
Can you describe the two approaches you're referring to? I'm aware of KeUserModeCallback, and I assume the other method is to create a win32 PE thread which waits on callbacks from the unixlib?
I meant calling it directly. Which (kind of) messes with syscall frame state.
Is this allowed in upstream wine, even as an intermediate step in the transition?
I was only suggesting a possibility, not necessarily what is allowed in upstream codebase policy.
As far as I know, KeUserModeCallback doesn't involve context switching, just the usual context saving/restoring required for syscalls in general.
Oh, maybe not a context switch per se. It's actually:
- __wine_setjmp: save Unix-side state
- emulated syscall return: divert into KiUserCallbackDispatcher
- syscall: call into NtCallbackReturn
- __wine_longjmp: restore Unix-side state
So it's still a lot of work.
Yeah, and of course it should be noted that this only works on threads created by wine.
If this ELF parts requires some Wine "kernel features", the it can (using ELF dynamic linking) use the APIs provided by ntdll.so ELF library.
+-----------------+ +-----------------+ +-----------+ | FOOBAR.dll (PE) | | FOOBAR.so (ELF) | -------------> | ntdll.so | | | --------> | (unixlib) | ELF dyn link +-----------+ | | | | -------------> | helper.so | +-----------------+ +-----------------+ +-----------+
Note: likely some other modules .so should be available too (like win32u) (to be confirmed)
I confirm that win32u.so also exists.
Here is a list of other Unixlibs:
I think what Eric was getting at here was what base unix libraries all other unix libraries can be linked against. (For example, using win32u.so from winevulkan.so).
Pretty much every Unix library can link to one another if they want to, barring abstraction layer issues. I think this aligns with what Eric is trying to convey.
Yeah, it's definitely possible to link to any unix library you want, but in terms of making sense of the system, it's possibly useful to clearly differentiate between unix libraries which in addition to their primary purpose can also be used as helper libraries for other unix libraries (like ntdll, win32u), and which unix libraries have the sole purpose of providing a link to the unix world for an optional PE dll (bcrypt, gphoto2, winegstreamer, winepulse, etc).
The former category would be those providing what Eric referred to as "kernel features".
You're right. Maybe I wasn't reading this thoroughly...
avicap32.so, bcrypt.so, capi2032.so, crypt32.so, ctapi32.so, dnsapi.so, dwrite.so, gphoto2.so, kerberos.so, mountmgr.so, msv1_0.so, netapi32.so, nsiproxy.so, odbc32.so, opencl.so, qcap.so, sane.so, secur32.so, winealsa.so, winebus.so, winecoreaudio.so, winegstreamer.so, wineoss.so, winepulse.so, winevulkan.so, winspool.so, wldap32.so, wpcap.so, ws2_32.so
- exception handling?
To accurately mimic stack unwinding as it happens on Windows, one should stick to the syscall interface instead of the unixlib interface.
Assuming you're referring to the __wine_init_unix_lib approach, the unixlib interface doesn't even exist anymore. (Was removed right before wine 7.0-rc1)
I really meant __wine_unix_call. There's no syscall gate in-between, exposing DWARF frames that could confuse Win32 debuggers/monitors (probably as part of some DRM/obfuscation/anti-RE)
__wine_unix_call is part of the syscall interface, so you won't run into the problems mentioned by using it.
https://source.winehq.org/git/wine.git/blob/HEAD:/dlls/ntdll/ntdll.spec#l164... :
@ stdcall -syscall __wine_unix_call(int64 long ptr)
I stand corrected.
This way, unix-side stack frames will never appear in RtlVirtualUnwind() output (since they are effectively kernel-mode frames, not user-mode ones).