[PATCH] ntdll: Add ARM64 SEH unwind directives for assembly functions in PE builds

Martin Storsjo martin at martin.st
Fri Sep 4 02:36:06 CDT 2020


This fixes unwinding through RtlRaiseException and
call_consolidate_callback in PE builds.

Adjust the call_consolidate_callback function to store the whole
context on the stack, and use the seh "context" opcode for
unwinding to that context instead of the parent. Adjust the dwarf
escape codes for reading from the context on the stack.

Signed-off-by: Martin Storsjo <martin at martin.st>
---
Clang only got support for the ARM64 SEH assembler directives
very recently (https://reviews.llvm.org/D86529 and
https://reviews.llvm.org/D86889), in the master branch (that is
slated to become Clang 12 in 6 months) fairly soon after the
release branch for version 11 was branched off.

(So the risk of users using a trunk version 12, before these
directives were added is fairly low. But I guess it'd be good to
keep track of what version the Android NDK updates to next.)
---
 dlls/ntdll/signal_arm64.c | 83 ++++++++++++++++++++++++---------------
 include/wine/asm.h        | 10 ++++-
 2 files changed, 61 insertions(+), 32 deletions(-)

diff --git a/dlls/ntdll/signal_arm64.c b/dlls/ntdll/signal_arm64.c
index d0d708c733..412947411f 100644
--- a/dlls/ntdll/signal_arm64.c
+++ b/dlls/ntdll/signal_arm64.c
@@ -959,9 +959,7 @@ PVOID WINAPI RtlVirtualUnwind( ULONG type, ULONG_PTR base, ULONG_PTR pc,
  * else. All CFI instructions are either DW_CFA_def_cfa_expression or
  * DW_CFA_expression, and the expressions have the following format:
  *
- * DW_OP_breg29; sleb128 0x10           | Load x29 + 0x10
- * DW_OP_deref                          | Get *(x29 + 0x10) == context
- * DW_OP_plus_uconst; uleb128 <OFFSET>  | Add offset to get struct member
+ * DW_OP_breg31; sleb128 <OFFSET>       | Load x31 + struct member offset
  * [DW_OP_deref]                        | Dereference, only for CFA
  */
 extern void * WINAPI call_consolidate_callback( CONTEXT *context,
@@ -969,40 +967,60 @@ extern void * WINAPI call_consolidate_callback( CONTEXT *context,
                                                 EXCEPTION_RECORD *rec,
                                                 TEB *teb );
 __ASM_GLOBAL_FUNC( call_consolidate_callback,
-                   "stp x29, x30, [sp, #-0x20]!\n\t"
-                   __ASM_CFI(".cfi_def_cfa_offset 32\n\t")
-                   __ASM_CFI(".cfi_offset 29, -32\n\t")
-                   __ASM_CFI(".cfi_offset 30, -24\n\t")
+                   "stp x29, x30, [sp, #-0x30]!\n\t"
+                   __ASM_CFI(".cfi_def_cfa_offset 48\n\t")
+                   __ASM_CFI(".cfi_offset 29, -48\n\t")
+                   __ASM_CFI(".cfi_offset 30, -40\n\t")
+                   __ASM_SEH(".seh_nop\n\t")
+                   "stp x1,  x2,  [sp, #0x10]\n\t"
+                   __ASM_SEH(".seh_nop\n\t")
+                   "str x3,       [sp, #0x20]\n\t"
+                   __ASM_SEH(".seh_nop\n\t")
                    "mov x29, sp\n\t"
                    __ASM_CFI(".cfi_def_cfa_register 29\n\t")
-                   "str x0, [sp, 0x10]\n\t"
+                   __ASM_SEH(".seh_nop\n\t")
                    __ASM_CFI(".cfi_remember_state\n\t")
-                   __ASM_CFI(".cfi_escape 0x0f,0x07,0x8d,0x10,0x06,0x23,0x80,0x02,0x06\n\t") /* CFA */
-                   __ASM_CFI(".cfi_escape 0x10,0x13,0x06,0x8d,0x10,0x06,0x23,0xa0,0x01\n\t") /* x19 */
-                   __ASM_CFI(".cfi_escape 0x10,0x14,0x06,0x8d,0x10,0x06,0x23,0xa8,0x01\n\t") /* x20 */
-                   __ASM_CFI(".cfi_escape 0x10,0x15,0x06,0x8d,0x10,0x06,0x23,0xb0,0x01\n\t") /* x21 */
-                   __ASM_CFI(".cfi_escape 0x10,0x16,0x06,0x8d,0x10,0x06,0x23,0xb8,0x01\n\t") /* x22 */
-                   __ASM_CFI(".cfi_escape 0x10,0x17,0x06,0x8d,0x10,0x06,0x23,0xc0,0x01\n\t") /* x23 */
-                   __ASM_CFI(".cfi_escape 0x10,0x18,0x06,0x8d,0x10,0x06,0x23,0xc8,0x01\n\t") /* x24 */
-                   __ASM_CFI(".cfi_escape 0x10,0x19,0x06,0x8d,0x10,0x06,0x23,0xd0,0x01\n\t") /* x25 */
-                   __ASM_CFI(".cfi_escape 0x10,0x1a,0x06,0x8d,0x10,0x06,0x23,0xd8,0x01\n\t") /* x26 */
-                   __ASM_CFI(".cfi_escape 0x10,0x1b,0x06,0x8d,0x10,0x06,0x23,0xe0,0x01\n\t") /* x27 */
-                   __ASM_CFI(".cfi_escape 0x10,0x1c,0x06,0x8d,0x10,0x06,0x23,0xe8,0x01\n\t") /* x28 */
-                   __ASM_CFI(".cfi_escape 0x10,0x1d,0x06,0x8d,0x10,0x06,0x23,0xf0,0x01\n\t") /* x29 */
-                   __ASM_CFI(".cfi_escape 0x10,0x1e,0x06,0x8d,0x10,0x06,0x23,0xf8,0x01\n\t") /* x30 */
-                   __ASM_CFI(".cfi_escape 0x10,0x48,0x06,0x8d,0x10,0x06,0x23,0x90,0x03\n\t") /* d8  */
-                   __ASM_CFI(".cfi_escape 0x10,0x49,0x06,0x8d,0x10,0x06,0x23,0xa0,0x03\n\t") /* d9  */
-                   __ASM_CFI(".cfi_escape 0x10,0x4a,0x06,0x8d,0x10,0x06,0x23,0xb0,0x03\n\t") /* d10 */
-                   __ASM_CFI(".cfi_escape 0x10,0x4b,0x06,0x8d,0x10,0x06,0x23,0xc0,0x03\n\t") /* d11 */
-                   __ASM_CFI(".cfi_escape 0x10,0x4c,0x06,0x8d,0x10,0x06,0x23,0xd0,0x03\n\t") /* d12 */
-                   __ASM_CFI(".cfi_escape 0x10,0x4d,0x06,0x8d,0x10,0x06,0x23,0xe0,0x03\n\t") /* d13 */
-                   __ASM_CFI(".cfi_escape 0x10,0x4e,0x06,0x8d,0x10,0x06,0x23,0xf0,0x03\n\t") /* d14 */
-                   __ASM_CFI(".cfi_escape 0x10,0x4f,0x06,0x8d,0x10,0x06,0x23,0x80,0x04\n\t") /* d15 */
+                   /* Memcpy the context onto the stack */
+                   "sub sp, sp, #0x390\n\t"
+                   __ASM_SEH(".seh_nop\n\t")
+                   "mov x1,  x0\n\t"
+                   __ASM_SEH(".seh_nop\n\t")
+                   "mov x0,  sp\n\t"
+                   __ASM_SEH(".seh_nop\n\t")
+                   "mov x2,  #0x390\n\t"
+                   __ASM_SEH(".seh_nop\n\t")
+                   "bl memcpy\n\t"
+                   __ASM_CFI(".cfi_def_cfa 31, 0\n\t")
+                   __ASM_CFI(".cfi_escape 0x0f,0x04,0x8f,0x80,0x02,0x06\n\t") /* CFA, DW_OP_breg31 + 0x100, DW_OP_deref */
+                   __ASM_CFI(".cfi_escape 0x10,0x13,0x03,0x8f,0xa0,0x01\n\t") /* x19, DW_OP_breg31 + 0xA0 */
+                   __ASM_CFI(".cfi_escape 0x10,0x14,0x03,0x8f,0xa8,0x01\n\t") /* x20 */
+                   __ASM_CFI(".cfi_escape 0x10,0x15,0x03,0x8f,0xb0,0x01\n\t") /* x21 */
+                   __ASM_CFI(".cfi_escape 0x10,0x16,0x03,0x8f,0xb8,0x01\n\t") /* x22 */
+                   __ASM_CFI(".cfi_escape 0x10,0x17,0x03,0x8f,0xc0,0x01\n\t") /* x23 */
+                   __ASM_CFI(".cfi_escape 0x10,0x18,0x03,0x8f,0xc8,0x01\n\t") /* x24 */
+                   __ASM_CFI(".cfi_escape 0x10,0x19,0x03,0x8f,0xd0,0x01\n\t") /* x25 */
+                   __ASM_CFI(".cfi_escape 0x10,0x1a,0x03,0x8f,0xd8,0x01\n\t") /* x26 */
+                   __ASM_CFI(".cfi_escape 0x10,0x1b,0x03,0x8f,0xe0,0x01\n\t") /* x27 */
+                   __ASM_CFI(".cfi_escape 0x10,0x1c,0x03,0x8f,0xe8,0x01\n\t") /* x28 */
+                   __ASM_CFI(".cfi_escape 0x10,0x1d,0x03,0x8f,0xf0,0x01\n\t") /* x29 */
+                   __ASM_CFI(".cfi_escape 0x10,0x1e,0x03,0x8f,0xf8,0x01\n\t") /* x30 */
+                   __ASM_CFI(".cfi_escape 0x10,0x48,0x03,0x8f,0x90,0x03\n\t") /* d8  */
+                   __ASM_CFI(".cfi_escape 0x10,0x49,0x03,0x8f,0x98,0x03\n\t") /* d9  */
+                   __ASM_CFI(".cfi_escape 0x10,0x4a,0x03,0x8f,0xa0,0x03\n\t") /* d10 */
+                   __ASM_CFI(".cfi_escape 0x10,0x4b,0x03,0x8f,0xa8,0x03\n\t") /* d11 */
+                   __ASM_CFI(".cfi_escape 0x10,0x4c,0x03,0x8f,0xb0,0x03\n\t") /* d12 */
+                   __ASM_CFI(".cfi_escape 0x10,0x4d,0x03,0x8f,0xb8,0x03\n\t") /* d13 */
+                   __ASM_CFI(".cfi_escape 0x10,0x4e,0x03,0x8f,0xc0,0x03\n\t") /* d14 */
+                   __ASM_CFI(".cfi_escape 0x10,0x4f,0x03,0x8f,0xc8,0x03\n\t") /* d15 */
+                   __ASM_SEH(".seh_context\n\t")
+                   __ASM_SEH(".seh_endprologue\n\t")
+                   "ldp x1,  x2,  [x29, #0x10]\n\t"
+                   "ldr x18,      [x29, #0x20]\n\t"
                    "mov x0,  x2\n\t"
-                   "mov x18, x3\n\t"
                    "blr x1\n\t"
+                   "mov sp,  x29\n\t"
                    __ASM_CFI(".cfi_restore_state\n\t")
-                   "ldp x29, x30, [sp], #32\n\t"
+                   "ldp x29, x30, [sp], #48\n\t"
                    __ASM_CFI(".cfi_restore 30\n\t")
                    __ASM_CFI(".cfi_restore 29\n\t")
                    __ASM_CFI(".cfi_def_cfa 31, 0\n\t")
@@ -1207,6 +1225,9 @@ void WINAPI RtlUnwind( void *frame, void *target_ip, EXCEPTION_RECORD *rec, void
 __ASM_STDCALL_FUNC( RtlRaiseException, 4,
                    "sub sp, sp, #0x3b0\n\t" /* 0x390 (context) + 0x20 */
                    "stp x29, x30, [sp]\n\t"
+                   __ASM_SEH(".seh_stackalloc 0x3b0\n\t")
+                   __ASM_SEH(".seh_save_fplr 0\n\t")
+                   __ASM_SEH(".seh_endprologue\n\t")
                    __ASM_CFI(".cfi_def_cfa x29, 944\n\t")
                    __ASM_CFI(".cfi_offset x30, -936\n\t")
                    __ASM_CFI(".cfi_offset x29, -944\n\t")
diff --git a/include/wine/asm.h b/include/wine/asm.h
index 592f638306..788e26126c 100644
--- a/include/wine/asm.h
+++ b/include/wine/asm.h
@@ -40,7 +40,15 @@
 #endif
 
 #ifdef __SEH__
-# define __ASM_SEH(str) str
+# if defined(__aarch64__) && defined(__clang_major__) && (__clang_major__ < 12 || defined(__apple_build_version__))
+   /* Clang got support for aarch64 SEH assembly directives in Clang 12,
+    * before that, only .seh_startproc/.seh_endproc but nothing else was
+    * supported. Support for it doesn't exist in any Apple branded version
+    * of Clang yet. */
+#  define __ASM_SEH(str)
+# else
+#  define __ASM_SEH(str) str
+# endif
 #else
 # define __ASM_SEH(str)
 #endif
-- 
2.17.1




More information about the wine-devel mailing list