https://bugs.winehq.org/show_bug.cgi?id=39570
Bug ID: 39570 Summary: Multiple application crash handlers fail to load symbol information using 'dbghelp.SymLoadModule64', reporting 'dbghelp:validate_addr64 Unsupported address 0xfffffffffxxxxxxx' Product: Wine Version: 1.7.54 Hardware: x86-64 OS: Linux Status: NEW Severity: normal Priority: P2 Component: dbghelp Assignee: wine-bugs@winehq.org Reporter: focht@gmx.net Distribution: ---
Hello folks,
the issue/question was raised in https://bugs.winehq.org/show_bug.cgi?id=32237#c15
--- quote --- I did try 2012 this time and I end up crashing
fixme:dbghelp:validate_addr64 Unsupported address fffffffff33a0000 err:seh:raise_exception Unhandled exception code c0000005 flags 0 addr 0x7bc3db51
What's wrong with the address? --- quote ---
Searching the Internet reveals this pattern/message many times - also in Wine Bugzilla - but no or even incorrect explanation - until now ;-)
On 64-bit Linux machines, the Wine loader allows 32-bit dlls being mapped at high >2GB, >3GB address ranges in 32-bit processes, not having certain (design) restrictions of 32-bit process address space layout on 64-bit Windows machines (even with /LARGEADDRESSWARE).
Good case, 32-bit Wine builtin dll mapped < 2 GiB virtual address space range:
--- snip --- ... 0009:Call PE DLL (proc=0x7e1b6838,module=0x7e1b0000 L"wsock32.dll",reason=PROCESS_ATTACH,res=0x1) ... 0027:Call dbghelp.SymLoadModule64(ffffffff,00000000,0b36a960 "C:\windows\system32\wsock32.dll",0b36a988 "wsock32.dll",7e1b0000,00000000,0000e000) ret=005eff32 0027:trace:dbghelp:SymLoadModuleEx (0xffffffff (nil) "C:\windows\system32\wsock32.dll" "wsock32.dll" 7e1b0000 0000e000 (nil) 00000000) ... 0027:trace:dbghelp:SymLoadModuleExW (0xffffffff (nil) L"C:\windows\system32\wsock32.dll" L"wsock32.dll" 7e1b0000 0000e000 (nil) 00000000) ... 0027:trace:dbghelp:elf_load_file Processing elf file 'L"/home/focht/projects/wine/wine.repo/install/bin/../lib/wine/wsock32.dll.so"' at 7e1a2000 ... 0027:Ret dbghelp.SymLoadModule64() retval=7e1b0000 ret=005eff32 --- snip ---
Bad case, 32-bit Wine builtin dll mapped near end of 4 GiB virtual address space range:
--- snip --- ... 0009:Call PE DLL (proc=0xf734e3fc,module=0xf72f0000 L"winex11.drv",reason=PROCESS_ATTACH,res=(nil)) ... 0027:Call dbghelp.SymLoadModule64(ffffffff,00000000,0b36a960 "C:\windows\system32\winex11.drv",0b36a988 "winex11.drv",f72f0000,ffffffff,00090000) ret=005eff32 0027:trace:dbghelp:SymLoadModuleEx (0xffffffff (nil) "C:\windows\system32\winex11.drv" "winex11.drv" fffffffff72f0000 00090000 (nil) 00000000) "winex11.drv",ffffffff,2d053b40,0000000c) ret=edbc2fa6 ... 0027:trace:dbghelp:SymLoadModuleExW (0xffffffff (nil) L"C:\windows\system32\winex11.drv" L"winex11.drv" fffffffff72f0000 00090000 (nil) 00000000) 0027:fixme:dbghelp:validate_addr64 Unsupported address fffffffff72f0000 ... 0027:Ret dbghelp.SymLoadModule64() retval=00000000 ret=005eff32 --- snip ---
In this specific case, the game registered an own crash handler which dumps various debugging information in case of a crash.
'dbghelp.SymLoadModule64' is called by the custom crash handler.
Source: https://source.winehq.org/git/wine.git/blob/1fa7710ff92dd9555b2b4753e22ce5fc...
--- snip --- 656 DWORD64 WINAPI SymLoadModule64(HANDLE hProcess, HANDLE hFile, PCSTR ImageName, 657 PCSTR ModuleName, DWORD64 BaseOfDll, DWORD SizeOfDll) 658 { 659 return SymLoadModuleEx(hProcess, hFile, ImageName, ModuleName, BaseOfDll, SizeOfDll, 660 NULL, 0); 661 } --- snip ---
So how does high DWORD of 'BaseOfDll' parameter get the 0xffffffff value?
A few caller frames up in the app crash handler:
--- snip --- ... 005F06D6 8B55 D0 MOV EDX,DWORD PTR SS:[EBP-30] 005F06D9 8B45 CC MOV EAX,DWORD PTR SS:[EBP-34] 005F06DC 8B4D F8 MOV ECX,DWORD PTR SS:[EBP-8] 005F06DF 52 PUSH EDX 005F06E0 99 CDQ 005F06E1 52 PUSH EDX ; high DWORD BaseOfDll 005F06E2 50 PUSH EAX ; low DWORD BaseOfDll 005F06E3 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4] 005F06E6 50 PUSH EAX 005F06E7 51 PUSH ECX 005F06E8 8B4D E8 MOV ECX,DWORD PTR SS:[EBP-18] 005F06EB 56 PUSH ESI 005F06EC E8 EFF7FFFF CALL A_Slower.005EFEE0 ... --- snip ---
'winex11.drv' -> 0xf72f0000
Since the highest bit in low 32-bit 'BaseOfDll' DWORD is set, the 'CDQ' instruction copies the sign (bit 31) of the value in the EAX register into every bit position in the EDX register.
Voila - you get the 0xffffffff EDX value which is then propagated through the caller chain as high 32-bit 'BaseOfDll' DWORD to 'dbghelp.SymLoadModule64', leading to symbol load failure and fixme/warning messages.
This should be fixed, allowing symbol information even for dlls mapped in high address range to be loaded.
$ wine --version wine-1.7.54-261-g61c49bd
Regards