ntdll: Fix unwind from call_consolidate_callback() for PE build on x64.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49698 Signed-off-by: Paul Gofman <pgofman@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
76556bc588
commit
c76dc32fef
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue