Today, Wine cannot properly handle the end of call stack when unwinding in ARM/ARM64, erroneously setting EH_STACK_INVALID in the exception record when the base of the thread stack is reached.
This is because the is_valid_frame function was copied from i386, where every function sets up a frame pointer next to the return address. However, this does not hold on any other architectures (e.g. x86-64), which instead rely on stack unwinding information tables to properly recognise stack frames.
On these architectures, reaching the bottom of the call stack means the stack pointer equals StackBase. This is why signal_x86_64.c explicitly recognises Rsp == StackBase to be a valid condition; however, this was not copied to ARM/ARM64 when unwinding was implemented on these architectures.
Fix this by allowing frame pointer to equal StackBase, just like X86-64.
Signed-off-by: Jinoh Kang jinoh.kang.kr@gmail.com --- dlls/ntdll/signal_arm.c | 2 +- dlls/ntdll/signal_arm64.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/dlls/ntdll/signal_arm.c b/dlls/ntdll/signal_arm.c index 72f3b023e45..12ffbb3663a 100644 --- a/dlls/ntdll/signal_arm.c +++ b/dlls/ntdll/signal_arm.c @@ -89,7 +89,7 @@ static inline BOOL is_valid_frame( ULONG_PTR frame ) { if (frame & 3) return FALSE; return ((void *)frame >= NtCurrentTeb()->Tib.StackLimit && - (void **)frame < (void **)NtCurrentTeb()->Tib.StackBase - 1); + (void *)frame <= NtCurrentTeb()->Tib.StackBase); }
diff --git a/dlls/ntdll/signal_arm64.c b/dlls/ntdll/signal_arm64.c index 290639b676b..034c78f6b4d 100644 --- a/dlls/ntdll/signal_arm64.c +++ b/dlls/ntdll/signal_arm64.c @@ -96,7 +96,7 @@ static inline BOOL is_valid_frame( ULONG_PTR frame ) { if (frame & 7) return FALSE; return ((void *)frame >= NtCurrentTeb()->Tib.StackLimit && - (void **)frame < (void **)NtCurrentTeb()->Tib.StackBase - 1); + (void *)frame <= NtCurrentTeb()->Tib.StackBase); }