[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