xref: /reactos/sdk/lib/rtl/amd64/except.c (revision 3ba1d82c)
15075f7d7STimo Kreuzer /*
25075f7d7STimo Kreuzer  * PROJECT:     ReactOS Run-Time Library
35075f7d7STimo Kreuzer  * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
45075f7d7STimo Kreuzer  * PURPOSE:     User-mode exception support for AMD64
55075f7d7STimo Kreuzer  * COPYRIGHT:   Copyright 2018-2021 Timo Kreuzer <timo.kreuzer@reactos.org>
65075f7d7STimo Kreuzer  */
75075f7d7STimo Kreuzer 
85075f7d7STimo Kreuzer /* INCLUDES *****************************************************************/
95075f7d7STimo Kreuzer 
105075f7d7STimo Kreuzer #include <rtl.h>
115075f7d7STimo Kreuzer #define NDEBUG
125075f7d7STimo Kreuzer #include <debug.h>
135075f7d7STimo Kreuzer 
145075f7d7STimo Kreuzer /* PUBLIC FUNCTIONS **********************************************************/
155075f7d7STimo Kreuzer 
165075f7d7STimo Kreuzer VOID
175075f7d7STimo Kreuzer NTAPI
185075f7d7STimo Kreuzer RtlRaiseException(IN PEXCEPTION_RECORD ExceptionRecord)
195075f7d7STimo Kreuzer {
205075f7d7STimo Kreuzer     CONTEXT Context;
215075f7d7STimo Kreuzer     NTSTATUS Status = STATUS_INVALID_DISPOSITION;
225075f7d7STimo Kreuzer 
23e6af7d9dSTimo Kreuzer     /* Capture the current context */
245075f7d7STimo Kreuzer     RtlCaptureContext(&Context);
255075f7d7STimo Kreuzer 
26e6af7d9dSTimo Kreuzer     /* Fix up Context.Rip for the caller */
27e6af7d9dSTimo Kreuzer     Context.Rip = (ULONG64)_ReturnAddress();
285075f7d7STimo Kreuzer 
29e6af7d9dSTimo Kreuzer     /* Fix up Context.Rsp for the caller */
30e6af7d9dSTimo Kreuzer     Context.Rsp = (ULONG64)_AddressOfReturnAddress() + 8;
315075f7d7STimo Kreuzer 
325075f7d7STimo Kreuzer     /* Save the exception address */
335075f7d7STimo Kreuzer     ExceptionRecord->ExceptionAddress = (PVOID)Context.Rip;
345075f7d7STimo Kreuzer 
355075f7d7STimo Kreuzer     /* Check if user mode debugger is active */
365075f7d7STimo Kreuzer     if (RtlpCheckForActiveDebugger())
375075f7d7STimo Kreuzer     {
385075f7d7STimo Kreuzer         /* Raise an exception immediately */
395075f7d7STimo Kreuzer         Status = ZwRaiseException(ExceptionRecord, &Context, TRUE);
405075f7d7STimo Kreuzer     }
415075f7d7STimo Kreuzer     else
425075f7d7STimo Kreuzer     {
435075f7d7STimo Kreuzer         /* Dispatch the exception and check if we should continue */
445075f7d7STimo Kreuzer         if (!RtlDispatchException(ExceptionRecord, &Context))
455075f7d7STimo Kreuzer         {
465075f7d7STimo Kreuzer             /* Raise the exception */
475075f7d7STimo Kreuzer             Status = ZwRaiseException(ExceptionRecord, &Context, FALSE);
485075f7d7STimo Kreuzer         }
495075f7d7STimo Kreuzer         else
505075f7d7STimo Kreuzer         {
515075f7d7STimo Kreuzer             /* Continue, go back to previous context */
525075f7d7STimo Kreuzer             Status = ZwContinue(&Context, FALSE);
535075f7d7STimo Kreuzer         }
545075f7d7STimo Kreuzer     }
555075f7d7STimo Kreuzer 
565075f7d7STimo Kreuzer     /* If we returned, raise a status */
575075f7d7STimo Kreuzer     RtlRaiseStatus(Status);
585075f7d7STimo Kreuzer }
595075f7d7STimo Kreuzer 
605075f7d7STimo Kreuzer /*
615075f7d7STimo Kreuzer * @unimplemented
625075f7d7STimo Kreuzer */
635075f7d7STimo Kreuzer PVOID
645075f7d7STimo Kreuzer NTAPI
655075f7d7STimo Kreuzer RtlpGetExceptionAddress(VOID)
665075f7d7STimo Kreuzer {
675075f7d7STimo Kreuzer     UNIMPLEMENTED;
685075f7d7STimo Kreuzer     return NULL;
695075f7d7STimo Kreuzer }
705075f7d7STimo Kreuzer 
713ec1ca9bSTimo Kreuzer BOOLEAN
723ec1ca9bSTimo Kreuzer NTAPI
73*3ba1d82cSKento Oki RtlpUnwindInternal(
743ec1ca9bSTimo Kreuzer     _In_opt_ PVOID TargetFrame,
753ec1ca9bSTimo Kreuzer     _In_opt_ PVOID TargetIp,
763ec1ca9bSTimo Kreuzer     _In_ PEXCEPTION_RECORD ExceptionRecord,
773ec1ca9bSTimo Kreuzer     _In_ PVOID ReturnValue,
783ec1ca9bSTimo Kreuzer     _In_ PCONTEXT ContextRecord,
793ec1ca9bSTimo Kreuzer     _In_opt_ struct _UNWIND_HISTORY_TABLE *HistoryTable,
803ec1ca9bSTimo Kreuzer     _In_ ULONG Flags);
813ec1ca9bSTimo Kreuzer 
825075f7d7STimo Kreuzer /*
835075f7d7STimo Kreuzer  * @unimplemented
845075f7d7STimo Kreuzer  */
855075f7d7STimo Kreuzer BOOLEAN
865075f7d7STimo Kreuzer NTAPI
873ec1ca9bSTimo Kreuzer RtlDispatchException(
883ec1ca9bSTimo Kreuzer     _In_ PEXCEPTION_RECORD ExceptionRecord,
893ec1ca9bSTimo Kreuzer     _In_ PCONTEXT ContextRecord)
905075f7d7STimo Kreuzer {
913ec1ca9bSTimo Kreuzer     BOOLEAN Handled;
923ec1ca9bSTimo Kreuzer 
933ec1ca9bSTimo Kreuzer     /* Perform vectored exception handling for user mode */
943ec1ca9bSTimo Kreuzer     if (RtlCallVectoredExceptionHandlers(ExceptionRecord, ContextRecord))
953ec1ca9bSTimo Kreuzer     {
963ec1ca9bSTimo Kreuzer         /* Exception handled, now call vectored continue handlers */
973ec1ca9bSTimo Kreuzer         RtlCallVectoredContinueHandlers(ExceptionRecord, ContextRecord);
983ec1ca9bSTimo Kreuzer 
993ec1ca9bSTimo Kreuzer         /* Continue execution */
1003ec1ca9bSTimo Kreuzer         return TRUE;
1013ec1ca9bSTimo Kreuzer     }
1023ec1ca9bSTimo Kreuzer 
1033ec1ca9bSTimo Kreuzer     /* Call the internal unwind routine */
104*3ba1d82cSKento Oki     Handled = RtlpUnwindInternal(NULL, // TargetFrame
1053ec1ca9bSTimo Kreuzer                                  NULL, // TargetIp
1063ec1ca9bSTimo Kreuzer                                  ExceptionRecord,
1073ec1ca9bSTimo Kreuzer                                  0, // ReturnValue
1083ec1ca9bSTimo Kreuzer                                  ContextRecord,
1093ec1ca9bSTimo Kreuzer                                  NULL, // HistoryTable
1103ec1ca9bSTimo Kreuzer                                  UNW_FLAG_EHANDLER);
1113ec1ca9bSTimo Kreuzer 
1123ec1ca9bSTimo Kreuzer     /* In user mode, call any registered vectored continue handlers */
1133ec1ca9bSTimo Kreuzer     RtlCallVectoredContinueHandlers(ExceptionRecord, ContextRecord);
1143ec1ca9bSTimo Kreuzer 
1153ec1ca9bSTimo Kreuzer     return Handled;
1165075f7d7STimo Kreuzer }
117