[Bug 46194] New: Windows PowerShell Core 6.2 Preview 2 for ARM64 crashes due to decoding of instruction from incorrect PC (write watch access causes SIGSEGV)
wine-bugs at winehq.org
wine-bugs at winehq.org
Sun Nov 25 11:18:48 CST 2018
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 at winehq.org
Reporter: focht at 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/PowerShell-6.2.0-preview.2-win-arm64.zip
--- 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 at PAGE
00000001802CFBC4 08 7D 41 F9 LDR X8, [X8,#VirtualAlloc at 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/15af1942dd61ee236a48b3de14d6f31c0b9e8116#diff-fbc7fc3a92cc6d52e2c63dea6cc4a129
--- 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 at arm.com>
--- quote ---
https://github.com/torvalds/linux/blob/e195ca6cb6f21633e56322d5aa11ed59cdb22fb2/arch/arm64/include/uapi/asm/sigcontext.h
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#l614
--- 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 at linaro.org>
Reviewed-by: Claudio Fontana <claudio.fontana at huawei.com>
Signed-off-by: Richard Henderson <rth at 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.a).pdf
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#l428
--- 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#l636
--- 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
--
Do not reply to this email, post in Bugzilla using the
above URL to reply.
You are receiving this mail because:
You are watching all bug changes.
More information about the wine-bugs
mailing list