Module: wine Branch: oldstable Commit: 65c0eacdee056c0ac4d4561dc6a56a712abb8802 URL: https://gitlab.winehq.org/wine/wine/-/commit/65c0eacdee056c0ac4d4561dc6a56a7...
Author: Martin Storsjö martin@martin.st Date: Wed May 11 00:52:10 2022 +0300
ntdll: Add SEH unwind info in ARM assembly functions/trampolines.
Clang generates SEH unwind info on ARM in both MSVC and mingw mode since Clang 15. The unwind info gets which gets enabled automatically by building with a new enough compiler.
For functions/trampolines that are implemented in assembly, the unwind information needs to be provided by hand - in particular for cases where unwinding should be diverted.
Contrary to AArch64, Clang got SEH assembler directives directly from the start when SEH was implemented (when the __SEH__ compiler define gets set), so there's no need for compiler version checks (like for AArch64 in include/wine/asm.h), but the default check for __SEH__ works fine for enabling the __ARM_SEH() macro.
Use a custom unwind opcode in the private opcode space for unwinding to a specific CONTEXT instead of up to the caller. (Contrary to AArch64, there's no specific unwind opcode for restoring a full CONTEXT, but the unwind opcode space does have a couple unallocated values marked as "available", which can be used for vendor specific needs here.)
This fixes unwinding in ARM PE builds.
Signed-off-by: Martin Storsjö martin@martin.st (cherry picked from commit 2d43653a2e789ed67a3c66db92276783b849051c) Signed-off-by: Michael Stefaniuc mstefani@winehq.org
---
dlls/ntdll/signal_arm.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
diff --git a/dlls/ntdll/signal_arm.c b/dlls/ntdll/signal_arm.c index 12ffbb3663a..34bd65989ad 100644 --- a/dlls/ntdll/signal_arm.c +++ b/dlls/ntdll/signal_arm.c @@ -731,6 +731,8 @@ static void process_unwind_codes( BYTE *ptr, BYTE *end, CONTEXT *context, WARN( "unsupported code %02x\n", *ptr ); else if (*ptr <= 0xef && ((val & 0xff) <= 0x0f)) /* ldr lr, [sp], #x */ pop_lr( 4 * (val & 0x0f), context, ptrs ); + else if (*ptr == 0xf4) /* Custom private (unallocated) opcode, saved a full CONTEXT on the stack */ + memcpy( context, (DWORD *)context->Sp, sizeof(CONTEXT) ); else if (*ptr <= 0xf4) /* Available */ WARN( "unsupported code %02x\n", *ptr ); else if (*ptr <= 0xf5) /* vpop {dS-dE} */ @@ -1075,11 +1077,18 @@ extern void * WINAPI call_consolidate_callback( CONTEXT *context, EXCEPTION_RECORD *rec ); __ASM_GLOBAL_FUNC( call_consolidate_callback, "push {r0-r2,lr}\n\t" + __ASM_SEH(".seh_nop\n\t") "sub sp, sp, #0x1a0\n\t" + __ASM_SEH(".seh_nop\n\t") "mov r1, r0\n\t" + __ASM_SEH(".seh_nop\n\t") "mov r0, sp\n\t" + __ASM_SEH(".seh_nop\n\t") "mov r2, #0x1a0\n\t" + __ASM_SEH(".seh_nop_w\n\t") "bl " __ASM_NAME("memcpy") "\n\t" + __ASM_SEH(".seh_custom 0xf4\n\t") /* A custom (unallocated) SEH opcode for CONTEXT on stack */ + __ASM_SEH(".seh_endprologue\n\t") __ASM_CFI(".cfi_def_cfa 13, 0\n\t") __ASM_CFI(".cfi_escape 0x0f,0x04,0x7d,0xb8,0x00,0x06\n\t") /* DW_CFA_def_cfa_expression: DW_OP_breg13 + 56, DW_OP_deref */ __ASM_CFI(".cfi_escape 0x10,0x04,0x02,0x7d,0x14\n\t") /* DW_CFA_expression: R4 DW_OP_breg13 + 20 */ @@ -1300,6 +1309,8 @@ extern LONG __C_ExecuteExceptionFilter(PEXCEPTION_POINTERS ptrs, PVOID frame, PUCHAR nonvolatile); __ASM_GLOBAL_FUNC( __C_ExecuteExceptionFilter, "push {r4-r11,lr}\n\t" + __ASM_SEH(".seh_save_regs_w {r4-r11,lr}\n\t") + __ASM_SEH(".seh_endprologue\n\t")
__ASM_CFI(".cfi_def_cfa 13, 36\n\t") __ASM_CFI(".cfi_offset r4, -36\n\t") @@ -1410,7 +1421,10 @@ EXCEPTION_DISPOSITION WINAPI __C_specific_handler( EXCEPTION_RECORD *rec, */ __ASM_STDCALL_FUNC( RtlRaiseException, 4, "push {r0, lr}\n\t" + __ASM_SEH(".seh_save_regs {r0, lr}\n\t") "sub sp, sp, #0x1a0\n\t" /* sizeof(CONTEXT) */ + __ASM_SEH(".seh_stackalloc 0x1a0\n\t") + __ASM_SEH(".seh_endprologue\n\t") __ASM_CFI(".cfi_adjust_cfa_offset 424\n\t") __ASM_CFI(".cfi_offset lr, -4\n\t") "mov r0, sp\n\t" /* context */