http://bugs.winehq.org/show_bug.cgi?id=36737
Bug ID: 36737 Summary: Steel Armor: Blaze of War crashes on start with built-in msvcr80 Product: Wine Version: 1.7.20 Hardware: x86 OS: Linux Status: NEW Severity: normal Priority: P2 Component: msvcrt Assignee: wine-bugs@winehq.org Reporter: gyebro69@gmail.com
Created attachment 48785 --> http://bugs.winehq.org/attachment.cgi?id=48785 +msvcrt,+relay debug log (uncompressed 30 MB)
After starting the game and skipping the intro video the game crashes during the initial loading stage (when the progress bar reaches 54%). There's no Wine crash dialog, the game quits silently and opens a 'last_bug.txt' file in notepad which contains the following text: 'Critical error 001: An error has occurred while initializing the program'
The game installs various DirectX runtime components and MSVC++ 2010 libraries.
'winetricks vcrun2005' allows the game to load properly. It seems Wine's built-in msvcr80 component does something wrong, because the problem doesn't occur with native msvcr80.
There is no demo version of Steel Armor: Blaze of War.
http://bugs.winehq.org/show_bug.cgi?id=36737
--- Comment #1 from Béla Gyebrószki gyebro69@gmail.com --- Created attachment 48786 --> http://bugs.winehq.org/attachment.cgi?id=48786 plain terminal output
http://bugs.winehq.org/show_bug.cgi?id=36737
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |focht@gmx.net Summary|Steel Armor: Blaze of War |Steel Armor: Blaze of War |crashes on start with |crashes on start with |built-in msvcr80 |built-in msvcr80 (malloc | |and operator new are | |required to return memory | |on a 16-byte boundary)
--- Comment #2 from Anastasius Focht focht@gmx.net --- Hello folks,
confirming.
I found a distributed "backup" and debugged it.
--- snip --- $ WINEDEBUG=+tid,+seh,+relay,+snoop,+msvcrt wine ./starter.exe root/programs/topgame.progpack >>log.txt 2>&1 ... 0024:Call KERNEL32.LoadLibraryA(0083a71d "bin\rel\x86\adv_render.codelib") ret=1000a810 ... 0024:Ret KERNEL32.LoadLibraryA() retval=00c10000 ret=1000a810 ... 0024:Call msvcr80._aligned_malloc(00000004,00000010) ret=00c28336 0024:trace:msvcrt:_aligned_malloc (4, 16) 0024:trace:msvcrt:_aligned_offset_malloc (4, 16, 0) 0024:Call ntdll.RtlAllocateHeap(00820000,00000000,00000018) ret=7e2f1515 0024:Ret ntdll.RtlAllocateHeap() retval=0089ed00 ret=7e2f1515 0024:Ret msvcr80._aligned_malloc() retval=0089ed10 ret=00c28336 0024:Call msvcr80._aligned_malloc(00000004,00000010) ret=00c3b2cd 0024:trace:msvcrt:_aligned_malloc (4, 16) 0024:trace:msvcrt:_aligned_offset_malloc (4, 16, 0) 0024:Call ntdll.RtlAllocateHeap(00820000,00000000,00000018) ret=7e2f1515 0024:Ret ntdll.RtlAllocateHeap() retval=008a41f8 ret=7e2f1515 0024:Ret msvcr80._aligned_malloc() retval=008a4200 ret=00c3b2cd 0024:Call msvcr80.memcpy(008a4200,00000000,00000000) ret=00c3b2e0 0024:Ret msvcr80.memcpy() retval=008a4200 ret=00c3b2e0 0024:Call msvcr80.??2@YAPAXI@Z(00000150) ret=00c24c6e 0024:Call ntdll.RtlAllocateHeap(00820000,00000000,00000150) ret=7e2f0c03 0024:Ret ntdll.RtlAllocateHeap() retval=008a18b8 ret=7e2f0c03 0024:trace:msvcrt:MSVCRT_operator_new (336) returning 0x8a18b8 0024:Ret msvcr80.??2@YAPAXI@Z() retval=008a18b8 ret=00c24c6e 0024:trace:seh:raise_exception code=c0000005 flags=0 addr=0xc242b7 ip=00c242b7 tid=0024 0024:trace:seh:raise_exception info[0]=00000000 0024:trace:seh:raise_exception info[1]=ffffffff 0024:trace:seh:raise_exception eax=008a18b8 ebx=00873950 ecx=008a4200 edx=7bcecbc8 esi=00000000 edi=00872960 0024:trace:seh:raise_exception ebp=0081d4a0 esp=0081d3ec cs=0023 ds=002b es=002b fs=0063 gs=006b flags=00010206 0024:trace:seh:call_stack_handlers calling handler at 0x3d4d00 code=c0000005 flags=0 ... --- snip ---
Although the game engine makes explicit use of '_aligned_malloc' to ensure 16-byte alignment for SSE instructions it also uses traditional MSVCRT operator 'new'.
It seems that 'msvcr80.MSVCRT_operator_new' must return 16-byte aligned memory chunks too.
--- snip --- ... 00C04C5E 8BF0 MOV ESI,EAX 00C04C60 68 50010000 PUSH 150 00C04C65 897424 30 MOV DWORD PTR SS:[ESP+30],ESI 00C04C69 E8 207D0100 CALL <JMP.&MSVCR80.??2@YAPAXI@Z> 00C04C6E 83C4 04 ADD ESP,4 00C04C71 85C0 TEST EAX,EAX 00C04C73 74 07 JE SHORT adv_rend.00C04C7C 00C04C75 E8 36F6FFFF CALL adv_rend.00C042B0 00C04C7A EB 02 JMP SHORT adv_rend.00C04C7E 00C04C7C 33C0 XOR EAX,EAX ... 00C042B0 0F2805 F0CEC200 MOVAPS XMM0,DQWORD PTR DS:[C2CEF0] 00C042B7 0F2900 MOVAPS DQWORD PTR DS:[EAX],XMM0 ; boom 00C042BA 0F280D 00CFC200 MOVAPS XMM1,DQWORD PTR DS:[C2CF00] 00C042C1 0F2948 10 MOVAPS DQWORD PTR DS:[EAX+10],XMM1 00C042C5 0F2815 10CFC200 MOVAPS XMM2,DQWORD PTR DS:[C2CF10] 00C042CC 0F2950 20 MOVAPS DQWORD PTR DS:[EAX+20],XMM2 00C042D0 0F281D 20CFC200 MOVAPS XMM3,DQWORD PTR DS:[C2CF20] 00C042D7 0F2958 30 MOVAPS DQWORD PTR DS:[EAX+30],XMM3 00C042DB 0F2940 40 MOVAPS DQWORD PTR DS:[EAX+40],XMM0 00C042DF 0F2948 50 MOVAPS DQWORD PTR DS:[EAX+50],XMM1 00C042E3 0F2950 60 MOVAPS DQWORD PTR DS:[EAX+60],XMM2 00C042E7 0F2958 70 MOVAPS DQWORD PTR DS:[EAX+70],XMM3 00C042EB F3:0F1005 0CE5C200 MOVSS XMM0,DWORD PTR DS:[C2E50C] 00C042F3 F3:0F1180 80000000 MOVSS DWORD PTR DS:[EAX+80],XMM0 00C042FB F3:0F1180 84000000 MOVSS DWORD PTR DS:[EAX+84],XMM0 --- snip ---
Interestingly the MSDN pages for various Visual Studio versions make different statements regarding 'malloc' alignment:
http://msdn.microsoft.com/en-us/library/ycsb6wwf%28vs.95%29.aspx
--- quote --- malloc Alignment
Visual Studio 2005
malloc is required to return memory on a 16-byte boundary. --- quote ---
http://msdn.microsoft.com/en-us/library/ycsb6wwf%28vs.90%29.aspx
--- quote --- malloc Alignment
Visual Studio 2008
malloc is required to return memory on a 16-byte boundary. --- quote ---
http://msdn.microsoft.com/en-us/library/ycsb6wwf%28vs.100%29.aspx
--- quote --- malloc Alignment
Visual Studio 2010
malloc is guaranteed to return memory that's aligned on a boundary that's suitable for storing any object that could fit in the amount of memory that's allocated. For example, a four-byte allocation is aligned on a boundary that supports any four-byte or smaller object. Memory alignment on a boundary that's suitable for an object that's larger than will fit in the allocation is not guaranteed. --- quote ---
http://msdn.microsoft.com/en-us/library/ycsb6wwf%28vs.110%29.aspx
--- quote --- malloc Alignment
Visual Studio 2012
malloc is guaranteed to return memory that's aligned on a boundary that's suitable for storing any object that could fit in the amount of memory that's allocated. For example, a four-byte allocation would be aligned on a boundary that supports any four-byte or smaller object. Memory alignment on a boundary that's suitable for a larger object than will fit in the allocation is not guaranteed. --- quote ---
http://msdn.microsoft.com/en-us/library/ycsb6wwf.aspx
--- quote --- malloc Alignment
Visual Studio 2013
malloc is guaranteed to return memory that's suitably aligned for storing any object that has a fundamental alignment and that could fit in the amount of memory that's allocated. A fundamental alignment is an alignment that's less than or equal to the largest alignment that's supported by the implementation without an alignment specification. (In Visual C++, this is the alignment that's required for a double, or 8 bytes. In code that targets 64-bit platforms, it’s 16 bytes.) For example, a four-byte allocation would be aligned on a boundary that supports any four-byte or smaller object. --- quote ---
With that part fixed the game runs further.
Regards
http://bugs.winehq.org/show_bug.cgi?id=36737
Piotr Caban piotr.caban@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |piotr.caban@gmail.com
--- Comment #3 from Piotr Caban piotr.caban@gmail.com --- (In reply to Anastasius Focht from comment #2)
--- quote ---
http://msdn.microsoft.com/en-us/library/ycsb6wwf%28vs.90%29.aspx
--- quote --- malloc Alignment
Visual Studio 2008
malloc is required to return memory on a 16-byte boundary.
I wrote a test for it and it's only true for 64-bit applications. 32-bit applications are aligned to 8 bytes. Checked with msvcr80.dll and msvcr90.dll.
The problem may be somewhere else or may be related to stack state after dll initialization.
A very simple tests that allocates 16-bytes blocks outputs (with native dll, 32-bit application): malloc(16): 00523810 malloc(16): 00524830 malloc(16): 00524848
And with builtin msvcr80.dll: malloc(16): 00411428 malloc(16): 00411440 malloc(16): 00411458
http://bugs.winehq.org/show_bug.cgi?id=36737
--- Comment #4 from Piotr Caban piotr.caban@gmail.com --- I'm not sure if it's the same bug but "Achtung Panzer Operation Star" game crashes in similar way (the progress bar also reaches 54%).
The demo is available here: http://www.graviteam.com/AP-STAR-demo/k43t_a1_demo_eng_04_setup.exe
http://bugs.winehq.org/show_bug.cgi?id=36737
--- Comment #5 from Piotr Caban piotr.caban@gmail.com --- The game uses _set_sbh_threshold function. I guess the crash may be related to it. Probably the "small allocations" heap uses different alignement.
http://bugs.winehq.org/show_bug.cgi?id=36737
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- Keywords| |download URL| |http://www.graviteam.com/AP | |-STAR-demo/k43t_a1_demo_eng | |_04_setup.exe Summary|Steel Armor: Blaze of War |Multiple Graviteam tank |crashes on start with |simulation games crash on |built-in msvcr80 (malloc |start with built-in msvcr80 |and operator new are |(malloc and operator new |required to return memory |are required to return |on a 16-byte boundary) |memory on a 16-byte | |boundary)
--- Comment #6 from Anastasius Focht focht@gmx.net --- Hello Piotr,
--- quote --- I'm not sure if it's the same bug but "Achtung Panzer Operation Star" game crashes in similar way (the progress bar also reaches 54%). --- quote ---
yes, it's the same issue (same game engine).
--- snip --- $ pwd /home/focht/.wine/drive_c/Program Files/Graviteam/Achtung Panzer Operation Star (demo)
$ WINEDEBUG=+tid,+seh,+relay,+msvcrt wine ./starter.exe >>log.txt 2>&1 ... 0023:Call KERNEL32.CreateProcessA(00000000,00884330 ""starter.exe" root\programs\opgame.progpack",00000000,00000000,00000000,00000000,00000000,00000000,0081ecb8,0081ec54) ret=1001253e ... 002f:Call KERNEL32.__wine_kernel_init() ret=7bc5a4b2 0023:Ret KERNEL32.CreateProcessA() retval=00000001 ret=1001253e ... 002f:Call PE DLL (proc=0x7e34a928,module=0x7e2e0000 L"msvcr80.dll",reason=PROCESS_ATTACH,res=(nil)) ... 002f:trace:msvcrt:DllMain (0x7e2e0000, DLL_PROCESS_ATTACH, (nil)) pid(2e), tid(2f), tls(0) ... 002f:Call KERNEL32.HeapCreate(00000000,00000000,00000000) ret=7e30c51f ... 002f:Ret KERNEL32.HeapCreate() retval=00820000 ret=7e30c51f ... 002f:Call KERNEL32.LoadLibraryA(0083b0dd "bin\rel\x86\adv_render.codelib") ret=1000a960 002f:Call PE DLL (proc=0xf3cb8c,module=0xf10000 L"adv_render.codelib",reason=PROCESS_ATTACH,res=(nil)) ... 002f:Ret KERNEL32.LoadLibraryA() retval=00f10000 ret=1000a960 ... 002f:Ret PE DLL (proc=0x1002691c,module=0x10000000 L"base_shell.codelib",reason=PROCESS_ATTACH,res=(nil)) retval=1 ... 002f:Call msvcr80._set_sbh_threshold(000003f8) ret=100010c8 002f:Ret msvcr80._set_sbh_threshold() retval=00000001 ret=100010c8 ... 002f:Call msvcr80._aligned_malloc(00000004,00000010) ret=00f29846 002f:trace:msvcrt:_aligned_malloc (4, 16) 002f:trace:msvcrt:_aligned_offset_malloc (4, 16, 0) 002f:Call ntdll.RtlAllocateHeap(00820000,00000000,00000018) ret=7e30b549 002f:Ret ntdll.RtlAllocateHeap() retval=0083e418 ret=7e30b549 002f:Ret msvcr80._aligned_malloc() retval=0083e420 ret=00f29846 002f:Call msvcr80._aligned_malloc(00000004,00000010) ret=00f1429d 002f:trace:msvcrt:_aligned_malloc (4, 16) 002f:trace:msvcrt:_aligned_offset_malloc (4, 16, 0) 002f:Call ntdll.RtlAllocateHeap(00820000,00000000,00000018) ret=7e30b549 002f:Ret ntdll.RtlAllocateHeap() retval=00840098 ret=7e30b549 002f:Ret msvcr80._aligned_malloc() retval=008400a0 ret=00f1429d 002f:Call msvcr80.memcpy(008400a0,00000000,00000000) ret=00f142b0 002f:Ret msvcr80.memcpy() retval=008400a0 ret=00f142b0 002f:Call msvcr80.??2@YAPAXI@Z(00000150) ret=00f25c3e 002f:Call ntdll.RtlAllocateHeap(00820000,00000000,00000150) ret=7e30ac37 002f:Ret ntdll.RtlAllocateHeap() retval=008ce6a8 ret=7e30ac37 002f:trace:msvcrt:MSVCRT_operator_new (336) returning 0x8ce6a8 002f:Ret msvcr80.??2@YAPAXI@Z() retval=008ce6a8 ret=00f25c3e 002f:trace:seh:raise_exception code=c0000005 flags=0 addr=0xf25267 ip=00f25267 tid=002f 002f:trace:seh:raise_exception info[0]=00000000 002f:trace:seh:raise_exception info[1]=ffffffff 002f:trace:seh:raise_exception eax=008ce6a8 ebx=008750f0 ecx=008400a0 edx=7bcecbc8 esi=00000000 edi=00874130 002f:trace:seh:raise_exception ebp=0081ea10 esp=0081e95c cs=0023 ds=002b es=002b fs=0063 gs=006b flags=00010202 002f:trace:seh:call_stack_handlers calling handler at 0x3a7040 code=c0000005 flags=0 ... 002f:Call msvcp80.?sputn@?$basic_streambuf@DU?$char_traits@D@std@@@std@@QAEHPBDH@Z(0081e23c,01261276 "001: An error has occurred while initializing the program",00000039) ret=10008009 --- snip ---
Disassembly (+0x15C30):
--- snip --- 00F25C30 68 50010000 PUSH 150 00F25C35 897424 30 MOV DWORD PTR SS:[ESP+30],ESI 00F25C39 E8 E66A0100 CALL <JMP.&MSVCR80.??2@YAPAXI@Z> 00F25C3E 83C4 04 ADD ESP,4 00F25C41 85C0 TEST EAX,EAX 00F25C43 74 07 JE SHORT adv_rend.00F25C4C 00F25C45 E8 16F6FFFF CALL adv_rend.00F25260 00F25C4A EB 02 JMP SHORT adv_rend.00F25C4E ... 00F25260 0F2805 70CEF400 MOVAPS XMM0,DQWORD PTR DS:[F4CE70] 00F25267 0F2900 MOVAPS DQWORD PTR DS:[EAX],XMM0 00F2526A 0F280D 80CEF400 MOVAPS XMM1,DQWORD PTR DS:[F4CE80] 00F25271 0F2948 10 MOVAPS DQWORD PTR DS:[EAX+10],XMM1 00F25275 0F2815 90CEF400 MOVAPS XMM2,DQWORD PTR DS:[F4CE90] 00F2527C 0F2950 20 MOVAPS DQWORD PTR DS:[EAX+20],XMM2 00F25280 0F281D A0CEF400 MOVAPS XMM3,DQWORD PTR DS:[F4CEA0] 00F25287 0F2958 30 MOVAPS DQWORD PTR DS:[EAX+30],XMM3 00F2528B 0F2940 40 MOVAPS DQWORD PTR DS:[EAX+40],XMM0 00F2528F 0F2948 50 MOVAPS DQWORD PTR DS:[EAX+50],XMM1 00F25293 0F2950 60 MOVAPS DQWORD PTR DS:[EAX+60],XMM2 00F25297 0F2958 70 MOVAPS DQWORD PTR DS:[EAX+70],XMM3 00F2529B F3:0F1005 F4E4F400 MOVSS XMM0,DWORD PTR DS:[F4E4F4] 00F252A3 F3:0F1180 80000000 MOVSS DWORD PTR DS:[EAX+80],XMM0 00F252AB F3:0F1180 84000000 MOVSS DWORD PTR DS:[EAX+84],XMM0 --- snip ---
$ sha1sum k43t_a1_demo_eng_04_setup.exe e96f4824365d31890ec4efa0f9e384de55dcdc47 k43t_a1_demo_eng_04_setup.exe
$ du -sh k43t_a1_demo_eng_04_setup.exe 721M k43t_a1_demo_eng_04_setup.exe
$ wine --version wine-1.7.20-62-g0b30276
Regards
http://bugs.winehq.org/show_bug.cgi?id=36737
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- Summary|Multiple Graviteam tank |Multiple Graviteam tank |simulation games crash on |simulation games crash on |start with built-in msvcr80 |start with built-in msvcr80 |(malloc and operator new |(small-block heap support |are required to return |needed) |memory on a 16-byte | |boundary) |
http://bugs.winehq.org/show_bug.cgi?id=36737
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- Fixed by SHA1| |608605c7dcb9584cf658e247938 | |c18fa13a7b0b2 Status|NEW |RESOLVED Resolution|--- |FIXED
--- Comment #7 from Anastasius Focht focht@gmx.net --- Hello folks,
this is fixed by commit http://source.winehq.org/git/wine.git/commitdiff/608605c7dcb9584cf658e247938...
Thanks Piotr
Regards
https://bugs.winehq.org/show_bug.cgi?id=36737
Alexandre Julliard julliard@winehq.org changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|RESOLVED |CLOSED
--- Comment #8 from Alexandre Julliard julliard@winehq.org --- Closing bugs fixed in 1.7.21.