diff options
Diffstat (limited to 'private/crt32/misc/ppc/chandler.c')
-rw-r--r-- | private/crt32/misc/ppc/chandler.c | 222 |
1 files changed, 222 insertions, 0 deletions
diff --git a/private/crt32/misc/ppc/chandler.c b/private/crt32/misc/ppc/chandler.c new file mode 100644 index 000000000..4badd7a1d --- /dev/null +++ b/private/crt32/misc/ppc/chandler.c @@ -0,0 +1,222 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + chandler.c + +Abstract: + + This module implements the C specific exception handler that provides + structured condition handling for the C language. + +Author: + + Modified for PowerPC by Rick Simpson 27-Sep-1993 + + + from MIPS version by David N. Cutler (davec) 11-Sep-1990 + +Environment: + + Any mode. + +Revision History: + + Tom Wood (twood) 1-Nov-1993 + Use __C_ExecuteExceptionFilter and __C_ExecuteTerminationHandler + previously deleted from the MIPS version. +--*/ + +#include "nt.h" + + +// +// Define procedure prototypes for exception filter and termination handler +// execution routines defined in jmpunwnd.s +// +LONG +__C_ExecuteExceptionFilter ( + PEXCEPTION_POINTERS ExceptionPointers, + EXCEPTION_FILTER ExceptionFilter, + ULONG EstablisherFrame + ); +VOID +__C_ExecuteTerminationHandler ( + BOOLEAN AbnormalTermination, + TERMINATION_HANDLER TerminationHandler, + ULONG EstablisherFrame + ); + +EXCEPTION_DISPOSITION +__C_specific_handler ( + IN PEXCEPTION_RECORD ExceptionRecord, + IN PVOID EstablisherFrame, + IN OUT PCONTEXT ContextRecord, + IN OUT PDISPATCHER_CONTEXT DispatcherContext + ) + +/*++ + +Routine Description: + + This function scans the scope tables associated with the specified + procedure and calls exception and termination handlers as necessary. + +Arguments: + + ExceptionRecord - Supplies a pointer to an exception record. + + EstablisherFrame - Supplies a pointer to frame of the establisher function. + + ContextRecord - Supplies a pointer to a context record. + + DispatcherContext - Supplies a pointer to the exception dispatcher or + unwind dispatcher context. + +Return Value: + + If the exception is handled by one of the exception filter routines, then + there is no return from this routine and RtlUnwind is called. Otherwise, + an exception disposition value of continue execution or continue search is + returned. + +--*/ + +{ + + ULONG ControlPc; + EXCEPTION_FILTER ExceptionFilter; + EXCEPTION_POINTERS ExceptionPointers; + PRUNTIME_FUNCTION FunctionEntry; + ULONG Index; + PSCOPE_TABLE ScopeTable; + ULONG TargetPc; + TERMINATION_HANDLER TerminationHandler; + LONG Value; + + // + // Get address of where control left the establisher, the address of the + // function table entry that describes the function, and the address of + // the scope table. + // + + ControlPc = DispatcherContext->ControlPc; + FunctionEntry = DispatcherContext->FunctionEntry; + ScopeTable = (PSCOPE_TABLE)(FunctionEntry->HandlerData); + + // + // If an unwind is not in progress, then scan the scope table and call + // the appropriate exception filter routines. Otherwise, scan the scope + // table and call the appropriate termination handlers using the target + // PC obtained from the context record. + // are called. + // + + if (IS_DISPATCHING(ExceptionRecord->ExceptionFlags)) { + + // + // Scan the scope table and call the appropriate exception filter + // routines. + // + + ExceptionPointers.ExceptionRecord = ExceptionRecord; + ExceptionPointers.ContextRecord = ContextRecord; + for (Index = 0; Index < ScopeTable->Count; Index += 1) { + if ((ControlPc >= ScopeTable->ScopeRecord[Index].BeginAddress) && + (ControlPc < ScopeTable->ScopeRecord[Index].EndAddress) && + (ScopeTable->ScopeRecord[Index].JumpTarget != 0)) { + + // + // Call the exception filter routine. + // + + ExceptionFilter = + (EXCEPTION_FILTER)ScopeTable->ScopeRecord[Index].HandlerAddress; + Value = __C_ExecuteExceptionFilter(&ExceptionPointers, + ExceptionFilter, + (ULONG)EstablisherFrame); + + // + // If the return value is less than zero, then dismiss the + // exception. Otherwise, if the value is greater than zero, + // then unwind to the target exception handler. Otherwise, + // continue the search for an exception filter. + // + + if (Value < 0) { + return ExceptionContinueExecution; + } else if (Value > 0) { + RtlUnwind(EstablisherFrame, + (PVOID)ScopeTable->ScopeRecord[Index].JumpTarget, + ExceptionRecord, + (PVOID)ExceptionRecord->ExceptionCode); + } + } + } + + } else { + + // + // Scan the scope table and call the appropriate termination handler + // routines. + // + + TargetPc = ContextRecord->Iar; + for (Index = 0; Index < ScopeTable->Count; Index += 1) { + if ((ControlPc >= ScopeTable->ScopeRecord[Index].BeginAddress) && + (ControlPc < ScopeTable->ScopeRecord[Index].EndAddress)) { + + // + // If the target PC is within the same scope the control PC + // is within, then this is an uplevel goto out of an inner try + // scope or a long jump back into a try scope. Terminate the + // scan termination handlers. + // + // N.B. The target PC can be just beyond the end of the scope, + // in which case it is a leave from the scope. + // + + + if ((TargetPc >= ScopeTable->ScopeRecord[Index].BeginAddress) && + (TargetPc <= ScopeTable->ScopeRecord[Index].EndAddress)) { + break; + + } else { + + // + // If the scope table entry describes an exception filter + // and the associated exception handler is the target of + // the unwind, then terminate the scan for termination + // handlers. Otherwise, if the scope table entry describes + // a termination handler, then record the address of the + // end of the scope as the new control PC address and call + // the termination handler. + // + + if (ScopeTable->ScopeRecord[Index].JumpTarget != 0) { + if (TargetPc == ScopeTable->ScopeRecord[Index].JumpTarget) { + break; + } + + } else { + DispatcherContext->ControlPc = + ScopeTable->ScopeRecord[Index].EndAddress + 4; + TerminationHandler = + (TERMINATION_HANDLER)ScopeTable->ScopeRecord[Index].HandlerAddress; + __C_ExecuteTerminationHandler(TRUE, + TerminationHandler, + (ULONG)EstablisherFrame); + } + } + } + } + } + + // + // Continue search for exception or termination handlers. + // + + return ExceptionContinueSearch; +} |