diff --git a/dlls/api-ms-win-crt-private-l1-1-0/api-ms-win-crt-private-l1-1-0.spec b/dlls/api-ms-win-crt-private-l1-1-0/api-ms-win-crt-private-l1-1-0.spec index f74cea4e14c..f9cfe67c1b0 100644 --- a/dlls/api-ms-win-crt-private-l1-1-0/api-ms-win-crt-private-l1-1-0.spec +++ b/dlls/api-ms-win-crt-private-l1-1-0/api-ms-win-crt-private-l1-1-0.spec @@ -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 diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 453c4827572..af1fac8df8e 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -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) diff --git a/dlls/ntdll/signal_arm64.c b/dlls/ntdll/signal_arm64.c index 7100da33d54..eb451603fe4 100644 --- a/dlls/ntdll/signal_arm64.c +++ b/dlls/ntdll/signal_arm64.c @@ -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.@) diff --git a/dlls/ucrtbase/ucrtbase.spec b/dlls/ucrtbase/ucrtbase.spec index 05ac3d3427a..4981d7fbac7 100644 --- a/dlls/ucrtbase/ucrtbase.spec +++ b/dlls/ucrtbase/ucrtbase.spec @@ -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 diff --git a/dlls/vcruntime140/vcruntime140.spec b/dlls/vcruntime140/vcruntime140.spec index 45d9370c86a..f799bcd4db5 100644 --- a/dlls/vcruntime140/vcruntime140.spec +++ b/dlls/vcruntime140/vcruntime140.spec @@ -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