[PATCH 1/3] ntdll: Add SEH unwind info in ARM assembly functions/trampolines
Martin Storsjö
wine at gitlab.winehq.org
Tue Jun 7 06:21:14 CDT 2022
From: Martin Storsjö <martin at martin.st>
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 at martin.st>
---
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 7872962bbbe..01c911660de 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 */
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/198
More information about the wine-devel
mailing list