mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 13:45:50 +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 **********************************************************/
|
/* 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
|
* @unimplemented
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -233,6 +233,81 @@ ReturnFar:
|
||||||
|
|
||||||
.ENDP
|
.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
|
END
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue