https://bugs.winehq.org/show_bug.cgi?id=38714
Bug ID: 38714 Summary: 64-bit ARM Windows applications from Windows SDK crash in entry (loader needs to set/randomize cookie for PE modules) Product: Wine Version: 1.7.44 Hardware: aarch64 OS: Linux Status: NEW Severity: normal Priority: P2 Component: ntdll Assignee: wine-bugs@winehq.org Reporter: focht@gmx.net Distribution: ---
Hello folks,
this is more an educated guess since I only have remote access to some 64-bit ARM Linux VM without proper debugging tools. Winedbg/gdb proxy is unusable as of now and my shiny JTAG Debugger for Cortex-A5x (ICD) can't work "remotely".
Anyway, I think I gathered enough information without the need for debugging.
Don't complain about 'root' - it's not my machine :)
--- snip --- # wine64 winedbg arm64/mt.exe
Wine-dbg>info process pid threads executable (all id:s are in hex)
00000024 1 'mt.exe'
00000026 2 _ 'wineconsole.exe' 00000014 4 'explorer.exe' 0000000e 5 'services.exe' 0000001b 3 _ 'plugplay.exe' 00000012 3 _ 'winedevice.exe'
Wine-dbg>info thread process tid prio (all id:s are in hex) 0000000e services.exe 0000001e 0 0000001d 0 00000016 0 00000010 0 0000000f 0 00000012 winedevice.exe 0000001a 0 00000019 0 00000013 0 00000014 explorer.exe 00000023 0 00000022 0 00000021 0 00000015 0 0000001b plugplay.exe 00000020 0 0000001f 0 0000001c 0 00000024 (D) Z:\root\wine\64\arm64\mt.exe 00000025 0 <== 00000026 wineconsole.exe 00000028 0 00000027 0 --- snip ---
--- snip --- Wine-dbg>si be_arm64_single_step: not done Unhandled exception: illegal instruction in 64-bit code (0x000000014010ce78). Register dump: ARM64 EL0t Mode Pc:000000014010ce78 Sp:0000007f8aa6fe20 Lr:000000014010ca7c Pstate:0000000060000000(-ZC-) x0: 0000007f8bd0c000 x1: 0000000000000005 x2: 0000007f8bd0e000 x3: 0000000000000001 x4: 0000000000000001 x5: f5183970d346f95f x6: 0000000000000001 x7: 0000000000000002 x8: 00002b992ddfa232 x9: 00002b992ddfa232 x10:00000000031bb537 x11:0000007f8bd0f078 x12:0000007ffb057a54 x13:0000007ffb057a58 x14:0000007ffb057b20 x15:0000007f8bb35908 ip0:0000007f8b966120 ip1:0000007f8b9c9e10 x18:0000007f8bb359d0 x19:0000007f8bd0c000 x20:000000014010ca70 x21:0000000000000000 x22:0000007f8b949000 x23:0000007f8acd3584 x24:0000007f8acfd000 x25:0000007f8aee07f0 x26:0000007ffb057e90 x27:0000007ffb057e08 x28:0000007f8ad15000 Fp:0000007f8aa6fe20 Stack dump: 0x0000007f8aa6fe20: 0000007f8aa6fe30 0000007f8acd35e0 0x0000007f8aa6fe30: 0000007f8aa6fe60 0000007f8b9310ac 0x0000007f8aa6fe40: 0000007f8acd3584 0000007f8bd0c000 0x0000007f8aa6fe50: 0000000000000000 0000000000000000 0x0000007f8aa6fe60: 0000007f8aa6ffe0 0000007f8b90ca20 0x0000007f8aa6fe70: 0000007f8bd0c000 0000007f8acd3584 0x0000007f8aa6fe80: ffffffffffffffff 0000007f8b941ab4 0x0000007f8aa6fe90: 0000007f8acb67cc 0000007f8acd3584 0x0000007f8aa6fea0: 0000007f8bd0c000 0000000000000000 0x0000007f8aa6feb0: 0000007f8b949000 0000007f8acd3584 0x0000007f8aa6fec0: 0000007f8acfd000 0000007f8aee07f0 0x0000007f8aa6fed0: 0000007ffb057e90 0000007ffb057e08 Backtrace: =>0 0x000000014010ce78 in mt (+0x10ce78) (0x0000007f8aa6fe20) 1 0x000000014010ca7c in mt (+0x10ca7b) (0x0000007f8aa6fe20) ... --- snip ---
The entry point code of the app:
--- snip --- entry: 0000000140020300 STP X29, X30, [SP,#-0x10]! 0000000140020304 MOV X29, SP 0000000140020308 BL 140020E40 000000014002030C BL 140020318 0000000140020310 LDP X29, X30, [SP],#0x10 0000000140020314 RET ... 0000000140020E40 ADRP X8, #0x140030000 ; .data 0000000140020E44 LDR X8, [X8,#0x800] ; offset to cookie 000000014010CE68 CBZ X8, 14010CE78 000000014010CE6C LDR X9, =0x2B992DDFA232 ; default cookie arm64? 000000014010CE70 CMP X8, X9 000000014010CE74 B.NE 14010CE7C 000000014010CE78 BRK #0xF003 ; whoops, bail here 000000014010CE7C MVN X8, X8 0000000140020E60 ADRP X9, #0x140030000 0000000140020E64 STR X8, [X9,#0x808] 000000014010CE88 RET
.data: ... 0000000140030800 DCQ 0x2B992DDFA232 ; module security cookie (default val) --- snip ---
Looks like the entry code checks for the default value of the security cookie and bails if it's still unmodified.
MSDN: https://msdn.microsoft.com/en-us/library/windows/desktop/ms680328%28v=vs.85%...
IMAGE_LOAD_CONFIG_DIRECTORY64 -> SecurityCookie (64-bit VA)
The loader needs to randomize the cookie for each module if present (= non-zero VA) before calling the entry.
---
Another tidbit:
For decoding the immediate field in the emitted 'brk' instruction I only found information for the Linux counterpart which says range 0x2000-0xffff is app/user-defined.
https://gcc.gnu.org/ml/gcc-patches/2013-11/msg02228.html
--- quote --- POSIX siginfo BRK #imm16 si_signo si_code Purpose ---------- -------- ------- -------
0000-0fff S/w breakpoint, reserved for debuggers 0000-3ff SIGTRAP TRAP_BRKPT- EL0 breakpoint (e.g. gdb) 0400-7ff SIGILL ILL_ILLTRP* EL1 breakpoint (e.g. kgdb) 0800-bff SIGILL ILL_ILLTRP* EL2 breakpoint 0c00-fff SIGILL ILL_ILLTRP* EL3 breakpoint
1000-1fff C/C++ runtime errors 1000 SIGABRT n/a libc abort() 1001 SIGFPE FPE_INTDIV integer divide by zero 1002 SIGFPE FPE_INTOVF integer overflow 1003 SIGFPE FPE_FLTDIV floating-point divide by zero 1004 SIGFPE FPE_FLTOVF floating-point overflow 1005 SIGFPE FPE_FLTUND floating-point underflow 1006 SIGFPE FPE_FLTRES floating-point inexact result 1007 SIGFPE FPE_FLTINV floating-point invalid op 1008 SIGFPE FPE_FLTSUB subscript out of range 1009-1fff SIGILL ILL_ILLTRP unused but reserved
2000-ffff SIGILL ILL_ILLOPC+ Guaranteed unused, resvd for apps
- This is the signal generated now for all values of BRK immediate. GDB currently uses "BRK #0"
* The EL1/EL2/EL3 breakpoints would deliver a SIGILL if they are executed by EL0 code, and caught by the EL1 kernel. A s/w debugger operating at a higher EL which placed such breakpoints would presumably catch them and handle them, without the EL1 kernel ever seeing them.
+ Immediate values 0x2000-ffff generate the same signal as any other UNDEFINED instruction encoding, but with guaranteed behaviour for JITs etc. The original imm16 value could be made available in the si_trapno field of the signal context. --- quote ---
Regards