ntdll: Implement __C_specific_handler and _local_unwind for arm64.
Signed-off-by: Martin Storsjo <martin@martin.st> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
5b7fac05d9
commit
2693e6662d
|
@ -14,7 +14,7 @@
|
|||
@ cdecl __AdjustPointer(ptr ptr) ucrtbase.__AdjustPointer
|
||||
@ stub __BuildCatchObject
|
||||
@ stub __BuildCatchObjectHelper
|
||||
@ stdcall -arch=x86_64 __C_specific_handler(ptr long ptr ptr) ucrtbase.__C_specific_handler
|
||||
@ stdcall -arch=x86_64,arm64 __C_specific_handler(ptr long ptr ptr) ucrtbase.__C_specific_handler
|
||||
@ stub __C_specific_handler_noexcept
|
||||
@ cdecl -arch=i386,x86_64,arm,arm64 __CxxDetectRethrow(ptr) ucrtbase.__CxxDetectRethrow
|
||||
@ cdecl -arch=i386,x86_64,arm,arm64 __CxxExceptionFilter(ptr ptr long ptr) ucrtbase.__CxxExceptionFilter
|
||||
|
@ -62,7 +62,7 @@
|
|||
@ cdecl _get_unexpected() ucrtbase._get_unexpected
|
||||
@ cdecl -arch=i386 _global_unwind2(ptr) ucrtbase._global_unwind2
|
||||
@ stub _is_exception_typeof
|
||||
@ cdecl -arch=x86_64 _local_unwind(ptr ptr) ucrtbase._local_unwind
|
||||
@ cdecl -arch=x86_64,arm64 _local_unwind(ptr ptr) ucrtbase._local_unwind
|
||||
@ cdecl -arch=i386 _local_unwind2(ptr long) ucrtbase._local_unwind2
|
||||
@ cdecl -arch=i386 _local_unwind4(ptr ptr long) ucrtbase._local_unwind4
|
||||
@ cdecl -arch=i386 _longjmpex(ptr long) ucrtbase._longjmpex
|
||||
|
|
|
@ -1437,7 +1437,7 @@
|
|||
@ cdecl -private -arch=i386 _CIpow()
|
||||
@ cdecl -private -arch=i386 _CIsin()
|
||||
@ cdecl -private -arch=i386 _CIsqrt()
|
||||
@ stdcall -arch=x86_64 __C_specific_handler(ptr long ptr ptr)
|
||||
@ stdcall -arch=x86_64,arm64 __C_specific_handler(ptr long ptr ptr)
|
||||
@ cdecl -arch=arm,x86_64 -norelay __chkstk()
|
||||
@ cdecl __isascii(long)
|
||||
@ cdecl __iscsym(long)
|
||||
|
@ -1463,7 +1463,7 @@
|
|||
@ cdecl _itoa(long ptr long)
|
||||
@ cdecl _itow(long ptr long)
|
||||
@ cdecl _lfind(ptr ptr ptr long ptr)
|
||||
@ stdcall -arch=x86_64 _local_unwind(ptr ptr)
|
||||
@ stdcall -arch=x86_64,arm64 _local_unwind(ptr ptr)
|
||||
@ cdecl _ltoa(long ptr long)
|
||||
@ cdecl _ltow(long ptr long)
|
||||
@ cdecl _memccpy(ptr ptr long long)
|
||||
|
|
|
@ -39,6 +39,19 @@
|
|||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(seh);
|
||||
|
||||
typedef struct _SCOPE_TABLE
|
||||
{
|
||||
ULONG Count;
|
||||
struct
|
||||
{
|
||||
ULONG BeginAddress;
|
||||
ULONG EndAddress;
|
||||
ULONG HandlerAddress;
|
||||
ULONG JumpTarget;
|
||||
} ScopeRecord[1];
|
||||
} SCOPE_TABLE, *PSCOPE_TABLE;
|
||||
|
||||
|
||||
/* layering violation: the setjmp buffer is defined in msvcrt, but used by RtlUnwindEx */
|
||||
struct MSVCRT_JUMP_BUFFER
|
||||
{
|
||||
|
@ -63,6 +76,19 @@ struct MSVCRT_JUMP_BUFFER
|
|||
};
|
||||
|
||||
|
||||
static void dump_scope_table( ULONG64 base, const SCOPE_TABLE *table )
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
TRACE( "scope table at %p\n", table );
|
||||
for (i = 0; i < table->Count; i++)
|
||||
TRACE( " %u: %lx-%lx handler %lx target %lx\n", i,
|
||||
base + table->ScopeRecord[i].BeginAddress,
|
||||
base + table->ScopeRecord[i].EndAddress,
|
||||
base + table->ScopeRecord[i].HandlerAddress,
|
||||
base + table->ScopeRecord[i].JumpTarget );
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
* is_valid_frame
|
||||
*/
|
||||
|
@ -1206,6 +1232,154 @@ void WINAPI RtlUnwind( void *frame, void *target_ip, EXCEPTION_RECORD *rec, void
|
|||
RtlUnwindEx( frame, target_ip, rec, retval, &context, NULL );
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
* _local_unwind (NTDLL.@)
|
||||
*/
|
||||
void WINAPI _local_unwind( void *frame, void *target_ip )
|
||||
{
|
||||
CONTEXT context;
|
||||
RtlUnwindEx( frame, target_ip, NULL, NULL, &context, NULL );
|
||||
}
|
||||
|
||||
extern LONG __C_ExecuteExceptionFilter(PEXCEPTION_POINTERS ptrs, PVOID frame,
|
||||
PEXCEPTION_FILTER filter,
|
||||
PUCHAR nonvolatile);
|
||||
__ASM_GLOBAL_FUNC( __C_ExecuteExceptionFilter,
|
||||
"stp x29, x30, [sp, #-96]!\n\t"
|
||||
__ASM_SEH(".seh_save_fplr_x 96\n\t")
|
||||
"stp x19, x20, [sp, #16]\n\t"
|
||||
__ASM_SEH(".seh_save_regp x19, 16\n\t")
|
||||
"stp x21, x22, [sp, #32]\n\t"
|
||||
__ASM_SEH(".seh_save_regp x21, 32\n\t")
|
||||
"stp x23, x24, [sp, #48]\n\t"
|
||||
__ASM_SEH(".seh_save_regp x23, 48\n\t")
|
||||
"stp x25, x26, [sp, #64]\n\t"
|
||||
__ASM_SEH(".seh_save_regp x25, 64\n\t")
|
||||
"stp x27, x28, [sp, #80]\n\t"
|
||||
__ASM_SEH(".seh_save_regp x27, 80\n\t")
|
||||
"mov x29, sp\n\t"
|
||||
__ASM_SEH(".seh_set_fp\n\t")
|
||||
__ASM_SEH(".seh_endprologue\n\t")
|
||||
|
||||
__ASM_CFI(".cfi_def_cfa x29, 96\n\t")
|
||||
__ASM_CFI(".cfi_offset x29, -96\n\t")
|
||||
__ASM_CFI(".cfi_offset x30, -88\n\t")
|
||||
__ASM_CFI(".cfi_offset x19, -80\n\t")
|
||||
__ASM_CFI(".cfi_offset x20, -72\n\t")
|
||||
__ASM_CFI(".cfi_offset x21, -64\n\t")
|
||||
__ASM_CFI(".cfi_offset x22, -56\n\t")
|
||||
__ASM_CFI(".cfi_offset x23, -48\n\t")
|
||||
__ASM_CFI(".cfi_offset x24, -40\n\t")
|
||||
__ASM_CFI(".cfi_offset x25, -32\n\t")
|
||||
__ASM_CFI(".cfi_offset x26, -24\n\t")
|
||||
__ASM_CFI(".cfi_offset x27, -16\n\t")
|
||||
__ASM_CFI(".cfi_offset x28, -8\n\t")
|
||||
|
||||
"ldp x19, x20, [x3, #0]\n\t"
|
||||
"ldp x21, x22, [x3, #16]\n\t"
|
||||
"ldp x23, x24, [x3, #32]\n\t"
|
||||
"ldp x25, x26, [x3, #48]\n\t"
|
||||
"ldp x27, x28, [x3, #64]\n\t"
|
||||
/* Overwrite the frame parameter with Fp from the
|
||||
* nonvolatile regs */
|
||||
"ldr x1, [x3, #80]\n\t"
|
||||
"blr x2\n\t"
|
||||
"ldp x19, x20, [sp, #16]\n\t"
|
||||
"ldp x21, x22, [sp, #32]\n\t"
|
||||
"ldp x23, x24, [sp, #48]\n\t"
|
||||
"ldp x25, x26, [sp, #64]\n\t"
|
||||
"ldp x27, x28, [sp, #80]\n\t"
|
||||
"ldp x29, x30, [sp], #96\n\t"
|
||||
"ret")
|
||||
|
||||
extern void __C_ExecuteTerminationHandler(BOOL abnormal, PVOID frame,
|
||||
PTERMINATION_HANDLER handler,
|
||||
PUCHAR nonvolatile);
|
||||
/* This is, implementation wise, identical to __C_ExecuteExceptionFilter. */
|
||||
__ASM_GLOBAL_FUNC( __C_ExecuteTerminationHandler,
|
||||
"b " __ASM_NAME("__C_ExecuteExceptionFilter") "\n\t");
|
||||
|
||||
/*******************************************************************
|
||||
* __C_specific_handler (NTDLL.@)
|
||||
*/
|
||||
EXCEPTION_DISPOSITION WINAPI __C_specific_handler( EXCEPTION_RECORD *rec,
|
||||
void *frame,
|
||||
CONTEXT *context,
|
||||
struct _DISPATCHER_CONTEXT *dispatch )
|
||||
{
|
||||
SCOPE_TABLE *table = dispatch->HandlerData;
|
||||
ULONG i;
|
||||
DWORD64 ControlPc = dispatch->ControlPc;
|
||||
|
||||
TRACE( "%p %p %p %p\n", rec, frame, context, dispatch );
|
||||
if (TRACE_ON(seh)) dump_scope_table( dispatch->ImageBase, table );
|
||||
|
||||
if (dispatch->ControlPcIsUnwound)
|
||||
ControlPc -= 4;
|
||||
|
||||
if (rec->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND))
|
||||
{
|
||||
for (i = dispatch->ScopeIndex; i < table->Count; i++)
|
||||
{
|
||||
if (ControlPc >= dispatch->ImageBase + table->ScopeRecord[i].BeginAddress &&
|
||||
ControlPc < dispatch->ImageBase + table->ScopeRecord[i].EndAddress)
|
||||
{
|
||||
PTERMINATION_HANDLER handler;
|
||||
|
||||
if (table->ScopeRecord[i].JumpTarget) continue;
|
||||
|
||||
if (rec->ExceptionFlags & EH_TARGET_UNWIND &&
|
||||
dispatch->TargetPc >= dispatch->ImageBase + table->ScopeRecord[i].BeginAddress &&
|
||||
dispatch->TargetPc < dispatch->ImageBase + table->ScopeRecord[i].EndAddress)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
handler = (PTERMINATION_HANDLER)(dispatch->ImageBase + table->ScopeRecord[i].HandlerAddress);
|
||||
dispatch->ScopeIndex = i+1;
|
||||
|
||||
TRACE( "calling __finally %p frame %p\n", handler, frame );
|
||||
__C_ExecuteTerminationHandler( TRUE, frame, handler,
|
||||
dispatch->NonVolatileRegisters );
|
||||
}
|
||||
}
|
||||
return ExceptionContinueSearch;
|
||||
}
|
||||
|
||||
for (i = dispatch->ScopeIndex; i < table->Count; i++)
|
||||
{
|
||||
if (ControlPc >= dispatch->ImageBase + table->ScopeRecord[i].BeginAddress &&
|
||||
ControlPc < dispatch->ImageBase + table->ScopeRecord[i].EndAddress)
|
||||
{
|
||||
if (!table->ScopeRecord[i].JumpTarget) continue;
|
||||
if (table->ScopeRecord[i].HandlerAddress != EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
EXCEPTION_POINTERS ptrs;
|
||||
PEXCEPTION_FILTER filter;
|
||||
|
||||
filter = (PEXCEPTION_FILTER)(dispatch->ImageBase + table->ScopeRecord[i].HandlerAddress);
|
||||
ptrs.ExceptionRecord = rec;
|
||||
ptrs.ContextRecord = context;
|
||||
TRACE( "calling filter %p ptrs %p frame %p\n", filter, &ptrs, frame );
|
||||
switch (__C_ExecuteExceptionFilter( &ptrs, frame, filter,
|
||||
dispatch->NonVolatileRegisters ))
|
||||
{
|
||||
case EXCEPTION_EXECUTE_HANDLER:
|
||||
break;
|
||||
case EXCEPTION_CONTINUE_SEARCH:
|
||||
continue;
|
||||
case EXCEPTION_CONTINUE_EXECUTION:
|
||||
return ExceptionContinueExecution;
|
||||
}
|
||||
}
|
||||
TRACE( "unwinding to target %lx\n", dispatch->ImageBase + table->ScopeRecord[i].JumpTarget );
|
||||
RtlUnwindEx( frame, (char *)dispatch->ImageBase + table->ScopeRecord[i].JumpTarget,
|
||||
rec, 0, dispatch->ContextRecord, dispatch->HistoryTable );
|
||||
}
|
||||
}
|
||||
return ExceptionContinueSearch;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* RtlRaiseException (NTDLL.@)
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
@ cdecl __AdjustPointer(ptr ptr)
|
||||
@ stub __BuildCatchObject
|
||||
@ stub __BuildCatchObjectHelper
|
||||
@ stdcall -arch=x86_64 __C_specific_handler(ptr long ptr ptr) ntdll.__C_specific_handler
|
||||
@ stdcall -arch=x86_64,arm64 __C_specific_handler(ptr long ptr ptr) ntdll.__C_specific_handler
|
||||
@ cdecl -arch=i386,x86_64,arm,arm64 __CxxDetectRethrow(ptr)
|
||||
@ cdecl -arch=i386,x86_64,arm,arm64 __CxxExceptionFilter(ptr ptr long ptr)
|
||||
@ cdecl -arch=i386,x86_64,arm,arm64 -norelay __CxxFrameHandler(ptr ptr ptr ptr)
|
||||
|
@ -555,7 +555,7 @@
|
|||
@ cdecl -arch=i386 -norelay _libm_sse2_sqrt_precise() MSVCRT___libm_sse2_sqrt_precise
|
||||
@ cdecl -arch=i386 -norelay _libm_sse2_tan_precise() MSVCRT___libm_sse2_tan
|
||||
@ cdecl _loaddll(str)
|
||||
@ cdecl -arch=x86_64 _local_unwind(ptr ptr)
|
||||
@ cdecl -arch=x86_64,arm64 _local_unwind(ptr ptr)
|
||||
@ cdecl -arch=i386 _local_unwind2(ptr long)
|
||||
@ cdecl -arch=i386 _local_unwind4(ptr ptr long)
|
||||
@ cdecl _localtime32(ptr) MSVCRT__localtime32
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
@ cdecl __AdjustPointer(ptr ptr) ucrtbase.__AdjustPointer
|
||||
@ stub __BuildCatchObject
|
||||
@ stub __BuildCatchObjectHelper
|
||||
@ stdcall -arch=x86_64 __C_specific_handler(ptr long ptr ptr) ucrtbase.__C_specific_handler
|
||||
@ stdcall -arch=x86_64,arm64 __C_specific_handler(ptr long ptr ptr) ucrtbase.__C_specific_handler
|
||||
@ stub __C_specific_handler_noexcept
|
||||
@ cdecl -arch=i386,x86_64,arm,arm64 __CxxDetectRethrow(ptr) ucrtbase.__CxxDetectRethrow
|
||||
@ cdecl -arch=i386,x86_64,arm,arm64 __CxxExceptionFilter(ptr ptr long ptr) ucrtbase.__CxxExceptionFilter
|
||||
|
@ -64,7 +64,7 @@
|
|||
@ cdecl -arch=i386 _local_unwind2(ptr long) ucrtbase._local_unwind2
|
||||
@ cdecl -arch=i386 _local_unwind4(ptr ptr long) ucrtbase._local_unwind4
|
||||
@ cdecl -arch=i386 _longjmpex(ptr long) ucrtbase._longjmpex
|
||||
@ cdecl -arch=x86_64 _local_unwind(ptr ptr) ucrtbase._local_unwind
|
||||
@ cdecl -arch=x86_64,arm64 _local_unwind(ptr ptr) ucrtbase._local_unwind
|
||||
@ cdecl _purecall() ucrtbase._purecall
|
||||
@ stdcall -arch=i386 _seh_longjmp_unwind4(ptr) ucrtbase._seh_longjmp_unwind4
|
||||
@ stdcall -arch=i386 _seh_longjmp_unwind(ptr) ucrtbase._seh_longjmp_unwind
|
||||
|
|
Loading…
Reference in New Issue