Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

356 lines
12 KiB

// TITLE("Miscellaneous Exception Handling")
//++
//
// Copyright (c) 1990 Microsoft Corporation
//
// Module Name:
//
// xcptmisc.s
//
// Abstract:
//
// This module implements miscellaneous routines that are required to
// support exception handling. Functions are provided to call an exception
// handler for an exception, call an exception handler for unwinding, call
// an exception filter, call a termination handler, and get the caller's
// stack limits.
//
// Author:
//
// David N. Cutler (davec) 12-Sep-1990
//
// Environment:
//
// Any mode.
//
// Revision History:
//
//--
#include "ksmips.h"
//
// Define call frame for calling exception handlers.
//
.struct 0
CfArg: .space 4 * 4 // argument register save area
.space 3 * 4 // fill for alignment
CfRa: .space 4 // saved return address
CfFrameLength: // length of stack frame
CfA0: .space 4 // caller argument save area
CfA1: .space 4 //
CfA2: .space 4 //
CfA3: .space 4 //
CfExr: .space 4 // address of exception routine
SBTTL("Execute Handler for Exception")
//++
//
// EXCEPTION_DISPOSITION
// RtlpExecuteHandlerForException (
// IN PEXCEPTION_RECORD ExceptionRecord,
// IN ULONG EstablisherFrame,
// IN OUT PCONTEXT ContextRecord,
// IN OUT PDISPATCHER_CONTEXT DispatcherContext,
// IN PEXCEPTION_ROUTINE ExceptionRoutine
// )
//
// Routine Description:
//
// This function allocates a call frame, stores the establisher frame
// pointer in the frame, establishes an exception handler, and then calls
// the specified exception handler as an exception handler. If a nested
// exception occurs, then the exception handler of this function is called
// and the establisher frame pointer is returned to the exception dispatcher
// via the dispatcher context parameter. If control is returned to this
// routine, then the frame is deallocated and the disposition status is
// returned to the exception dispatcher.
//
// Arguments:
//
// ExceptionRecord (a0) - Supplies a pointer to an exception record.
//
// EstablisherFrame (a1) - Supplies the frame pointer of the establisher
// of the exception handler that is to be called.
//
// ContextRecord (a2) - Supplies a pointer to a context record.
//
// DispatcherContext (a3) - Supplies a pointer to the dispatcher context
// record.
//
// ExceptionRoutine (4 * 4(sp)) - supplies a pointer to the exception handler
// that is to be called.
//
// Return Value:
//
// The disposition value returned by the specified exception handler is
// returned as the function value.
//
//--
EXCEPTION_HANDLER(RtlpExceptionHandler)
NESTED_ENTRY(RtlpExecuteHandlerForException, CfFrameLength, zero)
subu sp,sp,CfFrameLength // allocate stack frame
sw ra,CfRa(sp) // save return address
PROLOGUE_END
lw t0,CfExr(sp) // get address of exception routine
sw a3,CfA3(sp) // save address of dispatcher context
jal t0 // call exception exception handler
lw ra,CfRa(sp) // restore return address
addu sp,sp,CfFrameLength // deallocate stack frame
j ra // return
.end RtlpExecuteHandlerForException
SBTTL("Local Exception Handler")
//++
//
// EXCEPTION_DISPOSITION
// RtlpExceptionHandler (
// IN PEXCEPTION_RECORD ExceptionRecord,
// IN ULONG EstablisherFrame,
// IN OUT PCONTEXT ContextRecord,
// IN OUT PDISPATCHER_CONTEXT DispatcherContext
// )
//
// Routine Description:
//
// This function is called when a nested exception occurs. Its function
// is to retrieve the establisher frame pointer from its establisher's
// call frame, store this information in the dispatcher context record,
// and return a disposition value of nested exception.
//
// Arguments:
//
// ExceptionRecord (a0) - Supplies a pointer to an exception record.
//
// EstablisherFrame (a1) - Supplies the frame pointer of the establisher
// of this exception handler.
//
// ContextRecord (a2) - Supplies a pointer to a context record.
//
// DispatcherContext (a3) - Supplies a pointer to the dispatcher context
// record.
//
// Return Value:
//
// A disposition value ExceptionNestedException is returned if an unwind
// is not in progress. Otherwise a value of ExceptionContinueSearch is
// returned.
//
//--
LEAF_ENTRY(RtlpExceptionHandler)
lw t0,ErExceptionFlags(a0) // get exception flags
and t0,t0,EXCEPTION_UNWIND // check if unwind in progress
bne zero,t0,10f // if neq, unwind in progress
//
// Unwind is not in progress - return nested exception disposition.
//
lw t0,CfA3 - CfA0(a1) // get dispatcher context address
li v0,ExceptionNestedException // set disposition value
lw t1,DcEstablisherFrame(t0) // copy the establisher frame pointer
sw t1,DcEstablisherFrame(a3) // to current dispatcher context
j ra // return
//
// Unwind is in progress - return continue search disposition.
//
10: li v0,ExceptionContinueSearch // set disposition value
j ra // return
.end RtlpExceptionHandler)
SBTTL("Execute Handler for Unwind")
//++
//
// EXCEPTION_DISPOSITION
// RtlpExecuteHandlerForUnwind (
// IN PEXCEPTION_RECORD ExceptionRecord,
// IN PVOID EstablisherFrame,
// IN OUT PCONTEXT ContextRecord,
// IN OUT PVOID DispatcherContext,
// IN PEXCEPTION_ROUTINE ExceptionRoutine
// )
//
// Routine Description:
//
// This function allocates a call frame, stores the establisher frame
// pointer and the context record address in the frame, establishes an
// exception handler, and then calls the specified exception handler as
// an unwind handler. If a collided unwind occurs, then the exception
// handler of of this function is called and the establisher frame pointer
// and context record address are returned to the unwind dispatcher via
// the dispatcher context parameter. If control is returned to this routine,
// then the frame is deallocated and the disposition status is returned to
// the unwind dispatcher.
//
// Arguments:
//
// ExceptionRecord (a0) - Supplies a pointer to an exception record.
//
// EstablisherFrame (a1) - Supplies the frame pointer of the establisher
// of the exception handler that is to be called.
//
// ContextRecord (a2) - Supplies a pointer to a context record.
//
// DispatcherContext (a3) - Supplies a pointer to the dispatcher context
// record.
//
// ExceptionRoutine (4 * 4(sp)) - supplies a pointer to the exception handler
// that is to be called.
//
// Return Value:
//
// The disposition value returned by the specified exception handler is
// returned as the function value.
//
//--
EXCEPTION_HANDLER(RtlpUnwindHandler)
NESTED_ENTRY(RtlpExecuteHandlerForUnwind, CfFrameLength, zero)
subu sp,sp,CfFrameLength // allocate stack frame
sw ra,CfRa(sp) // save return address
PROLOGUE_END
lw t0,CfExr(sp) // get address of exception routine
sw a3,CfA3(sp) // save address of dispatcher context
jal t0 // call exception unwind handler
lw ra,CfRa(sp) // restore return address
addu sp,sp,CfFrameLength // deallocate stack frame
j ra // return
.end RtlpExecuteHandlerForUnwind
SBTTL("Local Unwind Handler")
//++
//
// EXCEPTION_DISPOSITION
// RtlpUnwindHandler (
// IN PEXCEPTION_RECORD ExceptionRecord,
// IN PVOID EstablisherFrame,
// IN OUT PCONTEXT ContextRecord,
// IN OUT PVOID DispatcherContext
// )
//
// Routine Description:
//
// This function is called when a collided unwind occurs. Its function
// is to retrieve the establisher dispatcher context, copy it to the
// current dispatcher context, and return a disposition value of nested
// unwind.
//
// Arguments:
//
// ExceptionRecord (a0) - Supplies a pointer to an exception record.
//
// EstablisherFrame (a1) - Supplies the frame pointer of the establisher
// of this exception handler.
//
// ContextRecord (a2) - Supplies a pointer to a context record.
//
// DispatcherContext (a3) - Supplies a pointer to the dispatcher context
// record.
//
// Return Value:
//
// A disposition value ExceptionCollidedUnwind is returned if an unwind is
// in progress. Otherwise, a value of ExceptionContinueSearch is returned.
//
//--
LEAF_ENTRY(RtlpUnwindHandler)
lw t0,ErExceptionFlags(a0) // get exception flags
and t0,t0,EXCEPTION_UNWIND // check if unwind in progress
beq zero,t0,10f // if eq, unwind not in progress
//
// Unwind is in progress - return collided unwind disposition.
//
lw t0,CfA3 - CfA0(a1) // get dispatcher context address
li v0,ExceptionCollidedUnwind // set disposition value
lw t1,DcControlPc(t0) // Copy the establisher frames'
lw t2,DcFunctionEntry(t0) // dispatcher context to the current
lw t3,DcEstablisherFrame(t0) // dispatcher context
lw t4,DcContextRecord(t0) //
sw t1,DcControlPc(a3) //
sw t2,DcFunctionEntry(a3) //
sw t3,DcEstablisherFrame(a3) //
sw t4,DcContextRecord(a3) //
j ra // return
//
// Unwind is not in progress - return continue search disposition.
//
10: li v0,ExceptionContinueSearch // set disposition value
j ra // return
.end RtlpUnwindHandler
SBTTL("Get Stack Limits")
//++
//
// VOID
// RtlpGetStackLimits (
// OUT PULONG LowLimit,
// OUT PULONG HighLimit
// )
//
// Routine Description:
//
// This function returns the current stack limits based on the current
// processor mode.
//
// Arguments:
//
// LowLimit (a0) - Supplies a pointer to a variable that is to receive
// the low limit of the stack.
//
// HighLimit (a1) - Supplies a pointer to a variable that is to receive
// the high limit of the stack.
//
// Return Value:
//
// None.
//
//--
LEAF_ENTRY(RtlpGetStackLimits)
li t0,UsPcr // get address of user PCR
bgez sp,10f // if gez, current mode is user
//
// Current mode is kernel - compute stack limits.
//
lw t1,KiPcr + PcInitialStack(zero) // get high limit kernel stack
lw t2,KiPcr + PcStackLimit(zero) // get low limit kernel stack
b 20f // finish in commom code
//
// Current mode is user - get stack limits from the TEB.
//
10: lw t0,PcTeb(t0) // get address of TEB
lw t2,TeStackLimit(t0) // get low limit of user stack
lw t1,TeStackBase(t0) // get high limit of user stack
20: sw t2,0(a0) // store low stack limit
sw t1,0(a1) // store high stack limit
j ra // return
.end RtlpGetStackLimits