[PATCH 16/18] ntdll: Implement __C_specific_handler and __jump_unwind for arm.
Martin Storsjö
martin at martin.st
Tue Nov 9 08:05:53 CST 2021
Signed-off-by: Martin Storsjö <martin at martin.st>
---
.../api-ms-win-crt-private-l1-1-0.spec | 3 +-
dlls/ntdll/ntdll.spec | 3 +-
dlls/ntdll/signal_arm.c | 145 ++++++++++++++++++
dlls/ucrtbase/ucrtbase.spec | 3 +-
dlls/vcruntime140/vcruntime140.spec | 3 +-
5 files changed, 153 insertions(+), 4 deletions(-)
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
--
2.25.1
More information about the wine-devel
mailing list