[PATCH 2/2] ntdll: Fix unwind from call_consolidate_callback() for PE build on x64.

Paul Gofman pgofman at codeweavers.com
Wed Aug 12 15:19:55 CDT 2020


Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49698
Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
---
 dlls/ntdll/signal_x86_64.c | 71 ++++++++++++++++++++++++++++++++++----
 1 file changed, 65 insertions(+), 6 deletions(-)

diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c
index 3ed89526893..28e4ec8ca6c 100644
--- a/dlls/ntdll/signal_x86_64.c
+++ b/dlls/ntdll/signal_x86_64.c
@@ -1011,8 +1011,8 @@ static DWORD call_teb_unwind_handler( EXCEPTION_RECORD *rec, DISPATCHER_CONTEXT
  * Wrapper function to call a consolidate callback from a fake frame.
  * If the callback executes RtlUnwindEx (like for example done in C++ handlers),
  * we have to skip all frames which were already processed. To do that we
- * trick the unwinding functions into thinking the call came from somewhere
- * else. All CFI instructions are either DW_CFA_def_cfa_expression or
+ * trick the unwinding functions into thinking the call came from the specified
+ * context. All CFI instructions are either DW_CFA_def_cfa_expression or
  * DW_CFA_expression, and the expressions have the following format:
  *
  * DW_OP_breg6; sleb128 0x10            | Load %rbp + 0x10
@@ -1025,15 +1025,26 @@ extern void * WINAPI call_consolidate_callback( CONTEXT *context,
                                                 EXCEPTION_RECORD *rec );
 __ASM_GLOBAL_FUNC( call_consolidate_callback,
                    "pushq %rbp\n\t"
-                   __ASM_SEH(".seh_pushreg %rbp\n\t")
                    __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
                    __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
                    "movq %rsp,%rbp\n\t"
-                   __ASM_SEH(".seh_setframe %rbp,0\n\t")
                    __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
-                   "subq $0x20,%rsp\n\t"
-                   __ASM_SEH(".seh_stackalloc 0x20\n\t")
+
+                   /* Setup SEH machine frame. */
+                   "subq $0x28,%rsp\n\t"
+                   __ASM_CFI(".cfi_adjust_cfa_offset 0x28\n\t")
+                   "movq 0xf8(%rcx),%rax\n\t" /* Context->Rip */
+                   "movq %rax,(%rsp)\n\t"
+                   "movq 0x98(%rcx),%rax\n\t" /* context->Rsp */
+                   "movq %rax,0x18(%rsp)\n\t"
+                   __ASM_SEH(".seh_pushframe\n\t")
                    __ASM_SEH(".seh_endprologue\n\t")
+
+                   "subq $0xf8,%rsp\n\t" /* 10*16 (float regs) + 7*8 (int regs) + 32 (shadow store). */
+                   __ASM_SEH(".seh_stackalloc 0xf8\n\t")
+                   __ASM_CFI(".cfi_adjust_cfa_offset 0xf8\n\t")
+
+                   /* Setup CFI unwind to context. */
                    "movq %rcx,0x10(%rbp)\n\t"
                    __ASM_CFI(".cfi_remember_state\n\t")
                    __ASM_CFI(".cfi_escape 0x0f,0x07,0x76,0x10,0x06,0x23,0x98,0x01,0x06\n\t") /* CFA    */
@@ -1056,9 +1067,57 @@ __ASM_GLOBAL_FUNC( call_consolidate_callback,
                    __ASM_CFI(".cfi_escape 0x10,0x1e,0x06,0x76,0x10,0x06,0x23,0xf0,0x04\n\t") /* %xmm13 */
                    __ASM_CFI(".cfi_escape 0x10,0x1f,0x06,0x76,0x10,0x06,0x23,0x80,0x05\n\t") /* %xmm14 */
                    __ASM_CFI(".cfi_escape 0x10,0x20,0x06,0x76,0x10,0x06,0x23,0x90,0x05\n\t") /* %xmm15 */
+
+                   /* Setup SEH unwind registers restore. */
+                   "movq 0x90(%rcx),%rax\n\t" /* context->Rbx */
+                   "movq %rax,0x20(%rsp)\n\t"
+                   __ASM_SEH(".seh_savereg %rbx, 0x20\n\t")
+                   "movq 0xa8(%rcx),%rax\n\t" /* context->Rsi */
+                   "movq %rax,0x28(%rsp)\n\t"
+                   __ASM_SEH(".seh_savereg %rsi, 0x28\n\t")
+                   "movq 0xb0(%rcx),%rax\n\t" /* context->Rdi */
+                   "movq %rax,0x30(%rsp)\n\t"
+                   __ASM_SEH(".seh_savereg %rdi, 0x30\n\t")
+
+                   "movq 0xd8(%rcx),%rax\n\t" /* context->R12 */
+                   "movq %rax,0x38(%rsp)\n\t"
+                   __ASM_SEH(".seh_savereg %r12, 0x38\n\t")
+                   "movq 0xe0(%rcx),%rax\n\t" /* context->R13 */
+                   "movq %rax,0x40(%rsp)\n\t"
+                   __ASM_SEH(".seh_savereg %r13, 0x40\n\t")
+                   "movq 0xe8(%rcx),%rax\n\t" /* context->R14 */
+                   "movq %rax,0x48(%rsp)\n\t"
+                   __ASM_SEH(".seh_savereg %r14, 0x48\n\t")
+                   "movq 0xf0(%rcx),%rax\n\t" /* context->R15 */
+                   "movq %rax,0x50(%rsp)\n\t"
+                   __ASM_SEH(".seh_savereg %r15, 0x50\n\t")
+                   "pushq %rsi\n\t"
+                   "pushq %rdi\n\t"
+                   "leaq 0x200(%rcx),%rsi\n\t"
+                   "leaq 0x60(%rsp),%rdi\n\t"
+                   "movq $0x14,%rcx\n\t"
+                   "cld\n\t"
+                   "rep; movsq\n\t"
+                   "popq %rdi\n\t"
+                   "popq %rsi\n\t"
+                   __ASM_SEH(".seh_savexmm %xmm6, 0x60\n\t")
+                   __ASM_SEH(".seh_savexmm %xmm7, 0x70\n\t")
+                   __ASM_SEH(".seh_savexmm %xmm8, 0x80\n\t")
+                   __ASM_SEH(".seh_savexmm %xmm9, 0x90\n\t")
+                   __ASM_SEH(".seh_savexmm %xmm10, 0xa0\n\t")
+                   __ASM_SEH(".seh_savexmm %xmm11, 0xb0\n\t")
+                   __ASM_SEH(".seh_savexmm %xmm12, 0xc0\n\t")
+                   __ASM_SEH(".seh_savexmm %xmm13, 0xd0\n\t")
+                   __ASM_SEH(".seh_savexmm %xmm14, 0xe0\n\t")
+                   __ASM_SEH(".seh_savexmm %xmm15, 0xf0\n\t")
+
+                   /* call the callback. */
                    "movq %r8,%rcx\n\t"
                    "callq *%rdx\n\t"
                    __ASM_CFI(".cfi_restore_state\n\t")
+                   "nop\n\t" /* Otherwise RtlVirtualUnwind() will think we are inside epilogue and
+                              * interpret / execute the rest of opcodes here instead of unwind through
+                              * machine frame. */
                    "leaq 0(%rbp),%rsp\n\t"
                    __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
                    "popq %rbp\n\t"
-- 
2.26.2




More information about the wine-devel mailing list