mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
[NTOS:KE:X64][NTDLL:X64] Implement KiUserExceptionDispatcher and fix KiDispatchExceptionToUser
This commit is contained in:
parent
1bfacf06f7
commit
2a8c680dbe
3 changed files with 151 additions and 24 deletions
|
@ -107,11 +107,125 @@ StatusRaise:
|
||||||
|
|
||||||
.ENDP
|
.ENDP
|
||||||
|
|
||||||
|
/*
|
||||||
|
BOOLEAN
|
||||||
|
NTAPI
|
||||||
|
RtlDispatchException(
|
||||||
|
_In_ PEXCEPTION_RECORD ExceptionRecord,
|
||||||
|
_In_ PCONTEXT ContextRecord);
|
||||||
|
*/
|
||||||
|
EXTERN RtlDispatchException:PROC
|
||||||
|
|
||||||
|
/*
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
ZwContinue(
|
||||||
|
_In_ PCONTEXT Context,
|
||||||
|
_In_ BOOLEAN TestAlert);
|
||||||
|
*/
|
||||||
|
EXTERN ZwContinue:PROC
|
||||||
|
|
||||||
|
/*
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
ZwRaiseException(
|
||||||
|
_In_ PEXCEPTION_RECORD ExceptionRecord,
|
||||||
|
_In_ PCONTEXT Context,
|
||||||
|
_In_ BOOLEAN SearchFrames);
|
||||||
|
*/
|
||||||
|
EXTERN ZwRaiseException:PROC
|
||||||
|
|
||||||
|
/*
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
RtlRaiseStatus(
|
||||||
|
_In_ PEXCEPTION_RECORD ExceptionRecord);
|
||||||
|
*/
|
||||||
|
EXTERN RtlRaiseException:PROC
|
||||||
|
|
||||||
|
/*
|
||||||
|
VOID
|
||||||
|
KiUserExceptionDispatcher(
|
||||||
|
CONTEXT ContextRecord<rcx>,
|
||||||
|
PEXCEPTION_RECORD ExceptionRecord<rdx>);
|
||||||
|
|
||||||
|
This function is called with the following stack layout:
|
||||||
|
CONTEXT ContextRecord <- RSP, RCX
|
||||||
|
EXCEPTION_RECORD ExceptionRecord <- RDX
|
||||||
|
ULONG64 Alignment
|
||||||
|
MACHINE_FRAME MachineFrame
|
||||||
|
*/
|
||||||
PUBLIC KiUserExceptionDispatcher
|
PUBLIC KiUserExceptionDispatcher
|
||||||
.PROC KiUserExceptionDispatcher
|
.PROC KiUserExceptionDispatcher
|
||||||
.endprolog
|
|
||||||
int 3
|
|
||||||
|
|
||||||
|
; The stack is set up with a KUSER_EXCEPTION_STACK
|
||||||
|
; The frame ends with a MACHINE_FRAME.
|
||||||
|
.PUSHFRAME
|
||||||
|
|
||||||
|
; This is for the alignment, EXCEPTION_RECORD and CONTEXT
|
||||||
|
.ALLOCSTACK 8 + EXCEPTION_RECORD_LENGTH + CONTEXT_FRAME_LENGTH
|
||||||
|
.ENDPROLOG
|
||||||
|
|
||||||
|
/* Clear direction flag */
|
||||||
|
cld
|
||||||
|
|
||||||
|
/* Dispatch the exception */
|
||||||
|
call RtlDispatchException
|
||||||
|
|
||||||
|
/* Check for success */
|
||||||
|
or al, al
|
||||||
|
jz RaiseException
|
||||||
|
|
||||||
|
/* We're fine, continue execution */
|
||||||
|
lea rcx, [rsp] ; ContextRecord
|
||||||
|
mov dl, 0 ; TestAlert
|
||||||
|
call ZwContinue
|
||||||
|
|
||||||
|
/* Exit */
|
||||||
|
jmp Exit
|
||||||
|
|
||||||
|
RaiseException:
|
||||||
|
|
||||||
|
/* Raise the exception */
|
||||||
|
lea rcx, [rsp + CONTEXT_FRAME_LENGTH] ; ExceptionRecord
|
||||||
|
lea rdx, [rsp] ; ContextRecord
|
||||||
|
xor r8, r8
|
||||||
|
call ZwRaiseException
|
||||||
|
|
||||||
|
Exit:
|
||||||
|
lea rcx, [rsp + CONTEXT_FRAME_LENGTH] ; ExceptionRecord
|
||||||
|
mov rdx, rax
|
||||||
|
call KiUserExceptionDispatcherNested
|
||||||
|
ret
|
||||||
|
|
||||||
|
.ENDP
|
||||||
|
|
||||||
|
/*
|
||||||
|
VOID
|
||||||
|
KiUserExceptionDispatcherNested(
|
||||||
|
_In_ ExceptionRecord<rcx>,
|
||||||
|
_In_ Status<edx>
|
||||||
|
)
|
||||||
|
*/
|
||||||
|
.PROC KiUserExceptionDispatcherNested
|
||||||
|
/* Allocate space for the nested exception record */
|
||||||
|
sub rsp, EXCEPTION_RECORD_LENGTH
|
||||||
|
.ALLOCSTACK EXCEPTION_RECORD_LENGTH
|
||||||
|
.ENDPROLOG
|
||||||
|
|
||||||
|
/* Set it up */
|
||||||
|
mov dword ptr [rsp + ErNumberParameters], 0
|
||||||
|
mov dword ptr [rsp + ErExceptionFlags], EXCEPTION_NONCONTINUABLE
|
||||||
|
mov [rsp + ErExceptionRecord], rcx
|
||||||
|
mov [rsp + ErExceptionCode], edx
|
||||||
|
|
||||||
|
/* Raise the exception */
|
||||||
|
mov rcx, rsp
|
||||||
|
call RtlRaiseException
|
||||||
|
|
||||||
|
/* Cleanup stack and return */
|
||||||
|
add rsp, EXCEPTION_RECORD_LENGTH
|
||||||
|
ret
|
||||||
.ENDP
|
.ENDP
|
||||||
|
|
||||||
END
|
END
|
||||||
|
|
|
@ -100,10 +100,8 @@ KiDispatchExceptionToUser(
|
||||||
IN PEXCEPTION_RECORD ExceptionRecord)
|
IN PEXCEPTION_RECORD ExceptionRecord)
|
||||||
{
|
{
|
||||||
EXCEPTION_RECORD LocalExceptRecord;
|
EXCEPTION_RECORD LocalExceptRecord;
|
||||||
ULONG Size;
|
|
||||||
ULONG64 UserRsp;
|
ULONG64 UserRsp;
|
||||||
PCONTEXT UserContext;
|
PKUSER_EXCEPTION_STACK UserStack;
|
||||||
PEXCEPTION_RECORD UserExceptionRecord;
|
|
||||||
|
|
||||||
/* Make sure we have a valid SS */
|
/* Make sure we have a valid SS */
|
||||||
if (TrapFrame->SegSs != (KGDT64_R3_DATA | RPL_MASK))
|
if (TrapFrame->SegSs != (KGDT64_R3_DATA | RPL_MASK))
|
||||||
|
@ -115,27 +113,29 @@ KiDispatchExceptionToUser(
|
||||||
ExceptionRecord = &LocalExceptRecord;
|
ExceptionRecord = &LocalExceptRecord;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Calculate the size of the exception record */
|
|
||||||
Size = FIELD_OFFSET(EXCEPTION_RECORD, ExceptionInformation) +
|
|
||||||
ExceptionRecord->NumberParameters * sizeof(ULONG64);
|
|
||||||
|
|
||||||
/* Get new stack pointer and align it to 16 bytes */
|
/* Get new stack pointer and align it to 16 bytes */
|
||||||
UserRsp = (Context->Rsp - Size - sizeof(CONTEXT)) & ~15;
|
UserRsp = (Context->Rsp - sizeof(KUSER_EXCEPTION_STACK)) & ~15;
|
||||||
|
|
||||||
/* Get pointers to the usermode context and exception record */
|
/* Get pointer to the usermode context, exception record and machine frame */
|
||||||
UserContext = (PVOID)UserRsp;
|
UserStack = (PKUSER_EXCEPTION_STACK)UserRsp;
|
||||||
UserExceptionRecord = (PVOID)(UserRsp + sizeof(CONTEXT));
|
|
||||||
|
|
||||||
/* Set up the user-stack */
|
/* Set up the user-stack */
|
||||||
_SEH2_TRY
|
_SEH2_TRY
|
||||||
{
|
{
|
||||||
/* Probe stack and copy Context */
|
/* Probe the user stack frame and zero it out */
|
||||||
ProbeForWrite(UserContext, sizeof(CONTEXT), sizeof(ULONG64));
|
ProbeForWrite(UserStack, sizeof(*UserStack), TYPE_ALIGNMENT(KUSER_EXCEPTION_STACK));
|
||||||
*UserContext = *Context;
|
RtlZeroMemory(UserStack, sizeof(*UserStack));
|
||||||
|
|
||||||
/* Probe stack and copy exception record */
|
/* Copy Context and ExceptionFrame */
|
||||||
ProbeForWrite(UserExceptionRecord, Size, sizeof(ULONG64));
|
UserStack->Context = *Context;
|
||||||
*UserExceptionRecord = *ExceptionRecord;
|
UserStack->ExceptionRecord = *ExceptionRecord;
|
||||||
|
|
||||||
|
/* Setup the machine frame */
|
||||||
|
UserStack->MachineFrame.Rip = Context->Rip;
|
||||||
|
UserStack->MachineFrame.SegCs = Context->SegCs;
|
||||||
|
UserStack->MachineFrame.EFlags = Context->EFlags;
|
||||||
|
UserStack->MachineFrame.Rsp = Context->Rsp;
|
||||||
|
UserStack->MachineFrame.SegSs = Context->SegSs;
|
||||||
}
|
}
|
||||||
_SEH2_EXCEPT((LocalExceptRecord = *_SEH2_GetExceptionInformation()->ExceptionRecord),
|
_SEH2_EXCEPT((LocalExceptRecord = *_SEH2_GetExceptionInformation()->ExceptionRecord),
|
||||||
EXCEPTION_EXECUTE_HANDLER)
|
EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
@ -148,8 +148,8 @@ KiDispatchExceptionToUser(
|
||||||
_SEH2_END;
|
_SEH2_END;
|
||||||
|
|
||||||
/* Now set the two params for the user-mode dispatcher */
|
/* Now set the two params for the user-mode dispatcher */
|
||||||
TrapFrame->Rcx = (ULONG64)UserContext;
|
TrapFrame->Rcx = (ULONG64)&UserStack->ExceptionRecord;
|
||||||
TrapFrame->Rdx = (ULONG64)UserExceptionRecord;
|
TrapFrame->Rdx = (ULONG64)&UserStack->Context;
|
||||||
|
|
||||||
/* Set new Stack Pointer */
|
/* Set new Stack Pointer */
|
||||||
TrapFrame->Rsp = UserRsp;
|
TrapFrame->Rsp = UserRsp;
|
||||||
|
@ -346,9 +346,10 @@ KiDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,
|
||||||
|
|
||||||
/* Forward exception to user mode debugger */
|
/* Forward exception to user mode debugger */
|
||||||
if (DbgkForwardException(ExceptionRecord, TRUE, FALSE)) return;
|
if (DbgkForwardException(ExceptionRecord, TRUE, FALSE)) return;
|
||||||
|
|
||||||
//KiDispatchExceptionToUser()
|
/* Forward exception to user mode (does not return) */
|
||||||
__debugbreak();
|
KiDispatchExceptionToUser(TrapFrame, &Context, ExceptionRecord);
|
||||||
|
NT_ASSERT(FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Try second chance */
|
/* Try second chance */
|
||||||
|
|
|
@ -998,6 +998,18 @@ typedef struct _UCALLOUT_FRAME
|
||||||
MACHINE_FRAME MachineFrame;
|
MACHINE_FRAME MachineFrame;
|
||||||
} UCALLOUT_FRAME, *PUCALLOUT_FRAME; // size = 0x0058
|
} UCALLOUT_FRAME, *PUCALLOUT_FRAME; // size = 0x0058
|
||||||
|
|
||||||
|
//
|
||||||
|
// Stack frame layout for KiUserExceptionDispatcher
|
||||||
|
// The name is totally made up
|
||||||
|
//
|
||||||
|
typedef struct _KUSER_EXCEPTION_STACK
|
||||||
|
{
|
||||||
|
CONTEXT Context;
|
||||||
|
EXCEPTION_RECORD ExceptionRecord;
|
||||||
|
ULONG64 Alignment;
|
||||||
|
MACHINE_FRAME MachineFrame;
|
||||||
|
} KUSER_EXCEPTION_STACK, * PKUSER_EXCEPTION_STACK;
|
||||||
|
|
||||||
typedef struct _DISPATCHER_CONTEXT
|
typedef struct _DISPATCHER_CONTEXT
|
||||||
{
|
{
|
||||||
ULONG64 ControlPc;
|
ULONG64 ControlPc;
|
||||||
|
|
Loading…
Reference in a new issue