https://bugs.winehq.org/show_bug.cgi?id=44860
Bug ID: 44860 Summary: 4k/8k demos crash due to Crinkler executable file compressor expecting PEB address in %EBX on process entry Product: Wine Version: 3.4 Hardware: x86-64 OS: Linux Status: NEW Severity: normal Priority: P2 Component: kernel32 Assignee: wine-bugs@winehq.org Reporter: focht@gmx.net Distribution: ---
Hello folks,
split out from bug 42125 which is about OS loader compatibility/PE image header fields/mappings.
Most of the PE tools struggle or even crash when trying to get something useful out of this due to the "optimized" usage (truncation) of DOS, PE headers (basically providing the bare minimum info to not have the OS loader crash).
Example: http://www.pouet.net/prod.php?which=66502 ("Psyltcipher by Loonies")
ProtectionID scan:
--- snip --- -=[ ProtectionID v0.6.9.0 DECEMBER]=- (c) 2003-2017 CDKiLLER & TippeX Build 24/12/17-21:05:42 Ready... Scanning -> Z:\home\focht\Downloads\lns-lpt-psyltcipher_720.exe [!] Warning : File has NO sections (suspicious) [!] Warning : File has NO imports (suspicious) File Type : 32-Bit Exe (Subsystem : Win GUI / 2), Size : 7242 (01C4Ah) Byte(s) | Machine: 0x14C (I386) [!] Warning - Entrypoint is INVALID (file may be damaged) Compilation TimeStamp : 0x7F61DB01 -> Mon 21st Sep 2037 04:18:09 (GMT) [TimeStamp] 0x7F61DB01 -> Mon 21st Sep 2037 04:18:09 (GMT) | PE Header | - | Offset: 0x0000000C | VA: 0x0040000C | - [LoadConfig] CodeIntegrity -> Flags 0xA3F0 | Catalog 0x46 (70) | Catalog Offset 0x2000001 | Reserved 0x46A4A0 [LoadConfig] GuardAddressTakenIatEntryTable 0x8000011 | Count 0x46A558 (4629848) [LoadConfig] GuardLongJumpTargetTable 0x8000001 | Count 0x46A5F8 (4630008) [LoadConfig] HybridMetadataPointer 0x8000011 | DynamicValueRelocTable 0x46A66C [LoadConfig] FailFastIndirectProc 0x8000011 | FailFastPointer 0x46C360 [LoadConfig] UnknownZero1 0x8000011 [File Heuristics] -> Flag #1 : 00010001000001111110000011001000 (0x1107E0C8) [DllCharacteristics] -> Flag : (0x0000) -> NONE [SectionCount] 0 (0x0) | ImageSize 0x2263B6EB (576960235) byte(s) [!} Warning - image has NO Data Directories... [!] Warning : Import Table is bad !!! -> Suspicious MZ Header.. [!] File appears to have no protection or is using an unknown protection - Scan Took : 0.211 Second(s) [0000000D3h (211) tick(s)] [506 of 580 scan(s) done] --- snip ---
LordPE dump (helper tool crashes during analysis but main app still shows info):
--- snip --- ->DOS Header e_magic: 0x5A4D e_cblp: 0x3032 e_cp: 0x4550 e_crlc: 0x0000 e_cparhdr: 0x014C e_minalloc: 0x0000 e_maxalloc: 0xDB01 e_ss: 0x7F61 e_sp: 0xD010 e_csum: 0x7317 e_ip: 0x4775 e_cs: 0xF9EB e_lfarlc: 0x0008 e_ovno: 0x0002 e_res: 0x010BC911854579C0 e_oemid: 0x011F e_oeminfo: 0x50D3 e_res2: 0xE2F73D90005C0000F3F7C139DB1948EB00000040 e_lfanew: 0x00000004
->File Header Machine: 0x014C (I386) NumberOfSections: 0x0000 TimeDateStamp: 0x7F61DB01 (GMT: Mon Sep 21 04:18:09 2037) PointerToSymbolTable: 0x7317D010 NumberOfSymbols: 0xF9EB4775 SizeOfOptionalHeader: 0x0008 Characteristics: 0x0002 (EXECUTABLE_IMAGE)
->Optional Header Magic: 0x010B (HDR32_MAGIC) MajorLinkerVersion: 0x11 MinorLinkerVersion: 0xC9 -> 17.201 SizeOfCode: 0x79C08545 SizeOfInitializedData: 0x50D3011F SizeOfUninitializedData: 0x3D90E2F7 AddressOfEntryPoint: 0x0000005C BaseOfCode: 0xC139F3F7 BaseOfData: 0x48EBDB19 ImageBase: 0x00400000 SectionAlignment: 0x00000004 FileAlignment: 0x00000004 MajorOperatingSystemVersion: 0xA30F MinorOperatingSystemVersion: 0x7D2D -> 41743.32045 MajorImageVersion: 0x4001 MinorImageVersion: 0x8D00 -> 16385.36096 MajorSubsystemVersion: 0x0004 MinorSubsystemVersion: 0xCEEB -> 4.52971 Win32VersionValue: 0x00000000 SizeOfImage: 0x2263B6EB ; <------- important! SizeOfHeaders: 0x00000040 CheckSum: 0xBBED3153 Subsystem: 0x0002 (WINDOWS_GUI) DllCharacteristics: 0x0000 SizeOfStackReserve: 0x0154BE90 SizeOfStackCommit: 0x016A0040 SizeOfHeapReserve: 0x0000BF58 SizeOfHeapCommit: 0x00B10042 LoaderFlags: 0x12EB5757 NumberOfRvaAndSizes: 0x00000000 --- snip ---
The PE compressor used for most of these 4K/8K demos is named 'Crinkler':
--- quote --- Crinkler is an executable file compressor (or rather, a compressing linker) for Windows specifically targeted towards executables with a size of just a few kilobytes. As of 2018, it is the most widely used tool for compressing 4k intros.
Crinkler is being developed by Rune L. H. Stubbe (Mentor/TBC) and Aske Simon Christensen (Blueberry/Loonies). --- quote ---
The compression itself and some parts of imports resolver are nicely covered here:
http://code4k.blogspot.de/2010/12/crinkler-secrets-4k-intro-executable.html
The decompression area for code, data etc. starts usually at fixed 0x420000 address range. One can easily bypass all the decompression stuff from entry and set a hardware breakpoint on execution to 0x420000.
NOTE: Not all 8K demos from http://www.pouet.net can be fixed in Wine nor run in modern Windows (bug 42125). Crinkler uses the PE optional header 'SizeOfImage' field to have the loader allocate a huge chunk of memory used for decompression.
Memory map:
--- snip --- Address Size Owner Section Contains 00110000 00010000 00220000 00001000 Process Parameters 00230000 00003000 Environment 00400000 2263C000 lns-lpt-psyltcipher_720 PE header (+SizeOfImage) 22A40000 00001000 22A41000 00001000 22A42000 016AE000 Stack of main thread 7B420000 00001000 KERNEL32 PE header 7B421000 00221000 KERNEL32 .text Code 7B642000 001B1000 KERNEL32 .data Data,imports,exports, .. 7BC30000 00001000 ntdll PE header 7BC31000 000BF000 ntdll .text Code 7BCF0000 0001D000 ntdll .data Data,exports,resources 7FFD8000 00004000 Data block of main thread 7FFDF000 00001000 Process Environment Block 7FFE0000 00010000 ... --- snip ---
https://github.com/wine-staging/wine-staging/blob/master/patches/kernel32-PE...
Relevant part of Crinkler code:
--- snip --- ; PE entry 0040005C 53 PUSH EBX ; PEB, see later 0040005D 31ED XOR EBP,EBP 0040005F BB 02000000 MOV EBX,2 00400064 90 NOP 00400065 BE 54014000 MOV ESI,OFFSET 00400154 0040006A 6A 01 PUSH 1 0040006C 58 POP EAX 0040006D BF 00004200 MOV EDI,OFFSET 00420000 00400072 B1 00 MOV CL,0 00400074 57 PUSH EDI 00400075 57 PUSH EDI 00400076 EB 12 JMP SHORT 0040008A ...
; OEP after decompression 00420000 5F POP EDI 00420001 B9 1D000000 MOV ECX,1D 00420006 B0 E8 MOV AL,0E8 00420008 AE SCAS BYTE PTR ES:[EDI] 00420009 75 FB JNE SHORT 00420006 0042000B 8B07 MOV EAX,DWORD PTR DS:[EDI] 0042000D 98 CWDE 0042000E 3B07 CMP EAX,DWORD PTR DS:[EDI] 00420010 75 F4 JNE SHORT 00420006 00420012 29F8 SUB EAX,EDI 00420014 98 CWDE 00420015 AB STOS DWORD PTR ES:[EDI] 00420016 E2 EE LOOP SHORT 00420006 00420018 BB 08014000 MOV EBX,OFFSET 00400108 0042001D BE D3124200 MOV ESI,OFFSET 004212D3 00420022 BF 00004300 MOV EDI,OFFSET 00430000 00420027 58 POP EAX ; was EBX -> PEB 00420028 8B40 0C MOV EAX,DWORD PTR DS:[EAX+0C] ; PEB_LDR_DATA ; InLoadOrderModuleList->LDR_DATA_TABLE_ENTRY 0042002B 8B40 0C MOV EAX,DWORD PTR DS:[EAX+0C] ; LDR_DATA_TABLE_ENTRY->InLoadOrderLinks 0042002E 8B00 MOV EAX,DWORD PTR DS:[EAX] 00420030 8B00 MOV EAX,DWORD PTR DS:[EAX] ; Flink ; _LDR_DATA_TABLE_ENTRY.DllBase (kernel32) 00420032 8B68 18 MOV EBP,DWORD PTR DS:[EAX+18] 00420035 31C0 XOR EAX,EAX 00420037 AC LODS BYTE PTR DS:[ESI] ; "user32" 00420038 85ED TEST EBP,EBP 0042003A 75 12 JNE SHORT 0042004E 0042003C 85C0 TEST EAX,EAX 0042003E 74 5B JE SHORT 0042009B 00420040 6A 00 PUSH 0 00420042 6A 00 PUSH 0 00420044 52 PUSH EDX ; "d3d11" 00420045 6A 00 PUSH 0 00420047 FF15 180043. CALL DWORD PTR DS:[430018] ; user32.MessageBoxA 0042004D C3 RETN ... --- snip ---
$ sha1sum lns-* 482e8d0fe4b5e6f7ffa6f2125143da5aadab34ad lns-lpt-psyltcipher_1080.exe 1da4738309c2738f5f89c4713c689a93b94cd898 lns-lpt-psyltcipher_1080_vsync.exe 7bab7cb1c8f528878b1547147d2c97dfa1032eab lns-lpt-psyltcipher_720.exe 85d1624523110af6c00cc53027e3b504ef3d5362 lns-lpt-psyltcipher.zip
$ du -sh lns-* 8.0K lns-lpt-psyltcipher_1080.exe 8.0K lns-lpt-psyltcipher_1080_vsync.exe 8.0K lns-lpt-psyltcipher_720.exe 24K lns-lpt-psyltcipher.zip
$ wine --version wine-3.4-256-g725ad420e1
Regards
https://bugs.winehq.org/show_bug.cgi?id=44860
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- Staged patchset| |https://github.com/wine-sta | |ging/wine-staging/blob/mast | |er/patches/kernel32-PE_Load | |er_Fixes/0003-kernel32-On-p | |rocess-entry-store-PEB-addr | |ess-in-ebx.patch Status|NEW |STAGED URL| |http://www.pouet.net/prod.p | |hp?which=66502 Keywords| |download, obfuscation
https://bugs.winehq.org/show_bug.cgi?id=44860
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- Depends on| |42125
https://bugs.winehq.org/show_bug.cgi?id=44860
Dmitry Timoshkov dmitry@baikal.ru changed:
What |Removed |Added ---------------------------------------------------------------------------- Fixed by SHA1| |8b929bd759334611c0c95748206 | |0168fe441cd5f Status|STAGED |RESOLVED Resolution|--- |FIXED
--- Comment #1 from Dmitry Timoshkov dmitry@baikal.ru --- The result of investigation in the staged patch has been silently incorporated during the process start up restructuring in September-December, and basically the staged patch was superseded.
https://bugs.winehq.org/show_bug.cgi?id=44860
--- Comment #2 from Anastasius Focht focht@gmx.net --- Hello Dmitry,
thanks, I found it still worthwhile to document with some code/explanations -> tracebility ;-)
Regards
https://bugs.winehq.org/show_bug.cgi?id=44860
--- Comment #3 from Dmitry Timoshkov dmitry@baikal.ru --- (In reply to Anastasius Focht from comment #2)
Hello Dmitry,
thanks, I found it still worthwhile to document with some code/explanations -> tracebility ;-)
And many thanks for the additional information, it's always a fascinating reading :) For instance at the time of my investigation I didn't know name of the tool that was used for compressing the demo I was playing with in the debugger.
https://bugs.winehq.org/show_bug.cgi?id=44860
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- Resolution|FIXED |--- Status|RESOLVED |REOPENED
--- Comment #4 from Anastasius Focht focht@gmx.net --- Hello Dmitry,
but that code has been reworked again in the meantime, causing a regression:
--- snip --- $ winedbg ./lns-lpt-psyltcipher_720.exe WineDbg starting on pid 002d DbgBreakPoint () at /home/focht/projects/wine/wine.repo/src/include/winternl.h:2215 0x7b46b134 DbgBreakPoint+0x4 [/home/focht/projects/wine/wine.repo/src/include/winternl.h:2215] in kernel32: nop 2215 static inline void WINAPI DbgBreakPoint(void) { __asm__ __volatile__("int3"); }
Wine-dbg> disas 0x0040005c EntryPoint in lns-lpt-psyltcipher_720: pushl %ebx 0x0040005d: xorl %ebp,%ebp 0x0040005f: movl $0x2,%ebx 0x00400064: nop 0x00400065: movl $0x400154,%esi 0x0040006a: pushl $0x1 0x0040006c: popl %eax 0x0040006d: movl $0x420000,%edi 0x00400072: movb $0x0,%cl 0x00400074: pushl %edi
Wine-dbg>b *0x40005C Breakpoint 1 at 0x0040005c EntryPoint in lns-lpt-psyltcipher_720
Wine-dbg>c Stopped on breakpoint 1 at 0x0040005c EntryPoint in lns-lpt-psyltcipher_720
Wine-dbg>info reg Register dump: CS:0023 SS:002b DS:002b ES:002b FS:0063 GS:006b EIP:0040005c ESP:240efeb4 EBP:240efec8 EFLAGS:00000212( - -- I -A- - ) EAX:240effe4 EBX:240effe4 ECX:240efed0 EDX:00000001 ESI:00000000 EDI:00000000 --- snip ---
I'm re-opening this here to track the regression.
Regards
https://bugs.winehq.org/show_bug.cgi?id=44860
Dmitry Timoshkov dmitry@baikal.ru changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|REOPENED |NEW
--- Comment #5 from Dmitry Timoshkov dmitry@baikal.ru --- (In reply to Anastasius Focht from comment #4)
Hello Dmitry,
but that code has been reworked again in the meantime, causing a regression:
...
I'm re-opening this here to track the regression.
I assume that the demo works in wine-staging 2.21, does it still work in wine-staging 3.4?
Are you planning to perform a regression test?
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
https://bugs.winehq.org/show_bug.cgi?id=44860
--- Comment #7 from Dmitry Timoshkov dmitry@baikal.ru --- (In reply to Anastasius Focht from comment #6)
Hello Dmitry,
turns out there was no regression at all.
Hi Anastasius,
You are correct in your analysis, I retested with 8k demos left from previous investigations eos_-_blue_morpho_1280x720.exe Serpent - Minimal - 720p.exe Serpent - Minimal - native.exe and they all crash with current wine.git (3.5+) but still work with wine-staging 3.5. Manually applying staged patches shows that it's still necessary to have 0003-kernel32-On-process-entry-store-PEB-address-in-ebx.patch and without it the demos will crash.
https://bugs.winehq.org/show_bug.cgi?id=44860
Peter De Schrijver p2@psychaos.be changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |p2@psychaos.be
https://bugs.winehq.org/show_bug.cgi?id=44860
pattietreutel katyaberezyaka@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |katyaberezyaka@gmail.com
https://bugs.winehq.org/show_bug.cgi?id=44860
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- Staged patchset|https://github.com/wine-sta |https://github.com/wine-sta |ging/wine-staging/blob/mast |ging/wine-staging/tree/mast |er/patches/kernel32-PE_Load |er/patches/kernel32-PE_Load |er_Fixes/0003-kernel32-On-p |er_Fixes |rocess-entry-store-PEB-addr | |ess-in-ebx.patch |
--- Comment #8 from Anastasius Focht focht@gmx.net --- Hello folks,
revisiting, the issue seems no longer present. Apparently the compilers no longer generate code that clobbers EBX in 'start_process'.
The original piece of code is still here (comment #6), albeit moved due to various refactoring of Wine process startup/environment setup code.
https://source.winehq.org/git/wine.git/blob/HEAD:/dlls/kernel32/process.c#l1...
--- snip --- 123 /*********************************************************************** 124 * __wine_start_process 125 * 126 * Startup routine of a new process. Runs on the new process stack. 127 */ 128 #ifdef __i386__ 129 void CDECL start_process( LPTHREAD_START_ROUTINE entry, PEB *peb ) 130 #else 131 void CDECL __wine_start_process( LPTHREAD_START_ROUTINE entry, PEB *peb ) 132 #endif 133 { 134 BOOL being_debugged; 135 136 if (!entry) 137 { 138 ERR( "%s doesn't have an entry point, it cannot be executed\n", 139 debugstr_w(peb->ProcessParameters->ImagePathName.Buffer) ); 140 ExitThread( 1 ); 141 } 142 143 TRACE_(relay)( "\1Starting process %s (entryproc=%p)\n", 144 debugstr_w(peb->ProcessParameters->ImagePathName.Buffer), entry ); 145 146 __TRY 147 { 148 if (!CheckRemoteDebuggerPresent( GetCurrentProcess(), &being_debugged )) 149 being_debugged = FALSE; 150 151 SetLastError( 0 ); /* clear error code */ 152 if (being_debugged) DbgBreakPoint(); 153 ExitThread( call_process_entry( peb, entry )); 154 } 155 __EXCEPT(UnhandledExceptionFilter) 156 { 157 TerminateProcess( GetCurrentProcess(), GetExceptionCode() ); 158 } 159 __ENDTRY 160 abort(); /* should not be reached */ 161 } --- snip ---
Both, LLVM MinGW (https://github.com/mstorsjo/llvm-mingw/releases/tag/20191230) and GCC 8.x/9.x produce identical code for this function.
EBX is used in debug/trace leaf functions but they properly save/restore it.
--- snip --- ; var_70 = dword ptr -70h ; var_6C = dword ptr -6Ch ; being_debugged = dword ptr -64h ; __f = __WINE_FRAME ptr -60h ; entry = dword ptr 8 ; peb = dword ptr 0Ch
7B4525D0 lea ecx, [esp+4] 7B4525D4 and esp, 0FFFFFFF0h 7B4525D7 push dword ptr [ecx-4] 7B4525DA push ebp 7B4525DB mov ebp, esp 7B4525DD push ecx 7B4525DE sub esp, 74h 7B4525E1 mov eax, [ecx] 7B4525E3 mov edx, [ecx+4] 7B4525E6 mov [ebp+var_70], eax 7B4525E9 mov [ebp+var_6C], edx 7B4525EC test eax, eax 7B4525EE jz loc_7B4526B8 7B4525F4 test __wine_dbch_relay.flags, 8 7B4525FB jnz short loc_7B452637 7B4525FD lea eax, [ebp+__f] 7B452600 push ecx 7B452601 push ecx 7B452602 push eax 7B452603 lea eax, [ebp+__f.jmp] 7B452606 push eax 7B452607 mov [ebp+__f.frame.Handler], offset __wine_exception_handler 7B45260E mov dword ptr [ebp+__f.u], offset UnhandledExceptionFilter 7B452615 call __wine_setjmpex 7B45261A add esp, 10h 7B45261D test eax, eax 7B45261F jz short loc_7B452666 7B452621 push eax 7B452622 push eax 7B452623 mov eax, [ebp+__f.ExceptionRecord] 7B452626 push dword ptr [eax+50h] 7B452629 push 0FFFFFFFFh 7B45262B call TerminateProcess 7B452630 pop eax 7B452631 pop edx 7B452632 call abort 7B452637 mov eax, [ebp+var_6C] 7B45263A mov eax, [eax+10h] 7B45263D mov eax, [eax+3Ch] 7B452640 call wine_dbgstr_wn_10 7B452645 push edx 7B452646 push edx 7B452647 push [ebp+var_70] 7B45264A push eax 7B45264B push offset byte_7B475524 ; format 7B452650 push offset __FUNCTION___30260 ; "start_process" 7B452655 push offset __wine_dbch_relay ; channel 7B45265A push 3 ; cls 7B45265C call wine_dbg_log 7B452661 add esp, 20h 7B452664 jmp short loc_7B4525FD 7B452666 lea eax, [ebp+__f] 7B452669 mov edx, large fs:0 7B452670 mov [eax], edx 7B452672 mov large fs:0, eax 7B452678 push eax 7B452679 push eax 7B45267A lea eax, [ebp+being_debugged] 7B45267D push eax 7B45267E push 0FFFFFFFFh 7B452680 call CheckRemoteDebuggerPresent 7B452685 pop edx 7B452686 pop ecx 7B452687 test eax, eax 7B452689 jz short loc_7B4526F6 7B45268B mov eax, large fs:18h 7B452691 cmp [ebp+being_debugged], 0 7B452695 mov dword ptr [eax+34h], 0 7B45269C jz short loc_7B4526A3 7B45269E call DbgBreakPoint 7B4526A3 push ecx 7B4526A4 push ecx 7B4526A5 push [ebp+var_70] 7B4526A8 push [ebp+var_6C] 7B4526AB call call_process_entry 7B4526B0 mov [esp], eax 7B4526B3 call ExitThread 7B4526B8 test __wine_dbch_process_0.flags, 2 7B4526BF jz short loc_7B4526EC 7B4526C1 mov eax, [ebp+var_6C] 7B4526C4 mov eax, [eax+10h] 7B4526C7 mov eax, [eax+3Ch] 7B4526CA call wine_dbgstr_wn_10 7B4526CF sub esp, 0Ch 7B4526D2 push eax 7B4526D3 push offset aSDoesnTHaveAnE ; "%s doesn't have an entry point,.." 7B4526D8 push offset __FUNCTION___30260 ; "start_process" 7B4526DD push offset __wine_dbch_process_0 ; channel 7B4526E2 push 1 ; cls 7B4526E4 call wine_dbg_log 7B4526E9 add esp, 20h 7B4526EC sub esp, 0Ch 7B4526EF push 1 7B4526F1 call ExitThread 7B4526F6 mov [ebp+being_debugged], 0 7B4526FD jmp short loc_7B45268B --- snip ---
The was considerable rework of debug trace functionality around April 2019 (inlining functions/exports etc.) which is very likely the reason.
https://source.winehq.org/git/wine.git/history/HEAD:/include/wine/debug.h
I consider it fixed (for now) and suggest to drop https://github.com/wine-staging/wine-staging/blob/master/patches/kernel32-PE... unless there is still a plan to eventually upstream it to mainline.
What do you think Dmitry.
$ wine --version wine-5.3
Regards
https://bugs.winehq.org/show_bug.cgi?id=44860
--- Comment #9 from Dmitry Timoshkov dmitry@baikal.ru --- (In reply to Anastasius Focht from comment #8)
I consider it fixed (for now) and suggest to drop https://github.com/wine-staging/wine-staging/blob/master/patches/kernel32- PE_Loader_Fixes/0003-kernel32-On-process-entry-store-PEB-address-in-ebx. patch unless there is still a plan to eventually upstream it to mainline.
What do you think Dmitry.
Since this highly depends on compiler behaviour (version, optimizations, register usage) I'd guess that the patch could still be useful for older compilers or not optimal configurations.
https://bugs.winehq.org/show_bug.cgi?id=44860
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|NEW |STAGED
--- Comment #10 from Anastasius Focht focht@gmx.net --- Hello Dmitry,
--- quote --- Since this highly depends on compiler behaviour (version, optimizations, register usage) I'd guess that the patch could still be useful for older compilers or not optimal configurations. --- quote ---
thanks, makes sense. Marking the bug report 'staged' again, the status was somehow lost in 2018. Was there an attempt to upstream the patch yet? I couldn't find a reference in old 2018 mailing list archive.
Regards
https://bugs.winehq.org/show_bug.cgi?id=44860
--- Comment #11 from Dmitry Timoshkov dmitry@baikal.ru --- (In reply to Anastasius Focht from comment #10)
Hello Dmitry,
--- quote --- Since this highly depends on compiler behaviour (version, optimizations, register usage) I'd guess that the patch could still be useful for older compilers or not optimal configurations. --- quote ---
thanks, makes sense. Marking the bug report 'staged' again, the status was somehow lost in 2018. Was there an attempt to upstream the patch yet? I couldn't find a reference in old 2018 mailing list archive.
No, I didn't send that patch set to winehq.
https://bugs.winehq.org/show_bug.cgi?id=44860 Bug 44860 depends on bug 42125, which changed state.
Bug 42125 Summary: 4k/8k demos often fail with 'Bad EXE Format' or 'error c0000020' due to Crinkler executable file compressor's "optimized" usage of PE header fields (loader compatibility) https://bugs.winehq.org/show_bug.cgi?id=42125
What |Removed |Added ---------------------------------------------------------------------------- Status|STAGED |RESOLVED Resolution|--- |FIXED
https://bugs.winehq.org/show_bug.cgi?id=44860
Dmitry Timoshkov dmitry@baikal.ru changed:
What |Removed |Added ---------------------------------------------------------------------------- Resolution|--- |FIXED Status|STAGED |RESOLVED Fixed by SHA1|8b929bd759334611c0c95748206 |360820fb5830750b23543dc3418 |0168fe441cd5f |8970aa9431835
--- Comment #12 from Dmitry Timoshkov dmitry@baikal.ru --- Committed as 360820fb5830750b23543dc34188970aa9431835.
https://bugs.winehq.org/show_bug.cgi?id=44860
Alexandre Julliard julliard@winehq.org changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|RESOLVED |CLOSED
--- Comment #13 from Alexandre Julliard julliard@winehq.org --- Closing bugs fixed in 5.9.
https://bugs.winehq.org/show_bug.cgi?id=44860
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- URL|http://www.pouet.net/prod.p |https://web.archive.org/web |hp?which=66502 |/20160208143329/http://loon | |ies.dk/demos/bin/lns-lpt-ps | |yltcipher.zip