https://bugs.winehq.org/show_bug.cgi?id=46194
Bug ID: 46194 Summary: Windows PowerShell Core 6.2 Preview 2 for ARM64 crashes due to decoding of instruction from incorrect PC (write watch access causes SIGSEGV) Product: Wine Version: 3.21 Hardware: aarch64 OS: Linux Status: NEW Severity: normal Priority: P2 Component: ntdll Assignee: wine-bugs@winehq.org Reporter: focht@gmx.net Distribution: ---
Hello folks,
essentially the same problem domain as bug 46187 ("Windows PowerShell Core 6.2 Preview 2 for ARM32 crashes due to unhandled trap_no 0 (write watch access causes SIGSEGV)")
Also mentioned briefly in bug 46155 ("Windows PowerShell Core 6.1 for ARM64 crashes on unimplemented function KERNEL32.dll.RaiseFailFastException") -> the failfast is a result of this one.
Download: https://github.com/PowerShell/PowerShell/releases
https://github.com/PowerShell/PowerShell/releases/download/v6.2.0-preview.2/...
--- snip --- $ WINEDEBUG=+seh,+loaddll,+virtual wine64 ./pwsh.exe ... 0009:trace:virtual:NtAllocateVirtualMemory 0xffffffffffffffff (nil) 003a0000 202000 00000004 0009:trace:virtual:map_view got mem in reserved area 0x18f30000-0x192d0000 0009:trace:virtual:VIRTUAL_DumpView View: 0x18f30000 - 0x192cffff (valloc) 0009:trace:virtual:VIRTUAL_DumpView 0x18f30000 - 0x192cffff -Hrw- 0009:trace:virtual:NtAllocateVirtualMemory 0xffffffffffffffff 0x18f30000 00090168 1000 00000004 0009:trace:virtual:VIRTUAL_DumpView View: 0x18f30000 - 0x192cffff (valloc) 0009:trace:virtual:VIRTUAL_DumpView 0x18f30000 - 0x18fc0fff cHrw- 0009:trace:virtual:VIRTUAL_DumpView 0x18fc1000 - 0x192cffff -Hrw- 0009:trace:seh:raise_exception code=c0000005 flags=0 addr=0x83fc2c pc=83fc2c tid=0009 0009:trace:seh:raise_exception info[0]=0000000000000000 0009:trace:seh:raise_exception info[1]=0000000018f30000 0009:trace:seh:raise_exception x0=0000000018f30000 x1=00000000002ad8a0 x2=0000000000000000 x3=0000000000000008 0009:trace:seh:raise_exception x4=000000007bd4bdf8 x5=000000007bd4bdb0 x6=0000007fba705f10 x7=0000007fba78a978 0009:trace:seh:raise_exception x8=000000000000c000 x9=00000000002ad9d8 x10=00000000ffffffff x11=00000000ffffffff 0009:trace:seh:raise_exception x12=0000000000000000 x13=0000000018f30040 x14=0000000000000001 x15=000000007bd2da70 0009:trace:seh:raise_exception x16=000000007bd2e010 x17=0000007fba895860 x18=000000007ffd8000 x19=0000000000a77348 0009:trace:seh:raise_exception x20=0000000018f30000 x21=0000000018f30000 x22=0000000000f30000 x23=0000000000090168 0009:trace:seh:raise_exception x24=0000000000a6a270 x25=00000000000000c4 x26=0000000000a69ea8 x27=0000000000030000 0009:trace:seh:raise_exception x28=0000000000595290 fp=00000000002ada30 lr=000000000083fbdc sp=00000000002ada30 0009:trace:seh:raise_exception pc=000000000083fc2c 0009:trace:seh:call_vectored_handlers calling handler at 0x5e4550 code=c0000005 flags=0 ... 0009:fixme:advapi:RegisterEventSourceW ((null),L".NET Runtime"): stub 0009:fixme:advapi:ReportEventW (0xcafe4242,0x0001,0x0000,0x000003ff,(nil),0x0001,0x00000000,0x2abc50,(nil)): stub 0009:err:eventlog:ReportEventW L"Application: pwsh.exe\nCoreCLR Version: 4.6.26919.2\nDescription: The process was terminated due to an internal error in the .NET Runtime at IP 000000000083FC2C (0000000000570000) with exit code 80131506.\n" 0009:fixme:advapi:DeregisterEventSource (0xcafe4242) stub 0009:trace:seh:raise_exception code=80000100 flags=1 addr=0x7bcd5ff4 pc=7bcd5ff4 tid=0009 0009:trace:seh:raise_exception info[0]=0000000000a63cfc 0009:trace:seh:raise_exception info[1]=0000000000a63896 wine: Call from 0x7bcd5ff4 to unimplemented function KERNEL32.dll.RaiseFailFastException, aborting 0009:trace:seh:call_vectored_handlers calling handler at 0x5e4550 code=80000100 flags=1 0009:trace:seh:call_vectored_handlers handler at 0x5e4550 returned 0 0009:trace:seh:call_stack_handlers calling handler at 0x7b4dd704 code=80000100 flags=1 wine: Unimplemented function KERNEL32.dll.RaiseFailFastException called at address 0x7bcd5ff4 (thread 0009), starting debugger... 0009:trace:seh:start_debugger Starting debugger "winedbg --auto 8 164" ... Modules: Module Address Debug info Name (65 modules) PE 3d0000- 45d000 Deferred hostpolicy PE 570000- ac8000 Deferred coreclr ELF 7b400000- 7b82e000 Deferred kernel32<elf> -PE 7b420000- 7b82e000 \ kernel32 ELF 7bc00000- 7bd4d000 Deferred ntdll<elf> -PE 7bc20000- 7bd4d000 \ ntdll ELF 7c000000- 7c004000 Deferred <wine-loader> PE 140000000- 140041000 Deferred pwsh PE 180000000- 18005d000 Deferred hostfxr ... ELF 7fbaa8c000- 7fbaabe000 Deferred ld-linux-aarch64.so.1 ELF 7fbaabf000- 7fbaac0000 Deferred [vdso].so Threads: process tid prio (all id:s are in hex) 00000008 (D) Z:\home\focht\projects\woa-winrt\powershell620-arm64\pwsh.exe 0000002b 0 00000009 0 <== ... System information: Wine build: wine-3.21-4-gfc4d5d49c6 Platform: arm64 Version: Windows 7 Host system: Linux Host version: 4.18.14-yocto-standard --- snip ---
Debugger session:
--- snip --- $ gdb wine64 GNU gdb (GDB) 8.2 ... (gdb) run pwsh.exe Starting program: /home/focht/projects/wine/mainline-install-aarch64/bin/wine64 pwsh.exe ... [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib64/libthread_db.so.1". ... 0009:fixme:wer:WerRegisterRuntimeExceptionModule (L"Z:\home\focht\projects\woa-winrt\powershell620-arm64\mscordaccore.dll", 0x570000) stub! [New LWP 1027] 0009:fixme:msvcrt:_control87 not implemented
Thread 1 "pwsh.exe" received signal SIGSEGV, Segmentation fault. 0x000000000083fc2c in ?? ()
(gdb) info reg x0 0x18f30000 418578432 x1 0x2ad8a0 2807968 x2 0x0 0 x3 0x8 8 x4 0x1 1 x5 0x4 4 x6 0x1 1 x7 0x7bd4cba0 2077543328 x8 0xc000 49152 x9 0x2ad9d8 2808280 x10 0xffffffff 4294967295 x11 0xffffffff 4294967295 x12 0x0 0 x13 0x18f30040 418578496 x14 0x1 1 x15 0x7bd4cb38 2077543224 x16 0x7bd2e010 2077417488 x17 0x7fbf4d6860 548670367840 x18 0x7ffd8000 2147319808 x19 0xa77348 10974024 x20 0x18f30000 418578432 x21 0x18f30000 418578432 x22 0xf30000 15925248 x23 0x90168 590184 x24 0xa6a270 10920560 x25 0xc4 196 x26 0xa69ea8 10919592 x27 0x30000 196608 x28 0x595290 5853840 x29 0x2ada30 2808368 x30 0x83fbdc 8649692 sp 0x2ada30 0x2ada30 pc 0x83fc2c 0x83fc2c cpsr 0x0 [ EL=0 ] fpsr 0x10 16 fpcr 0x0 0
(gdb) bt #0 0x000000000083fc2c in ?? () #1 0x0000000000a69ea8 in ?? () Backtrace stopped: previous frame identical to this frame (corrupt stack?)
(gdb) x/10i $pc => 0x83fc2c: stur wzr, [x13, #-64] 0x83fc30: ldr x11, [x19, #256] 0x83fc34: stp x22, x21, [x13, #-56] 0x83fc38: add x8, x13, x8, lsl #2 0x83fc3c: stur x8, [x13, #-40] 0x83fc40: ldr x8, [sp, #16] 0x83fc44: stp x8, xzr, [x13, #-16] 0x83fc48: ldur x8, [x13, #-40] 0x83fc4c: add x9, x8, x27, lsl #1 0x83fc50: sub x8, x11, #0x1 --- snip ---
Disassembly of surrounding code:
--- snip --- 00000001802CFBC0 48 08 00 90 ADRP X8, #VirtualAlloc@PAGE 00000001802CFBC4 08 7D 41 F9 LDR X8, [X8,#VirtualAlloc@PAGEOFF] 00000001802CFBC8 83 00 80 52 MOV W3, #4 00000001802CFBCC 02 00 82 52 MOV W2, #0x1000 00000001802CFBD0 E1 02 00 91 ADD X1, X23, #0 00000001802CFBD4 80 02 00 91 ADD X0, X20, #0 00000001802CFBD8 00 01 3F D6 BLR X8 00000001802CFBDC 40 02 00 B5 CBNZ X0, loc_1802CFC24 ... 00000001802CFC24 E8 13 40 F9 LDR X8, [SP,#0x70+var_50] 00000001802CFC28 8D 02 01 91 ADD X13, X20, #0x40 00000001802CFC2C BF 01 1C B8 STUR WZR, [X13,#-0x40] ; *boom* 00000001802CFC30 6B 82 40 F9 LDR X11, [X19,#0x100] 00000001802CFC34 B6 D5 3C A9 STP X22, X21, [X13,#-0x38] 00000001802CFC38 A8 09 08 8B ADD X8, X13, X8,LSL#2 00000001802CFC3C A8 81 1D F8 STUR X8, [X13,#-0x28] 00000001802CFC40 E8 0B 40 F9 LDR X8, [SP,#0x70+var_60] 00000001802CFC44 A8 7D 3F A9 STP X8, XZR, [X13,#-0x10] 00000001802CFC48 A8 81 5D F8 LDUR X8, [X13,#-0x28] ... --- snip ---
The problem domain is the same as bug 46187 - a write watch gets triggered and Wine's signal/exception handling needs to figure it out.
In case of aarch32 signal handlers it's a bit easier: the Linux kernel provides the information if the fault was caused by read or write access, see my comment https://bugs.winehq.org/show_bug.cgi?id=46187#c1 for details.
In case of aarch64 signal handlers the situation is a bit complicated. The Linux kernel exposes this information to userspace - but only via extended user/signal context information ('esr_context').
https://github.com/torvalds/linux/commit/15af1942dd61ee236a48b3de14d6f31c0b9...
--- quote --- arm64: Expose ESR_EL1 information to user when SIGSEGV/SIGBUS
This information is useful for instruction emulators to detect read/write and access size without having to decode the faulting instruction. The current patch exports it via sigcontext (struct esr_context) and is only valid for SIGSEGV and SIGBUS.
Signed-off-by: Catalin Marinas catalin.marinas@arm.com --- quote ---
https://github.com/torvalds/linux/blob/e195ca6cb6f21633e56322d5aa11ed59cdb22...
Wine currently uses a rather crude but acceptable way to figure read-or-write access out by decoding the faulting instruction.
https://source.winehq.org/git/wine.git/blob/HEAD:/dlls/ntdll/signal_arm64.c#...
--- snip --- 614 static inline DWORD is_write_fault( ucontext_t *context ) 615 { 616 DWORD inst = *(DWORD *)PC_sig(context); 617 if ((inst & 0xbfff0000) == 0x0c000000 /* C3.3.1 */ || 618 (inst & 0xbfe00000) == 0x0c800000 /* C3.3.2 */ || 619 (inst & 0xbfdf0000) == 0x0d000000 /* C3.3.3 */ || 620 (inst & 0xbfc00000) == 0x0d800000 /* C3.3.4 */ || 621 (inst & 0x3f400000) == 0x08000000 /* C3.3.6 */ || 622 (inst & 0x3bc00000) == 0x38000000 /* C3.3.8-12 */ || 623 (inst & 0x3fe00000) == 0x3c800000 /* C3.3.8-12 128bit */ || 624 (inst & 0x3bc00000) == 0x39000000 /* C3.3.13 */ || 625 (inst & 0x3fc00000) == 0x3d800000 /* C3.3.13 128bit */ || 626 (inst & 0x3a400000) == 0x28000000) /* C3.3.7,14-16 */ 627 return EXCEPTION_WRITE_FAULT; 628 return EXCEPTION_READ_FAULT; 629 } --- snip ---
Looks like it was "borrowed" from QEMU user:
https://github.com/qemu/qemu/commit/661f7fa4b088f2734050a751dd9d1d836b49e981
--- quote --- tcg-aarch64: Properly detect SIGSEGV writes
Since the kernel doesn't pass any info on the reason for the fault, disassemble the instruction to detect a store.
Reviewed-by: Alex Bennée alex.bennee@linaro.org Reviewed-by: Claudio Fontana claudio.fontana@huawei.com Signed-off-by: Richard Henderson rth@twiddle.net --- quote ---
The faulting instruction is: "stur wzr, [x13, -64]"
ARM Architecture Reference Manual ARMv8, for ARMv8-A architecture profile:
https://static.docs.arm.com/ddi0487/ca/DDI0487C_a_armv8_arm.pdf
--- quote --- C6.2.266 STUR
Store Register (unscaled) calculates an address from a base register value and an im mediate offset, and stores a 32-bit word or a 64-bit doubleword to the calculated address, from a register. For information about memory accesses, see Load/Store addressing modes on page C1-149
32-bit variant
Applies when size == 10
STUR <Wt>, [<Xn|SP>{, #<simm>}]
64-bit variant Applies when size == 11
STUR <Xt>, [<Xn|SP>{, #<simm>}]
Decode for all variants of this encoding
integer scale = UInt(size); bits(64) offset = SignExtend(imm9, 64);
Assembler symbols <Wt> Is the 32-bit name of the general-purpose register to be transferred, encoded in the "Rt" field.
<Xt> Is the 64-bit name of the general-purpose register to be transferred, encoded in the "Rt" field.
<Xn|SP> Is the 64-bit name of the general-purpose base register or stack pointer, encoded in the "Rn" field.
<simm> Is the optional signed immediate byte offset, in the range -256 to 255, defaulting to 0 and encoded in the "imm9" field. --- quote ---
wzr = zero register in 32-bit context
0xb81c01bf
10111000|00011100|00000001|10111111 ----------------------------------- 10 111 0 00|00 0 11100|0000 00 00|101 11111
sz = 10 = 32-bit variant opc = 0 imm9 = 0x1c0 Rn = 5 Rt = 0x1f
Using: https://yurichev.com/mirrors/ARMv8-A_Architecture_Reference_Manual_(Issue_A....
ARM Architecture Reference Manual for ARMv8 Profile-A, Issue A.a Section C3.1 "A64 instruction index by encoding": AArch64 main encoding table ... C3.3.12 Load/store register (unscale immediate)
---
After spending some hour on looking at ARMv8 processor manuals with magnifying glass, doing manual instruction decoding, almost questioning myself ... I finally spotted the problem.
It was decoding an instruction from Wine's own code, not the faulting instruction. Haha - nice one.
https://source.winehq.org/git/wine.git/blob/HEAD:/dlls/ntdll/signal_arm64.c#...
--- snip --- 428 static EXCEPTION_RECORD *setup_exception( ucontext_t *sigcontext, raise_func func ) 429 { ... 448 /* now modify the sigcontext to return to the raise function */ 449 SP_sig(sigcontext) = (ULONG_PTR)stack; 450 PC_sig(sigcontext) = (ULONG_PTR)func; 451 REGn_sig(0, sigcontext) = (ULONG_PTR)&stack->rec; /* first arg for raise_func */ 452 REGn_sig(1, sigcontext) = (ULONG_PTR)&stack->context; /* second arg for raise_func */ 453 454 return &stack->rec; 455 } --- snip ---
https://source.winehq.org/git/wine.git/blob/HEAD:/dlls/ntdll/signal_arm64.c#...
--- snip --- 636 static void segv_handler( int signal, siginfo_t *info, void *ucontext ) 637 { 638 EXCEPTION_RECORD *rec; 639 ucontext_t *context = ucontext; ... 656 rec = setup_exception( context, raise_segv_exception ); 657 if (rec->ExceptionCode == EXCEPTION_STACK_OVERFLOW) return; 658 659 switch(signal) 660 { 661 case SIGILL: /* Invalid opcode exception */ 662 rec->ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION; 663 break; 664 case SIGSEGV: /* Segmentation fault */ 665 rec->ExceptionCode = EXCEPTION_ACCESS_VIOLATION; 666 rec->NumberParameters = 2; 667 rec->ExceptionInformation[0] = is_write_fault(context); 668 rec->ExceptionInformation[1] = (ULONG_PTR)info->si_addr; 669 break; --- snip ---
At the point of 'is_write_fault' call, the context PC is already set to 'raise_segv_exception' function. I guess this code path was never tested - until now ;-)
Ideally the instruction disassembly approach should be reconsidered in favour of using extended context information. This will also help later when handling FPU/SIMD/SVE specific exceptions. But that requires more efforts -> future work task.
$ sha1sum PowerShell-6.2.0-preview.2-win-arm64.zip 731bf722a0083fbd101598fa42c9f1a0170d6548 PowerShell-6.2.0-preview.2-win-arm64.zip
$ du -sh PowerShell-6.2.0-preview.2-win-arm64.zip 40M PowerShell-6.2.0-preview.2-win-arm64.zip
Regards
https://bugs.winehq.org/show_bug.cgi?id=46194
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- URL| |https://github.com/PowerShe | |ll/PowerShell/releases/down | |load/v6.2.0-preview.2/Power | |Shell-6.2.0-preview.2-win-a | |rm64.zip Keywords| |download
https://bugs.winehq.org/show_bug.cgi?id=46194
André H. nerv@dawncrow.de changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |nerv@dawncrow.de
https://bugs.winehq.org/show_bug.cgi?id=46194
André H. nerv@dawncrow.de changed:
What |Removed |Added ---------------------------------------------------------------------------- Fixed by SHA1| |1b5b311cce908e33a5b1b11d5eb | |659e99c92c2f9 Resolution|--- |FIXED Status|NEW |RESOLVED
--- Comment #1 from André H. nerv@dawncrow.de --- should be fixed by: https://source.winehq.org/git/wine.git/commitdiff/1b5b311cce908e33a5b1b11d5e...
https://bugs.winehq.org/show_bug.cgi?id=46194
Stefan Dösinger stefan@codeweavers.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |stefan@codeweavers.com
--- Comment #2 from Stefan Dösinger stefan@codeweavers.com --- I noticed the problem long ago but didn't bother enough because in my case (my hangover hackeroo) it always defaulted to thinking it is a write access, which made the write guards I had issues with happy. I guess I should have tipped off André somewhen though :-( .
https://bugs.winehq.org/show_bug.cgi?id=46194
Alexandre Julliard julliard@winehq.org changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|RESOLVED |CLOSED
--- Comment #3 from Alexandre Julliard julliard@winehq.org --- Closing bugs fixed in 4.0-rc4.
https://bugs.winehq.org/show_bug.cgi?id=46194
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- URL|https://github.com/PowerShe |https://web.archive.org/web |ll/PowerShell/releases/down |/20210319110739/https://git |load/v6.2.0-preview.2/Power |hub.com/PowerShell/PowerShe |Shell-6.2.0-preview.2-win-a |ll/releases/download/v6.2.0 |rm64.zip |-preview.2/PowerShell-6.2.0 | |-preview.2-win-arm64.zip