https://git.reactos.org/?p=reactos.git;a=commitdiff;h=0520c75aaf3a9334d209e…
commit 0520c75aaf3a9334d209e6b5ec04f15cb9b773c4
Author: Timo Kreuzer <timo.kreuzer(a)reactos.org>
AuthorDate: Thu Mar 1 14:22:18 2018 +0100
Commit: Timo Kreuzer <timo.kreuzer(a)reactos.org>
CommitDate: Sat Jun 5 13:52:42 2021 +0200
[CRT] Implement __C_specific_handler
---
sdk/lib/crt/except/amd64/ehandler.c | 132 ++++++++++++++++++++++++++++++++++--
1 file changed, 125 insertions(+), 7 deletions(-)
diff --git a/sdk/lib/crt/except/amd64/ehandler.c b/sdk/lib/crt/except/amd64/ehandler.c
index 6e28e78e604..b32b821d6c9 100644
--- a/sdk/lib/crt/except/amd64/ehandler.c
+++ b/sdk/lib/crt/except/amd64/ehandler.c
@@ -1,19 +1,137 @@
+/*
+ * PROJECT: ReactOS CRT library
+ * LICENSE: MIT (
https://spdx.org/licenses/MIT)
+ * PURPOSE: C specific exception/unwind handler for AMD64
+ * COPYRIGHT: Copyright 2018-2021 Timo Kreuzer <timo.kreuzer(a)reactos.org>
+*/
#include <precomp.h>
+#include <winnt.h>
_CRTIMP
EXCEPTION_DISPOSITION
__cdecl
__C_specific_handler(
- struct _EXCEPTION_RECORD *_ExceptionRecord,
- void *_EstablisherFrame,
- struct _CONTEXT *_ContextRecord,
- struct _DISPATCHER_CONTEXT *_DispatcherContext)
+ struct _EXCEPTION_RECORD *ExceptionRecord,
+ void *EstablisherFrame,
+ struct _CONTEXT *ContextRecord,
+ struct _DISPATCHER_CONTEXT *DispatcherContext)
{
- UNIMPLEMENTED;
- __debugbreak();
- return 0;
+ PSCOPE_TABLE ScopeTable;
+ ULONG i, BeginAddress, EndAddress, Handler;
+ ULONG64 ImageBase, JumpTarget, IpOffset, TargetIpOffset;
+ EXCEPTION_POINTERS ExceptionPointers;
+ PTERMINATION_HANDLER TerminationHandler;
+ PEXCEPTION_FILTER ExceptionFilter;
+ LONG FilterResult;
+
+ /* Set up the EXCEPTION_POINTERS */
+ ExceptionPointers.ExceptionRecord = ExceptionRecord;
+ ExceptionPointers.ContextRecord = ContextRecord;
+
+ /* Get the image base */
+ ImageBase = (ULONG64)DispatcherContext->ImageBase;
+
+ /* Get the image base relative instruction pointers */
+ IpOffset = DispatcherContext->ControlPc - ImageBase;
+ TargetIpOffset = DispatcherContext->TargetIp - ImageBase;
+
+ /* Get the scope table and current index */
+ ScopeTable = (PSCOPE_TABLE)DispatcherContext->HandlerData;
+
+ /* Loop while we have scope table entries */
+ while (DispatcherContext->ScopeIndex < ScopeTable->Count)
+ {
+ /* Use i as index and update the dispatcher context */
+ i = DispatcherContext->ScopeIndex++;
+
+ /* Get the start and end of the scrope */
+ BeginAddress = ScopeTable->ScopeRecord[i].BeginAddress;
+ EndAddress = ScopeTable->ScopeRecord[i].EndAddress;
+
+ /* Skip this scope if we are not within the bounds */
+ if ((IpOffset < BeginAddress) || (IpOffset >= EndAddress))
+ {
+ continue;
+ }
+
+ /* Check if this is an unwind */
+ if (ExceptionRecord->ExceptionFlags & EXCEPTION_UNWIND)
+ {
+ /* Check if this is a target unwind */
+ if (ExceptionRecord->ExceptionFlags & EXCEPTION_TARGET_UNWIND)
+ {
+ /* Check if the target is within the scope itself */
+ if ((TargetIpOffset >= BeginAddress) &&
+ (TargetIpOffset < EndAddress))
+ {
+ return ExceptionContinueSearch;
+ }
+ }
+
+ /* Check if this is a termination handler / finally function */
+ if (ScopeTable->ScopeRecord[i].JumpTarget == 0)
+ {
+ /* Call the handler */
+ Handler = ScopeTable->ScopeRecord[i].HandlerAddress;
+ TerminationHandler = (PTERMINATION_HANDLER)(ImageBase + Handler);
+ TerminationHandler(TRUE, EstablisherFrame);
+ }
+ else if (ScopeTable->ScopeRecord[i].JumpTarget == TargetIpOffset)
+ {
+ return ExceptionContinueSearch;
+ }
+ }
+ else
+ {
+ /* We are only unterested in exception handlers */
+ if (ScopeTable->ScopeRecord[i].JumpTarget == 0)
+ {
+ continue;
+ }
+
+ /* This is an exception filter, get the handler address */
+ Handler = ScopeTable->ScopeRecord[i].HandlerAddress;
+
+ /* Check for hardcoded EXCEPTION_EXECUTE_HANDLER */
+ if (Handler == EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* This is our result */
+ FilterResult = EXCEPTION_EXECUTE_HANDLER;
+ }
+ else
+ {
+ /* Otherwise we need to call the handler */
+ ExceptionFilter = (PEXCEPTION_FILTER)(ImageBase + Handler);
+ FilterResult = ExceptionFilter(&ExceptionPointers,
EstablisherFrame);
+ }
+
+ if (FilterResult == EXCEPTION_CONTINUE_EXECUTION)
+ {
+ return ExceptionContinueExecution;
+ }
+
+ if (FilterResult == EXCEPTION_EXECUTE_HANDLER)
+ {
+ JumpTarget = (ImageBase + ScopeTable->ScopeRecord[i].JumpTarget);
+
+ /* Unwind to the target address (This does not return) */
+ RtlUnwindEx(EstablisherFrame,
+ (PVOID)JumpTarget,
+ ExceptionRecord,
+ UlongToPtr(ExceptionRecord->ExceptionCode),
+ DispatcherContext->ContextRecord,
+ DispatcherContext->HistoryTable);
+
+ /* Should not get here */
+ __debugbreak();
+ }
+ }
+ }
+
+ /* Reached the end of the scope table */
+ return ExceptionContinueSearch;
}
void __cdecl _local_unwind(void* frame, void* target)