https://bugs.winehq.org/show_bug.cgi?id=47027
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- Summary|EA Origin client crashes on |EA Origin client crashes on |startup (Origin IGO hook |startup (Origin IGO using |engine can't cope with |madCodeHook 3.x engine |GOT/PIC register load code |can't cope with GOT/PIC |at API entry, needs |register load code within |DECLSPEC_HOTPATCH for |15-byte range at API entry) |user32.SetForegroundWindow) |
--- Comment #12 from Anastasius Focht focht@gmx.net --- Hello Louis,
yeah I see it now ... IGO uses madCodeHook 3.x (http://www.madshi.net/)
--- snip --- ; ASCII "C:\jenkins\workspace\Client\build_release_win\origin\products\client\10.5.38\IGO\madCodeHook3\Sources\C++\ModuleTools.cpp" --- snip ---
Reminds me of Chromium. It copies a whole range of opcodes (15 bytes) from API entry into dynamically allocated trampoline. In addition it tries to be clever and patches instructions that change code flow (calls) within first 15 bytes of function entry (if their complete opcode fits in range).
Pure unhooked 'user32.SetForegroundWindow' with DECLSPEC_HOTPATCH applied:
--- snip --- 7E68A0C0 8BFF MOV EDI,EDI 7E68A0C2 55 PUSH EBP 7E68A0C3 8BEC MOV EBP,ESP 7E68A0C5 E8 77D9FCFF CALL 7E657A41 7E68A0CA 05 366F0B00 ADD EAX,0B6F36 7E68A0CF 5D POP EBP 7E68A0D0 8D4C24 04 LEA ECX,[ESP+4] 7E68A0D4 83E4 F0 AND ESP,FFFFFFF0 7E68A0D7 FF71 FC PUSH DWORD PTR DS:[ECX-4] 7E68A0DA 55 PUSH EBP 7E68A0DB 89E5 MOV EBP,ESP 7E68A0DD 53 PUSH EBX 7E68A0DE 8B19 MOV EBX,DWORD PTR DS:[ECX] 7E68A0E0 51 PUSH ECX 7E68A0E1 F680 80B60E00 0 TEST BYTE PTR DS:[EAX+0EB680],08 7E68A0E8 75 26 JNE SHORT 7E68A110 ... --- snip ---
After hook:
--- snip --- 7E68A0C0 E9 0BEED091 JMP 10398ED0 ; first hook 7E68A0C5 8BE5 MOV ESP,EBP 7E68A0C7 5D POP EBP 7E68A0C8 E9 03EED091 JMP 10398ED0 ; second hook, non-reachable though 7E68A0CD 0B00 OR EAX,DWORD PTR DS:[EAX] 7E68A0CF 5D POP EBP ; <--- trampoline continuation 7E68A0D0 8D4C24 04 LEA ECX,[ESP+4] 7E68A0D4 83E4 F0 AND ESP,FFFFFFF0 7E68A0D7 FF71 FC PUSH DWORD PTR DS:[ECX-4] 7E68A0DA 55 PUSH EBP 7E68A0DB 89E5 MOV EBP,ESP 7E68A0DD 53 PUSH EBX 7E68A0DE 8B19 MOV EBX,DWORD PTR DS:[ECX] 7E68A0E0 51 PUSH ECX 7E68A0E1 F680 80B60E00 0 TEST BYTE PTR DS:[EAX+0EB680],08 7E68A0E8 75 26 JNE SHORT 7E68A110 ... --- snip ---
When the first hook is done (taking 5-bytes), the next instruction instruction within 15-byte range is the call to load PIC register. IGO/madCodeHook3 considers it a code flow change and patches it as well, along with original prologue chunk insertion. Questionable implementation if the code won't be reachable at all due to first own(!) hook.
--- snip --- 7E68A0C0 E9 0BEED091 JMP 10398ED0 7E68A0C5 E8 77D9FCFF CALL 7E657A41 ; <-- will be patched in second pass 7E68A0CA 05 366F0B00 ADD EAX,0B6F36 7E68A0CF 5D POP EBP --- snip ---
The final trampoline with copied opcodes:
--- snip --- 7F000210 8BFF MOV EDI,EDI 7F000212 55 PUSH EBP 7F000213 8BEC MOV EBP,ESP 7F000215 E8 277865FF CALL 7E657A41 ; PIC load, can't work 7F00021A 05 366F0B00 ADD EAX,0B6F36 7F00021F E9 AB9E68FF JMP 7E68A0CF --- snip ---
In other cases it works because there is no call instruction in first 15-byte range, example:
'DoDragDrop' hooked API entry which doesn't even have DECLSPEC_HOTPATCH:
--- snip --- ... 7E366710 E9 8B210392 JMP 103988A0 7E366715 E4 F0 IN AL,0F0 7E366717 FF71 FC PUSH DWORD PTR DS:[ECX-4] 7E36671A 55 PUSH EBP 7E36671B 89E5 MOV EBP,ESP 7E36671D 57 PUSH EDI 7E36671E 56 PUSH ESI 7E36671F 53 PUSH EBX ; <--- trampoline continuation 7E366720 E8 1BDDFBFF CALL 7E324440 ; PIC load, will work 7E366725 81C3 DB280E00 ADD EBX,0E28DB ... --- snip ---
Trampoline, has copy of first 15 bytes:
--- snip --- 7F000040 8D4C24 04 LEA ECX,[ESP+4] ; original entry with no hotpatch 7F000044 83E4 F0 AND ESP,FFFFFFF0 7F000047 FF71 FC PUSH DWORD PTR DS:[ECX-4] 7F00004A 55 PUSH EBP 7F00004B 89E5 MOV EBP,ESP 7F00004D 57 PUSH EDI 7F00004E 56 PUSH ESI 7F00004F E9 CB6636FF JMP 7E36671F --- snip ---
Another example that doesn't work:
'user32.BringWindowToTop' has no DECLSPEC_HOTPATCH:
--- snip --- 7E6E9280 8D4C24 04 LEA ECX,[ARG.1] ; original entry with no hotpatch 7E6E9284 83E4 F0 AND ESP,FFFFFFF0 7E6E9287 FF71 FC PUSH DWORD PTR DS:[ECX-4] 7E6E928A 55 PUSH EBP 7E6E928B 89E5 MOV EBP,ESP 7E6E928D 53 PUSH EBX 7E6E928E E8 DD32F6FF CALL 7E64C570 7E6E9293 81C3 6D7D0500 ADD EBX,57D6D 7E6E9299 51 PUSH ECX ... --- snip ---
After hook:
--- snip --- 7E64C570 8B1C24 MOV EBX,DWORD PTR SS:[ESP] 7E64C573 C3 RETN
7E6E9280 E9 5BEECA91 JMP 103980E0 7E6E9285 E4 F0 IN AL,0F0 7E6E9287 FF71 FC PUSH DWORD PTR DS:[ECX-4] 7E6E928A 55 PUSH EBP 7E6E928B 89E5 MOV EBP,ESP 7E6E928D 53 PUSH EBX 7E6E928E E8 DD32F6FF CALL 7E64C570 7E6E9293 81C3 6D7D0500 ADD EBX,57D6D ; <--- trampoline continuation 7E6E9299 51 PUSH ECX 7E6E929A 83EC 04 SUB ESP,4 7E6E929D 6A 03 PUSH 3 7E6E929F 6A 00 PUSH 0 7E6E92A1 6A 00 PUSH 0 7E6E92A3 6A 00 PUSH 0 7E6E92A5 6A 00 PUSH 0 7E6E92A7 6A 00 PUSH 0 7E6E92A9 FF31 PUSH DWORD PTR DS:[ECX] 7E6E92AB E8 50F6FFFF CALL SetWindowPos ... --- snip ---
Unfortunately the first byte of call instruction to load PIC reg is the 15th byte, hence it's still considered part of "prologue". The hook copies the whole call into trampoline.
--- snip --- 7F000210 8D4C24 04 LEA ECX,[ESP+4] ; original entry with no hotpatch 7F000214 83E4 F0 AND ESP,FFFFFFF0 7F000217 FF71 FC PUSH DWORD PTR DS:[ECX-4] 7F00021A 55 PUSH EBP 7F00021B 89E5 MOV EBP,ESP 7F00021D 53 PUSH EBX 7F00021E E8 4DC364FF CALL 7E64C570 ; PIC load, can't work 7F000223 E9 6B906EFF JMP 7E6E9293 --- snip ---
DECLSPEC_HOTPATCH would help in this case.
There is not much to be done about it .. shuffling code around (add/remove/dummy vars) has the risk of not working out as intended. The compiler can optimize/re-arrange code at will, depending on used optimization levels.
Honstely, I've already said it multiple times (bug 37540 and the like): the usage of PIC for 32-bit is just harmful, I don't see any benefit at all. It's just wasted time hacking around and clobbering Wine sources with DECLSPEC_HOTPATCH which won't help in some cases as demonstrated here.
Regards