|
|
title "Miscellaneous Exception Handling" ;++ ; ; Copyright (c) 1989 Microsoft Corporation ; ; Module Name: ; ; xcptmisc.asm ; ; 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, get ; the caller's stack pointer, get the caller's frame pointer, get the ; caller's floating status, get the caller's processor state, get the ; caller's extended processor status, and get the current stack limits. ; ; Author: ; ; David N. Cutler (davec) 14-Aug-1989 ; ; Environment: ; ; Any mode. ; ; Revision History: ; ; 6 April 90 bryanwi ; ; 386 version created ; ;-- .386p
.xlist include ks386.inc include callconv.inc ; calling convention macros .list
; ; Unwind flags. ;
Unwind equ EXCEPTION_UNWINDING OR EXCEPTION_EXIT_UNWIND
_TEXT$01 SEGMENT DWORD PUBLIC 'CODE' ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
page subttl "Execute Handler for Exception" ;++ ; ; EXCEPTION_DISPOSITION ; RtlpExecuteHandlerForException ( ; 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 handler address and ; 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 ; of this function is called and the handler address and establisher ; frame pointer are 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 (ebp+8) - Supplies a pointer to an exception record. ; ; EstablisherFrame (ebp+12) - Supplies the frame pointer of the establisher ; of the exception handler that is to be called. ; ; ContextRecord (ebp+16) - Supplies a pointer to a context record. ; ; DispatcherContext (ebp+20) - Supplies a pointer to the dispatcher context ; record. ; ; ExceptionRoutine (ebp+24) - 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. ; ;--
cPublicProc _RtlpExecuteHandlerForException,5
mov edx,offset FLAT:ExceptionHandler ; Set who to register jmp ExecuteHandler ; jump to common code
stdENDP _RtlpExecuteHandlerForException
page subttl "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 handler address and ; establisher frame pointer 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 handler address and establisher ; frame pointer 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 (ebp+8) - Supplies a pointer to an exception record. ; ; EstablisherFrame (ebp+12) - Supplies the frame pointer of the establisher ; of the exception handler that is to be called. ; ; ContextRecord (ebp+16) - Supplies a pointer to a context record. ; ; DispatcherContext (ebp+20) - Supplies a pointer to the dispatcher context ; record. ; ; ExceptionRoutine (ebp+24) - 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. ; ;--
cPublicProc _RtlpExecuteHandlerForUnwind ,5
mov edx,offset FLAT:UnwindHandler
;; N.B. - FALL into ExecuteHandler
stdENDP _RtlpExecuteHandlerForUnwind
; ; ExecuteHandler is the common tail for RtlpExecuteHandlerForException ; and RtlpExecuteHandlerForUnwind - we clean up some registers so they don't ; leak through the handler, then call the real execute code. ; ; (edx) = handler (Exception or Unwind) address ;
cPublicProc ExecuteHandler,5 push ebx push esi push edi xor eax, eax xor ebx, ebx xor esi, esi xor edi, edi push [esp+32] ; ExceptionRoutine push [esp+32] ; DispatcherContext push [esp+32] ; ContextRecord push [esp+32] ; EstablisherFrame push [esp+32] ; ExceptionRecord call ExecuteHandler2 pop edi pop esi pop ebx stdRET ExecuteHandler stdENDP ExecuteHandler
ExceptionRecord equ [ebp+8] EstablisherFrame equ [ebp+12] ContextRecord equ [ebp+16] DispatcherContext equ [ebp+20] ExceptionRoutine equ [ebp+24]
cPublicProc ExecuteHandler2,5
push ebp mov ebp,esp
push EstablisherFrame ; Save context of exception handler ; that we're about to call.
.errnz ErrHandler-4 push edx ; Set Handler address
.errnz ErrNext-0 push fs:PcExceptionList ; Set next pointer
mov fs:PcExceptionList,esp ; Link us on
; Call the specified exception handler.
push DispatcherContext push ContextRecord push EstablisherFrame push ExceptionRecord
mov ecx,ExceptionRoutine call ecx mov esp,fs:PcExceptionList
; Don't clean stack here, code in front of ret will blow it off anyway
; Disposition is in eax, so all we do is deregister handler and return
.errnz ErrNext-0 pop fs:PcExceptionList
mov esp,ebp pop ebp stdRET ExecuteHandler2
stdENDP ExecuteHandler2
page subttl "Local Exception Handler" ;++ ; ; EXCEPTION_DISPOSITION ; ExceptionHandler ( ; IN PEXCEPTION_RECORD ExceptionRecord, ; IN PVOID EstablisherFrame, ; IN OUT PCONTEXT ContextRecord, ; IN OUT PVOID DispatcherContext ; ) ; ; Routine Description: ; ; This function is called when a nested exception occurs. Its function ; is to retrieve the establisher frame pointer and handler address from ; its establisher's call frame, store this information in the dispatcher ; context record, and return a disposition value of nested exception. ; ; Arguments: ; ; ExceptionRecord (exp+4) - Supplies a pointer to an exception record. ; ; EstablisherFrame (esp+8) - Supplies the frame pointer of the establisher ; of this exception handler. ; ; ContextRecord (esp+12) - Supplies a pointer to a context record. ; ; DispatcherContext (esp+16) - 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. ; ;--
stdPROC ExceptionHandler,4
mov ecx,dword ptr [esp+4] ; (ecx) -> ExceptionRecord test dword ptr [ecx.ErExceptionFlags],Unwind mov eax,ExceptionContinueSearch ; Assume unwind jnz eh10 ; unwind, go return
; ; Unwind is not in progress - return nested exception disposition. ;
mov ecx,[esp+8] ; (ecx) -> EstablisherFrame mov edx,[esp+16] ; (edx) -> DispatcherContext mov eax,[ecx+8] ; (eax) -> EstablisherFrame for the ; handler active when we ; nested. mov [edx],eax ; Set DispatcherContext field. mov eax,ExceptionNestedException
eh10: stdRET ExceptionHandler
stdENDP ExceptionHandler
page subttl "Local Unwind Handler" ;++ ; ; EXCEPTION_DISPOSITION ; UnwindHandler ( ; 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 frame pointer and handler address from ; its establisher's call frame, store this information in the dispatcher ; context record, and return a disposition value of nested unwind. ; ; Arguments: ; ; ExceptionRecord (esp+4) - Supplies a pointer to an exception record. ; ; EstablisherFrame (esp+8) - Supplies the frame pointer of the establisher ; of this exception handler. ; ; ContextRecord (esp+12) - Supplies a pointer to a context record. ; ; DispatcherContext (esp+16) - 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. ; ;--
stdPROC UnwindHandler,4
mov ecx,dword ptr [esp+4] ; (ecx) -> ExceptionRecord test dword ptr [ecx.ErExceptionFlags],Unwind mov eax,ExceptionContinueSearch ; Assume NOT unwind jz uh10 ; not unwind, go return
; ; Unwind is in progress - return collided unwind disposition. ;
mov ecx,[esp+8] ; (ecx) -> EstablisherFrame mov edx,[esp+16] ; (edx) -> DispatcherContext mov eax,[ecx+8] ; (eax) -> EstablisherFrame for the ; handler active when we ; nested. mov [edx],eax ; Set DispatcherContext field. mov eax,ExceptionCollidedUnwind
uh10: stdRET UnwindHandler
stdENDP UnwindHandler
page subttl "Unlink Exception Registration Record & Handler" ;++ ; ; VOID ; RtlpUnlinkHandler(PEXCEPTION_REGISTRATION_RECORD UnlinkPointer) ; ; Routine Description: ; ; This function removes the specified exception registration record ; (and thus the relevent handler) from the exception traversal ; chain. ; ; Arguments: ; ; UnlinkPointer (esp+4) - Address of registration record to unlink. ; ; Return Value: ; ; The caller's return address. ; ;--
cPublicProc _RtlpUnlinkHandler ,1
mov ecx,dword ptr [esp+4] mov ecx,[ecx.ErrNext] mov fs:PcExceptionList,ecx stdRET _RtlpUnlinkHandler
stdENDP _RtlpUnlinkHandler
page subttl "Capture Context" ;++ ; ; VOID ; RtlCaptureContext (PCONTEXT ContextRecord) ; RtlpCaptureContext (PCONTEXT ContextRecord) ; ; Routine Description: ; ; This fucntion fills in the specified context record with the ; current state of the machine, except that the values of EBP ; and ESP are computed to be those of the caller's caller. ; ; N.B. This function assumes it is called from a 'C' procedure with ; the old ebp at [ebp], the return address at [ebp+4], and ; old esp = ebp + 8. ; ; Certain 'C' optimizations may cause this to not be true. ; ; N.B. This function does NOT adjust ESP to pop the arguments off ; the caller's stack. In other words, it provides a __cdecl ESP, ; NOT a __stdcall ESP. This is mainly because we can't figure ; out how many arguments the caller takes. ; ; N.B. Floating point state is NOT captured. ; ; RtlpCaptureContext does not capture volitales. ; RtlCaptureContext captures volitales. ; ; Arguments: ; ; ContextRecord (esp+4) - Address of context record to fill in. ; ; Return Value: ; ; The caller's return address. ; ;--
cPublicProc _RtlCaptureContext ,1
push ebx mov ebx,[esp+8] ; (ebx) -> ContextRecord
mov dword ptr [ebx.CsEax],eax mov dword ptr [ebx.CsEcx],ecx mov dword ptr [ebx.CsEdx],edx mov eax, [esp] mov dword ptr [ebx.CsEbx],eax
mov dword ptr [ebx.CsEsi],esi mov dword ptr [ebx.CsEdi],edi jmp RtlpCaptureCommon stdENDP _RtlCaptureContext
cPublicProc _RtlpCaptureContext ,1
push ebx mov ebx,[esp+8] ; (ebx) -> ContextRecord
mov dword ptr [ebx.CsEax],0 mov dword ptr [ebx.CsEcx],0 mov dword ptr [ebx.CsEdx],0 mov dword ptr [ebx.CsEbx],0
mov dword ptr [ebx.CsEsi],0 mov dword ptr [ebx.CsEdi],0
RtlpCaptureCommon: mov [ebx.CsSegCs],cs mov [ebx.CsSegDs],ds mov [ebx.CsSegEs],es mov [ebx.CsSegFs],fs mov [ebx.CsSegGs],gs mov [ebx.CsSegSs],ss
pushfd pop [ebx.CsEflags]
mov eax,[ebp+4] mov [ebx.CsEip],eax
mov eax,[ebp] mov [ebx.CsEbp],eax
lea eax,[ebp+8] mov [ebx.CsEsp],eax
pop ebx stdRET _RtlpCaptureContext
stdENDP _RtlpCaptureContext
page subttl "Capture Context (private)" ;++ ; ; VOID ; RtlCaptureContext (PCONTEXT ContextRecord) ; ; Routine Description: ; ; This function is similiar too RtlpCaptureContext expect that ; volitales are captured as well. ; ; This fucntion fills in the specified context record with the ; current state of the machine, except that the values of EBP ; and ESP are computed to be those of the caller's caller. ; ; N.B. This function does NOT adjust ESP to pop the arguments off ; the caller's stack. In other words, it provides a __cdecl ESP, ; NOT a __stdcall ESP. This is mainly because we can't figure ; out how many arguments the caller takes. ; ; N.B. Floating point state is NOT captured. ; ; Arguments: ; ; ContextRecord (esp+4) - Address of context record to fill in. ; ; Return Value: ; ; The caller's return address. ; ;--
ifndef WX86_i386 page subttl "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. ; ; On the 386 we always store the stack limits in the PCR, and address ; both PCR and TEB the same way, so this code is mode independent. ; ; Arguments: ; ; LowLimit (esp+4) - Supplies a pointer to a variable that is to receive ; the low limit of the stack. ; ; HighLimit (esp+8) - Supplies a pointer to a variable that is to receive ; the high limit of the stack. ; ; Return Value: ; ; None. ; ;--
cPublicProc _RtlpGetStackLimits ,2 ;cPublicFpo 2,0
mov eax,fs:PcStackLimit mov ecx,[esp+4] mov [ecx],eax ; Save low limit
mov eax,fs:PcInitialStack mov ecx,[esp+8] mov [ecx],eax ; Save high limit
stdRET _RtlpGetStackLimits
stdENDP _RtlpGetStackLimits
endif page subttl "Get Exception Registration List Head" ;++ ; ; PVOID ; RtlpGetRegistrationHead() ; ; Routine Description: ; ; This function returns the address of the first Exception ; registration record for the current context. ; ; Arguments: ; ; None. ; ; Return Value: ; ; The address of the first registration record. ; ;--
cPublicProc _RtlpGetRegistrationHead ,0 ;cPublicFpo 0,0
mov eax,fs:PcExceptionList stdRET _RtlpGetRegistrationHead
stdENDP _RtlpGetRegistrationHead _TEXT$01 ends end
|