https://bugs.winehq.org/show_bug.cgi?id=44860
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- Summary|4k/8k demos crash due to |4k/8k demos crash due to |Crinkler executable file |Crinkler executable file |compressor expecting PEB |compressor expecting PEB |address in %EBX on process |address in %ebx on process |entry |entry
--- Comment #6 from Anastasius Focht focht@gmx.net --- Hello Dmitry,
turns out there was no regression at all.
The commit(s) you mentioned earlier are indeed bringing the necessary infrastructure in place, along with later rework (https://source.winehq.org/git/wine.git/history/HEAD:/dlls/ntdll/loader.c , https://source.winehq.org/git/wine.git/history/HEAD:/dlls/ntdll/signal_i386....)
* https://source.winehq.org/git/wine.git/commitdiff/8b929bd759334611c0c9574820... ("ntdll: Set the initial process context on i386.") * https://source.winehq.org/git/wine.git/commitdiff/0eefa767919e81f3467141377b... ("ntdll: Suspend the process before attaching dlls, using the process initial context.")
These were included in Wine 2.18 release.
I cherry-picked https://github.com/wine-staging/wine-staging/blob/master/patches/kernel32-PE... for testing on top (bug 42125).
Debugging 'lns-lpt-psyltcipher_720.exe' with Wine 2.18 yields the same result: %ebx was not pointing to PEB when reaching the entry point.
Digging deeper it turns out that register %ebx is clobbered in between the main thread stack switch and the call of entry point due to a 'TRACE_(chn)(foo)'.
Source: https://source.winehq.org/git/wine.git/blob/HEAD:/dlls/kernel32/process.c#l1...
--- snip --- 1078 void WINAPI start_process( LPTHREAD_START_ROUTINE entry, PEB *peb ) 1079 { 1080 BOOL being_debugged; 1081 1082 if (!entry) 1083 { 1084 ERR( "%s doesn't have an entry point, it cannot be executed\n", 1085 debugstr_w(peb->ProcessParameters->ImagePathName.Buffer) ); 1086 ExitThread( 1 ); 1087 } 1088 1089 TRACE_(relay)( "\1Starting process %s (entryproc=%p)\n", 1090 debugstr_w(peb->ProcessParameters->ImagePathName.Buffer), entry ); 1091 1092 __TRY 1093 { 1094 if (!CheckRemoteDebuggerPresent( GetCurrentProcess(), &being_debugged )) 1095 being_debugged = FALSE; 1096 1097 SetLastError( 0 ); /* clear error code */ 1098 if (being_debugged) DbgBreakPoint(); 1099 ExitThread( call_process_entry( peb, entry )); 1100 } 1101 __EXCEPT(UnhandledExceptionFilter) 1102 { 1103 TerminateThread( GetCurrentThread(), GetExceptionCode() ); 1104 } 1105 __ENDTRY 1106 abort(); /* should not be reached */ 1107 } --- snip ---
Line 1089 essentially causes the harm.
Disassembly for proof:
--- snip --- # src/dlls/kernel32/process.c
Wine-dbg>disas start_process
0x7b46d516 [process.c:1079] leal 0x4(%esp),%ecx 0x7b46d51a [process.c:1079] andl $-16,%esp 0x7b46d51d [process.c:1079] pushl 0xfffffffc(%ecx) 0x7b46d520 [process.c:1079] pushl %ebp 0x7b46d521 [process.c:1079] movl %esp,%ebp 0x7b46d523 [process.c:1079] pushl %ebx ; local save 0x7b46d524 [process.c:1079] pushl %ecx 0x7b46d525 [process.c:1079] subl $0xf0,%esp 0x7b46d52b [process.c:1079] movl %ecx,%eax 0x7b46d52d [process.c:1079] movl %eax,0xffffff14(%ebp) ; addr arg1 0x7b46d533 [process.c:1082] cmpl $0,0x0(%eax) ; entry 0x7b46d536 [process.c:1082] jnz 0x7b46d599 start_process+0x83 0x7b46d538 [process.c:1084] movl $0x7b7f1c9c,%eax 0x7b46d53d [process.c:1084] movzbl 0x0(%eax),%eax 0x7b46d540 [process.c:1084] movzbl %eax,%eax 0x7b46d543 [process.c:1084] andl $2,%eax 0x7b46d546 [process.c:1084] testl %eax,%eax 0x7b46d548 [process.c:1084] jz 0x7b46d58f start_process+0x79 0x7b46d54a [process.c:1084] movl $0x7b7f1c9c,0xffffffe8(%ebp) 0x7b46d551 [process.c:1084] movl $0x1,0xffffffe4(%ebp) 0x7b46d558 [process.c:1084] movl 0xffffff14(%ebp),%eax ; addr arg1 0x7b46d55e [process.c:1084] movl 0x4(%eax),%eax ; arg2 -> PEB 0x7b46d561 [process.c:1084] movl 0x10(%eax),%eax ; ProcessParameters 0x7b46d564 [process.c:1084] movl 0x3c(%eax),%eax ; ImagePathName 0x7b46d567 [process.c:1084] subl $12,%esp 0x7b46d56a [process.c:1084] pushl %eax 0x7b46d56b [process.c:1084] call 0x7b46b4ab debugstr_w 0x7b46d570 [process.c:1084] addl $16,%esp 0x7b46d573 [process.c:1084] subl $12,%esp 0x7b46d576 [process.c:1084] pushl %eax 0x7b46d577 [process.c:1084] pushl $0x7b4a2b70 0x7b46d57c [process.c:1084] pushl $0x7b4a39e0 0x7b46d581 [process.c:1084] pushl 0xffffffe8(%ebp) 0x7b46d584 [process.c:1084] pushl 0xffffffe4(%ebp) 0x7b46d587 [process.c:1084] call 0xf7de0af5 wine_dbg_log 0x7b46d58c [process.c:1084] addl $32,%esp 0x7b46d58f [process.c:1086] subl $12,%esp 0x7b46d592 [process.c:1086] pushl $0x1 0x7b46d594 [process.c:1086] call 0x7b483b7b ExitThread ; entry != NULL, relay channel with lazy init 0x7b46d599 [process.c:1089] movzbl 0x7b7f1cac __wine_dbch_relay,%eax 0x7b46d5a0 [process.c:1089] movzbl %eax,%eax 0x7b46d5a3 [process.c:1089] andl $8,%eax 0x7b46d5a6 [process.c:1089] testl %eax,%eax 0x7b46d5a8 [process.c:1089] jz 0x7b46d5f1 start_process+0xdb 0x7b46d5aa [process.c:1089] movl $0x7b7f1cac,0xfffffff0(%ebp) 0x7b46d5b1 [process.c:1089] movl $0x3,0xffffffec(%ebp) ; *** clobbers %ebx *** 0x7b46d5b8 [process.c:1089] movl 0xffffff14(%ebp),%ebx ; addr arg1 0x7b46d5be [process.c:1089] movl 0x4(%ebx),%eax ; arg2 -> PEB 0x7b46d5c1 [process.c:1089] movl 0x10(%eax),%eax ; ProcessParameters 0x7b46d5c4 [process.c:1089] movl 0x3c(%eax),%eax ; ImagePathName 0x7b46d5c7 [process.c:1089] subl $12,%esp 0x7b46d5ca [process.c:1089] pushl %eax 0x7b46d5cb [process.c:1089] call 0x7b46b4ab debugstr_w 0x7b46d5d0 [process.c:1089] addl $16,%esp 0x7b46d5d3 [process.c:1089] subl $8,%esp 0x7b46d5d6 [process.c:1089] pushl 0x0(%ebx) 0x7b46d5d8 [process.c:1089] pushl %eax 0x7b46d5d9 [process.c:1089] pushl $0x7b4a2ba8 0x7b46d5de [process.c:1089] pushl $0x7b4a39e0 0x7b46d5e3 [process.c:1089] pushl 0xfffffff0(%ebp) 0x7b46d5e6 [process.c:1089] pushl 0xffffffec(%ebp) 0x7b46d5e9 [process.c:1089] call 0xf7de0af5 wine_dbg_log 0x7b46d5ee [process.c:1089] addl $32,%esp 0x7b46d5f1 [process.c:1092] movl $0x1,0xfffffff4(%ebp) 0x7b46d5f8 [process.c:1092] cmpl $0,0xfffffff4(%ebp) 0x7b46d5fc [process.c:1092] jnz 0x7b46d655 start_process+0x13f 0x7b46d5fe [process.c:1094] subl $8,%esp 0x7b46d601 [process.c:1094] leal 0xffffffd8(%ebp),%eax 0x7b46d604 [process.c:1094] pushl %eax 0x7b46d605 [process.c:1094] pushl $0xff 0x7b46d607 [process.c:1094] call 0x7b443983 CheckRemoteDebuggerPresent 0x7b46d60c [process.c:1094] addl $8,%esp 0x7b46d60f [process.c:1094] testl %eax,%eax 0x7b46d611 [process.c:1094] jnz 0x7b46d61a start_process+0x104 0x7b46d613 [process.c:1095] movl $0x0,0xffffffd8(%ebp) 0x7b46d61a [process.c:1095] movl $0x0,0xffffffdc(%ebp) 0x7b46d621 [winbase.h:3076] movl 0xffffffdc(%ebp),%eax 0x7b46d624 [winbase.h:3076] movl %eax,%fs:0x34 0x7b46d62a [process.c:1098] movl 0xffffffd8(%ebp),%eax 0x7b46d62d [process.c:1098] testl %eax,%eax 0x7b46d62f [process.c:1098] jz 0x7b46d636 start_process+0x120 ; debugger breakin: %ebx already clobbered 0x7b46d631 [process.c:1098] call 0x7b46b130 DbgBreakPoint 0x7b46d636 [process.c:1099] subl $8,%esp 0x7b46d639 [process.c:1099] movl 0xffffff14(%ebp),%eax 0x7b46d63f [process.c:1099] pushl 0x0(%eax) 0x7b46d641 [process.c:1099] pushl 0x4(%eax) ; normal entry: %ebx already clobbered 0x7b46d644 [process.c:1099] call 0x7b46d4fc call_process_entry 0x7b46d649 [process.c:1099] addl $16,%esp 0x7b46d64c [process.c:1099] subl $12,%esp 0x7b46d64f [process.c:1099] pushl %eax 0x7b46d650 [process.c:1099] call 0x7b483b7b ExitThread ... --- snip ---
Any lazy (first time) init of the channel or enabling via WINEDEBUG will cause clobber - as long as 'wine_dbg_log' with args is called here (via macro expansion). Either move the TRACE() before the thread stack switch or use a wrapper function to preserve %ebx.
$ wine --version wine-3.5-2-g6d43d5b101
Regards