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 ea6cfa2a7f9..3366a435966 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,arm64 __C_specific_handler(ptr long ptr ptr) ucrtbase.__C_specific_handler +@ stdcall -arch=x86_64,arm,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 @@ -41,6 +41,7 @@ @ cdecl __intrinsic_abnormal_termination() ucrtbase.__intrinsic_abnormal_termination @ cdecl -arch=i386,x86_64,arm,arm64 -norelay __intrinsic_setjmp(ptr) ucrtbase.__intrinsic_setjmp @ cdecl -arch=x86_64,arm64 -norelay __intrinsic_setjmpex(ptr ptr) ucrtbase.__intrinsic_setjmpex +@ stdcall -arch=arm __jump_unwind(ptr ptr) ucrtbase.__jump_unwind @ cdecl __processing_throw() ucrtbase.__processing_throw @ stub __report_gsfailure @ cdecl __std_exception_copy(ptr ptr) ucrtbase.__std_exception_copy diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index c703219cfbb..e7c1fa1dcf3 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -1464,11 +1464,12 @@ @ cdecl -private -arch=i386 _CIpow() @ cdecl -private -arch=i386 _CIsin() @ cdecl -private -arch=i386 _CIsqrt() -@ stdcall -arch=x86_64,arm64 __C_specific_handler(ptr long ptr ptr) +@ stdcall -arch=x86_64,arm,arm64 __C_specific_handler(ptr long ptr ptr) @ cdecl -arch=arm,arm64,x86_64 -norelay __chkstk() @ cdecl __isascii(long) @ cdecl __iscsym(long) @ cdecl __iscsymf(long) +@ stdcall -arch=arm __jump_unwind(ptr ptr) @ cdecl __toascii(long) @ cdecl -norelay -arch=i386 -ret64 _alldiv(int64 int64) @ cdecl -arch=i386 -norelay _alldvrm(int64 int64) diff --git a/dlls/ntdll/signal_arm.c b/dlls/ntdll/signal_arm.c index a24cac97df7..72f3b023e45 100644 --- a/dlls/ntdll/signal_arm.c +++ b/dlls/ntdll/signal_arm.c @@ -37,6 +37,18 @@ 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 @@ -56,6 +68,20 @@ struct MSVCRT_JUMP_BUFFER unsigned long long D[8]; }; + +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 */ @@ -1260,6 +1286,125 @@ void WINAPI RtlUnwind( void *frame, void *target_ip, EXCEPTION_RECORD *rec, void } +/******************************************************************* + * __jump_unwind (NTDLL.@) + */ +void WINAPI __jump_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, + "push {r4-r11,lr}\n\t" + + __ASM_CFI(".cfi_def_cfa 13, 36\n\t") + __ASM_CFI(".cfi_offset r4, -36\n\t") + __ASM_CFI(".cfi_offset r5, -32\n\t") + __ASM_CFI(".cfi_offset r6, -28\n\t") + __ASM_CFI(".cfi_offset r7, -24\n\t") + __ASM_CFI(".cfi_offset r8, -20\n\t") + __ASM_CFI(".cfi_offset r9, -16\n\t") + __ASM_CFI(".cfi_offset r10, -12\n\t") + __ASM_CFI(".cfi_offset r11, -8\n\t") + __ASM_CFI(".cfi_offset lr, -4\n\t") + + "ldm r3, {r4-r11,lr}\n\t" + "blx r2\n\t" + "pop {r4-r11,pc}\n\t" ) + +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 -= 2; + + 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 d39387d5f00..831bff9eee1 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,arm64 __C_specific_handler(ptr long ptr ptr) ntdll.__C_specific_handler +@ stdcall -arch=x86_64,arm,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) @@ -100,6 +100,7 @@ @ cdecl __iscsymf(long) @ stub __iswcsym @ stub __iswcsymf +@ stdcall -arch=arm __jump_unwind(ptr ptr) ntdll.__jump_unwind @ cdecl -arch=i386 -norelay __libm_sse2_acos() @ cdecl -arch=i386 -norelay __libm_sse2_acosf() @ cdecl -arch=i386 -norelay __libm_sse2_asin() diff --git a/dlls/vcruntime140/vcruntime140.spec b/dlls/vcruntime140/vcruntime140.spec index 9ca10cc2a70..7bbb37afcec 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,arm64 __C_specific_handler(ptr long ptr ptr) ucrtbase.__C_specific_handler +@ stdcall -arch=x86_64,arm,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 @@ -34,6 +34,7 @@ @ cdecl __current_exception_context() ucrtbase.__current_exception_context @ cdecl -arch=i386,x86_64,arm,arm64 -norelay __intrinsic_setjmp(ptr) ucrtbase.__intrinsic_setjmp @ cdecl -arch=x86_64,arm64 -norelay __intrinsic_setjmpex(ptr ptr) ucrtbase.__intrinsic_setjmpex +@ stdcall -arch=arm __jump_unwind(ptr ptr) ucrtbase.__jump_unwind @ cdecl __processing_throw() ucrtbase.__processing_throw @ stub __report_gsfailure @ cdecl __std_exception_copy(ptr ptr) ucrtbase.__std_exception_copy