ntdll: Fix usage of libunwind on x86-64 on non-macOS platforms.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2019-09-18 16:52:38 +02:00
parent 12c09051b4
commit af4c7e6e61
1 changed files with 78 additions and 146 deletions

View File

@ -321,6 +321,41 @@ static inline struct amd64_thread_data *amd64_thread_data(void)
return (struct amd64_thread_data *)NtCurrentTeb()->SystemReserved2; return (struct amd64_thread_data *)NtCurrentTeb()->SystemReserved2;
} }
static inline void set_sigcontext( const CONTEXT *context, ucontext_t *sigcontext )
{
RAX_sig(sigcontext) = context->Rax;
RCX_sig(sigcontext) = context->Rcx;
RDX_sig(sigcontext) = context->Rdx;
RBX_sig(sigcontext) = context->Rbx;
RSP_sig(sigcontext) = context->Rsp;
RBP_sig(sigcontext) = context->Rbp;
RSI_sig(sigcontext) = context->Rsi;
RDI_sig(sigcontext) = context->Rdi;
R8_sig(sigcontext) = context->R8;
R9_sig(sigcontext) = context->R9;
R10_sig(sigcontext) = context->R10;
R11_sig(sigcontext) = context->R11;
R12_sig(sigcontext) = context->R12;
R13_sig(sigcontext) = context->R13;
R14_sig(sigcontext) = context->R14;
R15_sig(sigcontext) = context->R15;
RIP_sig(sigcontext) = context->Rip;
CS_sig(sigcontext) = context->SegCs;
FS_sig(sigcontext) = context->SegFs;
GS_sig(sigcontext) = context->SegGs;
EFL_sig(sigcontext) = context->EFlags;
#ifdef DS_sig
DS_sig(sigcontext) = context->SegDs;
#endif
#ifdef ES_sig
ES_sig(sigcontext) = context->SegEs;
#endif
#ifdef SS_sig
SS_sig(sigcontext) = context->SegSs;
#endif
}
/*********************************************************************** /***********************************************************************
* Definitions for Win32 unwind tables * Definitions for Win32 unwind tables
*/ */
@ -1426,112 +1461,6 @@ static NTSTATUS dwarf_virtual_unwind( ULONG64 ip, ULONG64 *frame,CONTEXT *contex
#ifdef HAVE_LIBUNWIND #ifdef HAVE_LIBUNWIND
/***********************************************************************
* libunwind_set_cursor_from_context
*/
static int libunwind_set_cursor_from_context( unw_cursor_t *cursor, CONTEXT *context, ULONG64 ip )
{
int rc;
rc = unw_set_reg(cursor, UNW_REG_IP, ip);
if (rc == UNW_ESUCCESS)
rc = unw_set_reg(cursor, UNW_REG_SP, context->Rsp);
if (rc == UNW_ESUCCESS)
rc = unw_set_reg(cursor, UNW_X86_64_RAX, context->Rax);
if (rc == UNW_ESUCCESS)
rc = unw_set_reg(cursor, UNW_X86_64_RDX, context->Rdx);
if (rc == UNW_ESUCCESS)
rc = unw_set_reg(cursor, UNW_X86_64_RCX, context->Rcx);
if (rc == UNW_ESUCCESS)
rc = unw_set_reg(cursor, UNW_X86_64_RBX, context->Rbx);
if (rc == UNW_ESUCCESS)
rc = unw_set_reg(cursor, UNW_X86_64_RSI, context->Rsi);
if (rc == UNW_ESUCCESS)
rc = unw_set_reg(cursor, UNW_X86_64_RDI, context->Rdi);
if (rc == UNW_ESUCCESS)
rc = unw_set_reg(cursor, UNW_X86_64_RBP, context->Rbp);
if (rc == UNW_ESUCCESS)
rc = unw_set_reg(cursor, UNW_X86_64_R8, context->R8);
if (rc == UNW_ESUCCESS)
rc = unw_set_reg(cursor, UNW_X86_64_R9, context->R9);
if (rc == UNW_ESUCCESS)
rc = unw_set_reg(cursor, UNW_X86_64_R10, context->R10);
if (rc == UNW_ESUCCESS)
rc = unw_set_reg(cursor, UNW_X86_64_R11, context->R11);
if (rc == UNW_ESUCCESS)
rc = unw_set_reg(cursor, UNW_X86_64_R12, context->R12);
if (rc == UNW_ESUCCESS)
rc = unw_set_reg(cursor, UNW_X86_64_R13, context->R13);
if (rc == UNW_ESUCCESS)
rc = unw_set_reg(cursor, UNW_X86_64_R14, context->R14);
if (rc == UNW_ESUCCESS)
rc = unw_set_reg(cursor, UNW_X86_64_R15, context->R15);
return rc;
}
/***********************************************************************
* libunwind_get_reg
*/
static int libunwind_get_reg( unw_cursor_t *cursor, unw_regnum_t reg, ULONG64 *val )
{
int rc;
unw_word_t word;
rc = unw_get_reg(cursor, reg, &word);
if (rc == UNW_ESUCCESS)
*val = word;
return rc;
}
/***********************************************************************
* libunwind_set_context_from_cursor
*/
static BOOL libunwind_set_context_from_cursor( CONTEXT *context, unw_cursor_t *cursor )
{
int rc;
rc = libunwind_get_reg(cursor, UNW_REG_IP, &context->Rip);
if (rc == UNW_ESUCCESS)
rc = libunwind_get_reg(cursor, UNW_REG_SP, &context->Rsp);
if (rc == UNW_ESUCCESS)
rc = libunwind_get_reg(cursor, UNW_X86_64_RAX, &context->Rax);
if (rc == UNW_ESUCCESS)
rc = libunwind_get_reg(cursor, UNW_X86_64_RDX, &context->Rdx);
if (rc == UNW_ESUCCESS)
rc = libunwind_get_reg(cursor, UNW_X86_64_RCX, &context->Rcx);
if (rc == UNW_ESUCCESS)
rc = libunwind_get_reg(cursor, UNW_X86_64_RBX, &context->Rbx);
if (rc == UNW_ESUCCESS)
rc = libunwind_get_reg(cursor, UNW_X86_64_RSI, &context->Rsi);
if (rc == UNW_ESUCCESS)
rc = libunwind_get_reg(cursor, UNW_X86_64_RDI, &context->Rdi);
if (rc == UNW_ESUCCESS)
rc = libunwind_get_reg(cursor, UNW_X86_64_RBP, &context->Rbp);
if (rc == UNW_ESUCCESS)
rc = libunwind_get_reg(cursor, UNW_X86_64_R8, &context->R8);
if (rc == UNW_ESUCCESS)
rc = libunwind_get_reg(cursor, UNW_X86_64_R9, &context->R9);
if (rc == UNW_ESUCCESS)
rc = libunwind_get_reg(cursor, UNW_X86_64_R10, &context->R10);
if (rc == UNW_ESUCCESS)
rc = libunwind_get_reg(cursor, UNW_X86_64_R11, &context->R11);
if (rc == UNW_ESUCCESS)
rc = libunwind_get_reg(cursor, UNW_X86_64_R12, &context->R12);
if (rc == UNW_ESUCCESS)
rc = libunwind_get_reg(cursor, UNW_X86_64_R13, &context->R13);
if (rc == UNW_ESUCCESS)
rc = libunwind_get_reg(cursor, UNW_X86_64_R14, &context->R14);
if (rc == UNW_ESUCCESS)
rc = libunwind_get_reg(cursor, UNW_X86_64_R15, &context->R15);
return rc;
}
/*********************************************************************** /***********************************************************************
* libunwind_virtual_unwind * libunwind_virtual_unwind
* *
@ -1545,11 +1474,34 @@ static NTSTATUS libunwind_virtual_unwind( ULONG64 ip, BOOL* got_info, ULONG64 *f
unw_proc_info_t info; unw_proc_info_t info;
int rc; int rc;
#ifdef __APPLE__
rc = unw_getcontext( &unw_context ); rc = unw_getcontext( &unw_context );
if (rc == UNW_ESUCCESS) if (rc == UNW_ESUCCESS)
rc = unw_init_local( &cursor, &unw_context ); rc = unw_init_local( &cursor, &unw_context );
if (rc == UNW_ESUCCESS) if (rc == UNW_ESUCCESS)
rc = libunwind_set_cursor_from_context( &cursor, context, ip - 1 ); {
unw_set_reg( &cursor, UNW_REG_IP, context->Rip );
unw_set_reg( &cursor, UNW_REG_SP, context->Rsp );
unw_set_reg( &cursor, UNW_X86_64_RAX, context->Rax );
unw_set_reg( &cursor, UNW_X86_64_RDX, context->Rdx );
unw_set_reg( &cursor, UNW_X86_64_RCX, context->Rcx );
unw_set_reg( &cursor, UNW_X86_64_RBX, context->Rbx );
unw_set_reg( &cursor, UNW_X86_64_RSI, context->Rsi );
unw_set_reg( &cursor, UNW_X86_64_RDI, context->Rdi );
unw_set_reg( &cursor, UNW_X86_64_RBP, context->Rbp );
unw_set_reg( &cursor, UNW_X86_64_R8, context->R8 );
unw_set_reg( &cursor, UNW_X86_64_R9, context->R9 );
unw_set_reg( &cursor, UNW_X86_64_R10, context->R10 );
unw_set_reg( &cursor, UNW_X86_64_R11, context->R11 );
unw_set_reg( &cursor, UNW_X86_64_R12, context->R12 );
unw_set_reg( &cursor, UNW_X86_64_R13, context->R13 );
unw_set_reg( &cursor, UNW_X86_64_R14, context->R14 );
unw_set_reg( &cursor, UNW_X86_64_R15, context->R15 );
}
#else
set_sigcontext( context, &unw_context );
rc = unw_init_local( &cursor, &unw_context );
#endif
if (rc != UNW_ESUCCESS) if (rc != UNW_ESUCCESS)
{ {
WARN( "setup failed: %d\n", rc ); WARN( "setup failed: %d\n", rc );
@ -1562,7 +1514,7 @@ static NTSTATUS libunwind_virtual_unwind( ULONG64 ip, BOOL* got_info, ULONG64 *f
WARN( "failed to get info: %d\n", rc ); WARN( "failed to get info: %d\n", rc );
return STATUS_INVALID_DISPOSITION; return STATUS_INVALID_DISPOSITION;
} }
if (rc == UNW_ENOINFO || ip < info.start_ip || info.end_ip <= ip || !info.format) if (rc == UNW_ENOINFO || ip < info.start_ip || ip > info.end_ip || info.end_ip == info.start_ip + 1)
{ {
*got_info = FALSE; *got_info = FALSE;
return STATUS_SUCCESS; return STATUS_SUCCESS;
@ -1580,14 +1532,23 @@ static NTSTATUS libunwind_virtual_unwind( ULONG64 ip, BOOL* got_info, ULONG64 *f
} }
*frame = context->Rsp; *frame = context->Rsp;
unw_get_reg( &cursor, UNW_REG_IP, (unw_word_t *)&context->Rip );
rc = libunwind_set_context_from_cursor( context, &cursor ); unw_get_reg( &cursor, UNW_REG_SP, (unw_word_t *)&context->Rsp );
if (rc != UNW_ESUCCESS) unw_get_reg( &cursor, UNW_X86_64_RAX, (unw_word_t *)&context->Rax );
{ unw_get_reg( &cursor, UNW_X86_64_RDX, (unw_word_t *)&context->Rdx );
WARN( "failed to update context after unwind: %d\n", rc ); unw_get_reg( &cursor, UNW_X86_64_RCX, (unw_word_t *)&context->Rcx );
return STATUS_INVALID_DISPOSITION; unw_get_reg( &cursor, UNW_X86_64_RBX, (unw_word_t *)&context->Rbx );
} unw_get_reg( &cursor, UNW_X86_64_RSI, (unw_word_t *)&context->Rsi );
unw_get_reg( &cursor, UNW_X86_64_RDI, (unw_word_t *)&context->Rdi );
unw_get_reg( &cursor, UNW_X86_64_RBP, (unw_word_t *)&context->Rbp );
unw_get_reg( &cursor, UNW_X86_64_R8, (unw_word_t *)&context->R8 );
unw_get_reg( &cursor, UNW_X86_64_R9, (unw_word_t *)&context->R9 );
unw_get_reg( &cursor, UNW_X86_64_R10, (unw_word_t *)&context->R10 );
unw_get_reg( &cursor, UNW_X86_64_R11, (unw_word_t *)&context->R11 );
unw_get_reg( &cursor, UNW_X86_64_R12, (unw_word_t *)&context->R12 );
unw_get_reg( &cursor, UNW_X86_64_R13, (unw_word_t *)&context->R13 );
unw_get_reg( &cursor, UNW_X86_64_R14, (unw_word_t *)&context->R14 );
unw_get_reg( &cursor, UNW_X86_64_R15, (unw_word_t *)&context->R15 );
*handler = (void*)info.handler; *handler = (void*)info.handler;
*handler_data = (void*)info.lsda; *handler_data = (void*)info.lsda;
*got_info = TRUE; *got_info = TRUE;
@ -1776,36 +1737,7 @@ static void restore_context( const CONTEXT *context, ucontext_t *sigcontext )
amd64_thread_data()->dr3 = context->Dr3; amd64_thread_data()->dr3 = context->Dr3;
amd64_thread_data()->dr6 = context->Dr6; amd64_thread_data()->dr6 = context->Dr6;
amd64_thread_data()->dr7 = context->Dr7; amd64_thread_data()->dr7 = context->Dr7;
RAX_sig(sigcontext) = context->Rax; set_sigcontext( context, sigcontext );
RCX_sig(sigcontext) = context->Rcx;
RDX_sig(sigcontext) = context->Rdx;
RBX_sig(sigcontext) = context->Rbx;
RSP_sig(sigcontext) = context->Rsp;
RBP_sig(sigcontext) = context->Rbp;
RSI_sig(sigcontext) = context->Rsi;
RDI_sig(sigcontext) = context->Rdi;
R8_sig(sigcontext) = context->R8;
R9_sig(sigcontext) = context->R9;
R10_sig(sigcontext) = context->R10;
R11_sig(sigcontext) = context->R11;
R12_sig(sigcontext) = context->R12;
R13_sig(sigcontext) = context->R13;
R14_sig(sigcontext) = context->R14;
R15_sig(sigcontext) = context->R15;
RIP_sig(sigcontext) = context->Rip;
CS_sig(sigcontext) = context->SegCs;
FS_sig(sigcontext) = context->SegFs;
GS_sig(sigcontext) = context->SegGs;
EFL_sig(sigcontext) = context->EFlags;
#ifdef DS_sig
DS_sig(sigcontext) = context->SegDs;
#endif
#ifdef ES_sig
ES_sig(sigcontext) = context->SegEs;
#endif
#ifdef SS_sig
SS_sig(sigcontext) = context->SegSs;
#endif
if (FPU_sig(sigcontext)) *FPU_sig(sigcontext) = context->u.FltSave; if (FPU_sig(sigcontext)) *FPU_sig(sigcontext) = context->u.FltSave;
} }