windows-nt/Source/XPSP1/NT/base/ntos/rtl/i386/xcptmisc.asm

603 lines
16 KiB
NASM
Raw Normal View History

2020-09-26 03:20:57 -05:00
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