Hello,
While implementing the MSVC /hotpatch flag into LLVM clang-cl, we were wondering how hotpatching is achieved in Wine for 32-bit x86 targets? Previous versions of MSVC up to VS2013 were emitting "8F FF MOV edi, edi". However since VS2015, a two-byte nop "66 90 XCHG ax, ax" is emitted, as suggested by Intel documentation. Charles suggested here: https://reviews.llvm.org/D81301#2077964 that Wine might be relying on the magic "8F FF" to patch the Win32 APIs. However how is that possible since (I assume) recent Windows do not contain that magic sequence, rather a two-byte nop. In essence the question is, if MSVC /hotpatch or GCC __ms_hook_prologue__ was supported in LLVM, would it be fine if it generated "66 90 XCHG ax, ax"?
Thanks in advance! Alex.
Hi,
In essence the question is, if MSVC /hotpatch or GCC __ms_hook_prologue__ was supported in LLVM, would it be fine if it generated “66 90 XCHG ax, ax”?
Wine itself does not depend on it at all, we don't hotpatch our own code. Windows applications like Steam might depend on it though, and I can't give you a certain answer for all of them.
Check the nop opcode in Windows DLLs. If Microsoft's kernel32.dll switched to 66 90 we're safe to switch too. If they still use 8b ff we probably should stick to that.
Steam checks which instructions it replaces, and if it doesn't know 66 90 it will stop patching, breaking the in-game overlay in 32 bit games. Other applications like FRAPS don't care what they replace, as long as they can move the first 5 bytes elsewhere.
(Resent to the list because I forgot to CC the list in the previous mail)
Am 07.06.20 um 11:47 schrieb Stefan Dösinger:
Check the nop opcode in Windows DLLs. If Microsoft's kernel32.dll switched to 66 90 we're safe to switch too. If they still use 8b ff we probably should stick to that.
I just checked my Win10 19.09, it still uses 8b ff. So either Microsoft compiles Windows with an old Visual Studio or they kept the old style nops for Windows itself.
Also worth noting is that I have not seen any application that uses the 2 byte instructions the way Microsoft uses it themselves for on the fly updates: Put an absolute jump in the 5 bytes (0xcc or 0x90) before the function and then replace the two byte instruction with a relative -5 jump. The applications I dealt with all replace the first 5 bytes with an absolute jump, with varying degrees of care. The idea of the 2 byte nop is that it can be replaced without caring about races, whereas replacing the 5 bytes will crash and burn if a thread is in the middle of executing them. Steam hotpatches on process creation or DLL load, so it is fine. Others I am not so sure...
On 2020-06-07 11:56, Stefan Dösinger wrote:
Am 07.06.20 um 11:47 schrieb Stefan Dösinger:
Check the nop opcode in Windows DLLs. If Microsoft's kernel32.dll switched to 66 90 we're safe to switch too. If they still use 8b ff we probably should stick to that.
I just checked my Win10 19.09, it still uses 8b ff. So either Microsoft compiles Windows with an old Visual Studio or they kept the old style nops for Windows itself.
Looks like the /arch:IA32 option changes the hotpatch instruction from 66 90 back to 8b ff. This is true in a simple test and also my observation from looking at ReactOS binaries, which use that option.
It makes sense to assume that 32-bit Windows binaries would be built with that option for compatibility; the compiler default is to assume SSE2 these days.
That is quite interesting, thanks for the explanation. Normally, 66 90 was introduced with i386, so it would be a valid opcode for /arch:IA32. But I suppose reverting to 8F FF was done for compatibility reasons. We should maybe mimic the same behavior in Clang. My intent was to support MSVC /hotpath in Clang, not GCC's ms_hook_prologue attribute. That could perhaps land later.
-----Message d'origine----- De : Thomas Faber thomas.faber@reactos.org Envoyé : June 7, 2020 11:24 AM À : Alexandre Ganea alexandre.ganea@ubisoft.com Cc : Stefan Dösinger stefandoesinger@gmail.com; wine-devel@winehq.org Objet : Re: 32-bit hotpatching question
On 2020-06-07 11:56, Stefan Dösinger wrote:
Am 07.06.20 um 11:47 schrieb Stefan Dösinger:
Check the nop opcode in Windows DLLs. If Microsoft's kernel32.dll switched to 66 90 we're safe to switch too. If they still use 8b ff we probably should stick to that.
I just checked my Win10 19.09, it still uses 8b ff. So either Microsoft compiles Windows with an old Visual Studio or they kept the old style nops for Windows itself.
Looks like the /arch:IA32 option changes the hotpatch instruction from 66 90 back to 8b ff. This is true in a simple test and also my observation from looking at ReactOS binaries, which use that option.
It makes sense to assume that 32-bit Windows binaries would be built with that option for compatibility; the compiler default is to assume SSE2 these days.