mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 01:55:19 +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
|
||||
|
||||
/*
|
||||
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
|
||||
.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
|
||||
|
||||
END
|
||||
|
|
|
@ -100,10 +100,8 @@ KiDispatchExceptionToUser(
|
|||
IN PEXCEPTION_RECORD ExceptionRecord)
|
||||
{
|
||||
EXCEPTION_RECORD LocalExceptRecord;
|
||||
ULONG Size;
|
||||
ULONG64 UserRsp;
|
||||
PCONTEXT UserContext;
|
||||
PEXCEPTION_RECORD UserExceptionRecord;
|
||||
PKUSER_EXCEPTION_STACK UserStack;
|
||||
|
||||
/* Make sure we have a valid SS */
|
||||
if (TrapFrame->SegSs != (KGDT64_R3_DATA | RPL_MASK))
|
||||
|
@ -115,27 +113,29 @@ KiDispatchExceptionToUser(
|
|||
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 */
|
||||
UserRsp = (Context->Rsp - Size - sizeof(CONTEXT)) & ~15;
|
||||
UserRsp = (Context->Rsp - sizeof(KUSER_EXCEPTION_STACK)) & ~15;
|
||||
|
||||
/* Get pointers to the usermode context and exception record */
|
||||
UserContext = (PVOID)UserRsp;
|
||||
UserExceptionRecord = (PVOID)(UserRsp + sizeof(CONTEXT));
|
||||
/* Get pointer to the usermode context, exception record and machine frame */
|
||||
UserStack = (PKUSER_EXCEPTION_STACK)UserRsp;
|
||||
|
||||
/* Set up the user-stack */
|
||||
_SEH2_TRY
|
||||
{
|
||||
/* Probe stack and copy Context */
|
||||
ProbeForWrite(UserContext, sizeof(CONTEXT), sizeof(ULONG64));
|
||||
*UserContext = *Context;
|
||||
/* Probe the user stack frame and zero it out */
|
||||
ProbeForWrite(UserStack, sizeof(*UserStack), TYPE_ALIGNMENT(KUSER_EXCEPTION_STACK));
|
||||
RtlZeroMemory(UserStack, sizeof(*UserStack));
|
||||
|
||||
/* Probe stack and copy exception record */
|
||||
ProbeForWrite(UserExceptionRecord, Size, sizeof(ULONG64));
|
||||
*UserExceptionRecord = *ExceptionRecord;
|
||||
/* Copy Context and ExceptionFrame */
|
||||
UserStack->Context = *Context;
|
||||
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),
|
||||
EXCEPTION_EXECUTE_HANDLER)
|
||||
|
@ -148,8 +148,8 @@ KiDispatchExceptionToUser(
|
|||
_SEH2_END;
|
||||
|
||||
/* Now set the two params for the user-mode dispatcher */
|
||||
TrapFrame->Rcx = (ULONG64)UserContext;
|
||||
TrapFrame->Rdx = (ULONG64)UserExceptionRecord;
|
||||
TrapFrame->Rcx = (ULONG64)&UserStack->ExceptionRecord;
|
||||
TrapFrame->Rdx = (ULONG64)&UserStack->Context;
|
||||
|
||||
/* Set new Stack Pointer */
|
||||
TrapFrame->Rsp = UserRsp;
|
||||
|
@ -346,9 +346,10 @@ KiDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,
|
|||
|
||||
/* Forward exception to user mode debugger */
|
||||
if (DbgkForwardException(ExceptionRecord, TRUE, FALSE)) return;
|
||||
|
||||
//KiDispatchExceptionToUser()
|
||||
__debugbreak();
|
||||
|
||||
/* Forward exception to user mode (does not return) */
|
||||
KiDispatchExceptionToUser(TrapFrame, &Context, ExceptionRecord);
|
||||
NT_ASSERT(FALSE);
|
||||
}
|
||||
|
||||
/* Try second chance */
|
||||
|
|
|
@ -998,6 +998,18 @@ typedef struct _UCALLOUT_FRAME
|
|||
MACHINE_FRAME MachineFrame;
|
||||
} 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
|
||||
{
|
||||
ULONG64 ControlPc;
|
||||
|
|
Loading…
Reference in a new issue