[RTL/x64] Handle STATUS_UNWIND_CONSOLIDATE in RtlRestoreContext

It's not entirely correct yet and will probably fail on recursive c++ exceptions, but it fixes basic c++ exception handling.
This commit is contained in:
Timo Kreuzer 2023-10-22 18:21:42 +03:00
parent ff282894a8
commit bb444b93d9
2 changed files with 29 additions and 9 deletions

View file

@ -107,22 +107,19 @@ PUBLIC RtlCaptureContext
.ENDP .ENDP
/* /*
* VOID NTAPI * VOID
* RtlRestoreContext( * RtlpRestoreContextInternal(
* _In_ PCONTEXT ContextRecord@<rcx>, * _In_ PCONTEXT ContextRecord@<rcx>);
* PEXCEPTION_RECORD *ExceptionRecord@<rdx>);
*/ */
PUBLIC RtlRestoreContext PUBLIC RtlpRestoreContextInternal
.PROC RtlRestoreContext .PROC RtlpRestoreContextInternal
/* Allocate space */ /* Allocate space */
sub rsp, HEX(8) sub rsp, HEX(8)
.ALLOCSTACK 8 .ALLOCSTACK 8
.ENDPROLOG .ENDPROLOG
// TODO: Handle ExceptionRecord /* Restore legacy floating point registers (It is slow, so do it first) */
/* Restore legacy floating point registers (It's slow, so do it first) */
ldmxcsr [rcx + CxMxCsr] ldmxcsr [rcx + CxMxCsr]
fxrstor [rcx + CxFltSave] fxrstor [rcx + CxFltSave]

View file

@ -1131,3 +1131,26 @@ RtlSetUnwindContext(
*ContextPointers.Xmm14 = Context->Xmm14; *ContextPointers.Xmm14 = Context->Xmm14;
*ContextPointers.Xmm15 = Context->Xmm15; *ContextPointers.Xmm15 = Context->Xmm15;
} }
VOID
RtlpRestoreContextInternal(
_In_ PCONTEXT ContextRecord);
VOID
RtlRestoreContext(
_In_ PCONTEXT ContextRecord,
_In_ PEXCEPTION_RECORD ExceptionRecord)
{
if (ExceptionRecord != NULL)
{
if ((ExceptionRecord->ExceptionCode == STATUS_UNWIND_CONSOLIDATE) &&
(ExceptionRecord->NumberParameters >= 1))
{
PVOID (*Consolidate)(EXCEPTION_RECORD*) = (PVOID)ExceptionRecord->ExceptionInformation[0];
// FIXME: This should be called through an asm wrapper to allow handling recursive unwinding
ContextRecord->Rip = (ULONG64)Consolidate(ExceptionRecord);
}
}
RtlpRestoreContextInternal(ContextRecord);
}