Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141/* * 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@reactos.org>*/
#include <precomp.h>#include <winnt.h>
_CRTIMPEXCEPTION_DISPOSITION__cdecl__C_specific_handler( struct _EXCEPTION_RECORD *ExceptionRecord, void *EstablisherFrame, struct _CONTEXT *ContextRecord, struct _DISPATCHER_CONTEXT *DispatcherContext){ 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 < 0 /* EXCEPTION_CONTINUE_EXECUTION */) { return ExceptionContinueExecution; }
if (FilterResult > 0 /* 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){ RtlUnwind(frame, target, NULL, 0);}