[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