mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 01:55:19 +00:00
[RTL/x64] Implement RtlRaiseException in asm
This fixes invalid contexts being passed to RtlDispatchException. Also update the ExceptionAddress field in the EXCEPTION_FRAME, to match the Rip value in the CONTEXT, which is required for proper unwinding.
This commit is contained in:
parent
ba170757d6
commit
83e741c643
2 changed files with 75 additions and 44 deletions
|
@ -13,50 +13,6 @@
|
|||
|
||||
/* PUBLIC FUNCTIONS **********************************************************/
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
RtlRaiseException(IN PEXCEPTION_RECORD ExceptionRecord)
|
||||
{
|
||||
CONTEXT Context;
|
||||
NTSTATUS Status = STATUS_INVALID_DISPOSITION;
|
||||
|
||||
/* Capture the current context */
|
||||
RtlCaptureContext(&Context);
|
||||
|
||||
/* Fix up Context.Rip for the caller */
|
||||
Context.Rip = (ULONG64)_ReturnAddress();
|
||||
|
||||
/* Fix up Context.Rsp for the caller */
|
||||
Context.Rsp = (ULONG64)_AddressOfReturnAddress() + 8;
|
||||
|
||||
/* Save the exception address */
|
||||
ExceptionRecord->ExceptionAddress = (PVOID)Context.Rip;
|
||||
|
||||
/* Check if user mode debugger is active */
|
||||
if (RtlpCheckForActiveDebugger())
|
||||
{
|
||||
/* Raise an exception immediately */
|
||||
Status = ZwRaiseException(ExceptionRecord, &Context, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Dispatch the exception and check if we should continue */
|
||||
if (!RtlDispatchException(ExceptionRecord, &Context))
|
||||
{
|
||||
/* Raise the exception */
|
||||
Status = ZwRaiseException(ExceptionRecord, &Context, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Continue, go back to previous context */
|
||||
Status = ZwContinue(&Context, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
/* If we returned, raise a status */
|
||||
RtlRaiseStatus(Status);
|
||||
}
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
|
|
|
@ -233,6 +233,81 @@ ReturnFar:
|
|||
|
||||
.ENDP
|
||||
|
||||
EXTERN RtlpCheckForActiveDebugger:PROC
|
||||
EXTERN RtlDispatchException:PROC
|
||||
EXTERN ZwContinue:PROC
|
||||
EXTERN ZwRaiseException:PROC
|
||||
EXTERN RtlRaiseStatus:PROC
|
||||
|
||||
/*
|
||||
* VOID
|
||||
* RtlRaiseException (
|
||||
* _In_ PEXCEPTION_RECORD ExceptionRecord);
|
||||
*/
|
||||
PUBLIC RtlRaiseException
|
||||
.PROC RtlRaiseException
|
||||
|
||||
/* Allocate stack space for a CONTEXT record */
|
||||
sub rsp, CONTEXT_FRAME_LENGTH + 8
|
||||
.allocstack CONTEXT_FRAME_LENGTH + 8
|
||||
|
||||
/* Save the ExceptionRecord pointer */
|
||||
mov [rsp + CONTEXT_FRAME_LENGTH + 8 + P1Home], rcx
|
||||
|
||||
.endprolog
|
||||
|
||||
/* Save the return address in EXCEPTION_RECORD.ExceptionAddress */
|
||||
mov rdx, [rsp + CONTEXT_FRAME_LENGTH + 8]
|
||||
mov [rcx + ErExceptionAddress], rdx
|
||||
|
||||
/* Capture the current context */
|
||||
mov rcx, rsp
|
||||
call RtlCaptureContext
|
||||
|
||||
/* Fix up CONTEXT.Rip for the caller (RtlCaptureContext doesn't change rdx!) */
|
||||
mov [rsp + CxRip], rdx
|
||||
|
||||
/* Fix up CONTEXT.Rsp for the caller (+8 for the return address) */
|
||||
lea rdx, [rsp + CONTEXT_FRAME_LENGTH + 8 + 8]
|
||||
mov [rsp + CxRsp], rdx
|
||||
|
||||
/* Check if a user mode debugger is active */
|
||||
call RtlpCheckForActiveDebugger
|
||||
test al, al
|
||||
mov r8b, 1
|
||||
jnz RaiseException
|
||||
|
||||
/* Dispatch the exception */
|
||||
mov rcx, [rsp + CONTEXT_FRAME_LENGTH + 8 + P1Home]
|
||||
mov rdx, rsp
|
||||
call RtlDispatchException
|
||||
|
||||
/* Check if it was handled */
|
||||
test al, al
|
||||
mov r8b, 0
|
||||
jz RaiseException
|
||||
|
||||
/* It was handled, continue with the updated context */
|
||||
mov rcx, rsp
|
||||
mov dl, 0
|
||||
call ZwContinue
|
||||
jmp RaiseStatus
|
||||
|
||||
RaiseException:
|
||||
|
||||
mov rcx, [rsp + CxP1Home]
|
||||
mov rdx, rsp
|
||||
call ZwRaiseException
|
||||
|
||||
RaiseStatus:
|
||||
|
||||
mov rcx, rax
|
||||
mov rdx, rsp
|
||||
call RtlRaiseStatus
|
||||
|
||||
.ENDP
|
||||
|
||||
|
||||
END
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue