ReactOS 0.4.17-dev-243-g1369312
except.c File Reference
#include <rtl.h>
#include <debug.h>
Include dependency graph for except.c:

Go to the source code of this file.

Macros

#define NDEBUG
 

Functions

PVOID NTAPI RtlpGetExceptionAddress (VOID)
 
BOOLEAN NTAPI RtlpUnwindInternal (_In_opt_ PVOID TargetFrame, _In_opt_ PVOID TargetIp, _In_ PEXCEPTION_RECORD ExceptionRecord, _In_ PVOID ReturnValue, _In_ PCONTEXT ContextRecord, _In_opt_ struct _UNWIND_HISTORY_TABLE *HistoryTable, _In_ ULONG Flags)
 
BOOLEAN NTAPI RtlDispatchException (_In_ PEXCEPTION_RECORD ExceptionRecord, _In_ PCONTEXT ContextRecord)
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 11 of file except.c.

Function Documentation

◆ RtlDispatchException()

BOOLEAN NTAPI RtlDispatchException ( _In_ PEXCEPTION_RECORD  ExceptionRecord,
_In_ PCONTEXT  ContextRecord 
)

Definition at line 43 of file except.c.

46{
48
49 /* Perform vectored exception handling for user mode */
51 {
52 /* Exception handled, now call vectored continue handlers */
54
55 /* Continue execution */
56 return TRUE;
57 }
58
59 /* Call the internal unwind routine */
60 Handled = RtlpUnwindInternal(NULL, // TargetFrame
61 NULL, // TargetIp
62 ExceptionRecord,
63 0, // ReturnValue
65 NULL, // HistoryTable
66 UNW_FLAG_EHANDLER);
67
68 /* In user mode, call any registered vectored continue handlers */
70
71 return Handled;
72}
unsigned char BOOLEAN
Definition: actypes.h:127
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
_IRQL_requires_same_ _In_ PVOID _Inout_ struct _CONTEXT * ContextRecord
Definition: ntbasedef.h:666
VOID NTAPI RtlCallVectoredContinueHandlers(_In_ PEXCEPTION_RECORD ExceptionRecord, _In_ PCONTEXT Context)
Definition: libsupp.c:822
BOOLEAN NTAPI RtlCallVectoredExceptionHandlers(_In_ PEXCEPTION_RECORD ExceptionRecord, _In_ PCONTEXT Context)
Definition: libsupp.c:813
BOOLEAN NTAPI RtlpUnwindInternal(_In_opt_ PVOID TargetFrame, _In_opt_ PVOID TargetIp, _In_ PEXCEPTION_RECORD ExceptionRecord, _In_ PVOID ReturnValue, _In_ PCONTEXT ContextRecord, _In_opt_ struct _UNWIND_HISTORY_TABLE *HistoryTable, _In_ ULONG Flags)
Definition: unwind.c:721
_In_ BOOLEAN Handled
Definition: ketypes.h:401

◆ RtlpGetExceptionAddress()

PVOID NTAPI RtlpGetExceptionAddress ( VOID  )

Definition at line 21 of file except.c.

22{
24 return NULL;
25}
#define UNIMPLEMENTED
Definition: ntoskrnl.c:15

◆ RtlpUnwindInternal()

BOOLEAN NTAPI RtlpUnwindInternal ( _In_opt_ PVOID  TargetFrame,
_In_opt_ PVOID  TargetIp,
_In_ PEXCEPTION_RECORD  ExceptionRecord,
_In_ PVOID  ReturnValue,
_In_ PCONTEXT  ContextRecord,
_In_opt_ struct _UNWIND_HISTORY_TABLE HistoryTable,
_In_ ULONG  HandlerType 
)
Remarks
The implementation is based on the description in this blog: http://www.nynaeve.net/?p=106
Differences to the desciption:
- Instead of using 2 pointers to the unwind context and previous context,
  that are being swapped and the context copied, the unwind context is
  kept in the local context and copied back into the context passed in
  by the caller.
See also
http://www.nynaeve.net/?p=106

TODO: Handle DPC stack

TODO

TODO: Check for DPC stack

Definition at line 721 of file unwind.c.

729{
731 PEXCEPTION_ROUTINE ExceptionRoutine;
733 PRUNTIME_FUNCTION FunctionEntry;
734 ULONG_PTR StackLow, StackHigh;
735 ULONG64 ImageBase, EstablisherFrame;
736 CONTEXT UnwindContext;
737
738 /* Get the current stack limits */
739 RtlpGetStackLimits(&StackLow, &StackHigh);
740
741 /* If we have a target frame, then this is our high limit */
742 if (TargetFrame != NULL)
743 {
744 StackHigh = (ULONG64)TargetFrame + 1;
745 }
746
747 /* Copy the context */
748 UnwindContext = *ContextRecord;
749
750 /* Set up the constant fields of the dispatcher context */
751 DispatcherContext.ContextRecord =
752 (HandlerType == UNW_FLAG_UHANDLER) ? ContextRecord : &UnwindContext;
753 DispatcherContext.HistoryTable = HistoryTable;
754 DispatcherContext.TargetIp = (ULONG64)TargetIp;
755
756 /* Start looping */
757 while (TRUE)
758 {
759 if (!RtlpIsStackPointerValid(UnwindContext.Rsp, StackLow, StackHigh))
760 {
761 return FALSE;
762 }
763
764 /* Lookup the FunctionEntry for the current RIP */
765 FunctionEntry = RtlLookupFunctionEntry(UnwindContext.Rip, &ImageBase, NULL);
766 if (FunctionEntry == NULL)
767 {
768 /* No function entry, so this must be a leaf function. Pop the return address from the stack.
769 Note: this can happen after the first frame as the result of an exception */
770 UnwindContext.Rip = *(DWORD64*)UnwindContext.Rsp;
771 UnwindContext.Rsp += sizeof(DWORD64);
772
773 if (HandlerType == UNW_FLAG_UHANDLER)
774 {
775 /* Copy the context back for the next iteration */
776 *ContextRecord = UnwindContext;
777 }
778 continue;
779 }
780
781 /* Save Rip before the virtual unwind */
782 DispatcherContext.ControlPc = UnwindContext.Rip;
783
784 /* Do a virtual unwind to get the next frame */
785 ExceptionRoutine = RtlVirtualUnwind(HandlerType,
786 ImageBase,
787 UnwindContext.Rip,
788 FunctionEntry,
789 &UnwindContext,
790 &DispatcherContext.HandlerData,
792 NULL);
793
794 /* Check, if we are still within the stack boundaries */
795 if ((EstablisherFrame < StackLow) ||
796 (EstablisherFrame >= StackHigh) ||
797 (EstablisherFrame & 7))
798 {
800
801 /* If we are handling an exception, we are done here. */
802 if (HandlerType == UNW_FLAG_EHANDLER)
803 {
804 ExceptionRecord->ExceptionFlags |= EXCEPTION_STACK_INVALID;
805 return FALSE;
806 }
807
808 __debugbreak();
810 }
811
812 /* Check if we have an exception routine */
813 if (ExceptionRoutine != NULL)
814 {
815 /* Check if this is the target frame */
816 if (EstablisherFrame == (ULONG64)TargetFrame)
817 {
818 /* Set flag to inform the language handler */
819 ExceptionRecord->ExceptionFlags |= EXCEPTION_TARGET_UNWIND;
820 }
821
822 /* Log the exception if it's enabled */
823 RtlpCheckLogException(ExceptionRecord,
824 &UnwindContext,
826 sizeof(DispatcherContext));
827
828 /* Set up the variable fields of the dispatcher context */
829 DispatcherContext.ImageBase = ImageBase;
830 DispatcherContext.FunctionEntry = FunctionEntry;
831 DispatcherContext.LanguageHandler = ExceptionRoutine;
832 DispatcherContext.EstablisherFrame = EstablisherFrame;
833 DispatcherContext.ScopeIndex = 0;
834
835 /* Store the return value in the unwind context */
836 UnwindContext.Rax = (ULONG64)ReturnValue;
837
838 /* Loop all nested handlers */
839 do
840 {
841 /* Call the language specific handler */
846
847 /* Clear exception flags for the next iteration */
848 ExceptionRecord->ExceptionFlags &= ~(EXCEPTION_TARGET_UNWIND |
850
851 /* Check if we do exception handling */
852 if (HandlerType == UNW_FLAG_EHANDLER)
853 {
855 {
856 /* Check if it was non-continuable */
857 if (ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE)
858 {
859 __debugbreak();
861 }
862
863 /* Execution continues */
864 return TRUE;
865 }
867 {
869 __debugbreak();
870 }
871 }
872
874 {
875 /* We collided with another unwind, so we need to continue
876 "after" the handler, skipping the termination handler
877 that resulted in this unwind. The installed handler has
878 already copied the original dispatcher context, we now
879 need to copy back the original context. */
880 UnwindContext = *ContextRecord = *DispatcherContext.ContextRecord;
881
882 /* The original context was from "before" the unwind, so we
883 need to do an additional virtual unwind to restore the
884 unwind contxt. */
886 DispatcherContext.ImageBase,
887 UnwindContext.Rip,
888 DispatcherContext.FunctionEntry,
889 &UnwindContext,
890 &DispatcherContext.HandlerData,
892 NULL);
893
894 /* Restore the context pointer and establisher frame. */
895 DispatcherContext.ContextRecord = &UnwindContext;
896 EstablisherFrame = DispatcherContext.EstablisherFrame;
897
898 /* Set the exception flags to indicate that we collided
899 with an unwind and continue the handler loop, which
900 will run any additional handlers from the previous
901 unwind. */
902 ExceptionRecord->ExceptionFlags |= EXCEPTION_COLLIDED_UNWIND;
903 continue;
904 }
905
906 /* This must be ExceptionContinueSearch now */
908 {
909 __debugbreak();
911 }
912 } while (ExceptionRecord->ExceptionFlags & EXCEPTION_COLLIDED_UNWIND);
913 }
914
915 /* Check, if we have left our stack (8.) */
916 if ((EstablisherFrame < StackLow) ||
917 (EstablisherFrame > StackHigh) ||
918 (EstablisherFrame & 7))
919 {
921 __debugbreak();
922
923 if (UnwindContext.Rip == ContextRecord->Rip)
924 {
926 }
927 else
928 {
929 ZwRaiseException(ExceptionRecord, ContextRecord, FALSE);
930 }
931 }
932
933 if (EstablisherFrame == (ULONG64)TargetFrame)
934 {
935 break;
936 }
937
938 if (HandlerType == UNW_FLAG_UHANDLER)
939 {
940 /* We have successfully unwound a frame. Copy the unwind context back. */
941 *ContextRecord = UnwindContext;
942 }
943 }
944
945 if (ExceptionRecord->ExceptionCode != STATUS_UNWIND_CONSOLIDATE)
946 {
947 ContextRecord->Rip = (ULONG64)TargetIp;
948 }
949
950 /* Set the return value */
952
953 /* Restore the context */
954 RtlRestoreContext(ContextRecord, ExceptionRecord);
955
956 /* Should never get here! */
957 ASSERT(FALSE);
958 return FALSE;
959}
UINT32 void void ** ReturnValue
Definition: acevents.h:216
ACPI_PHYSICAL_ADDRESS ACPI_SIZE BOOLEAN Warn UINT32 *TableIdx UINT32 ACPI_TABLE_HEADER *OutTableHeader ACPI_TABLE_HEADER **OutTable ACPI_HANDLE UINT32 ACPI_WALK_CALLBACK ACPI_WALK_CALLBACK void void **ReturnValue UINT32 ACPI_BUFFER *RetPathPtr ACPI_OBJECT_HANDLER void *Data ACPI_OBJECT_HANDLER void **Data ACPI_STRING ACPI_OBJECT_LIST ACPI_BUFFER *ReturnObjectBuffer ACPI_DEVICE_INFO **ReturnBuffer ACPI_HANDLE ACPI_HANDLE ACPI_HANDLE *OutHandle ACPI_HANDLE *OutHandle void *Context void *Context ACPI_EVENT_HANDLER Handler UINT32 UINT32 ACPI_GPE_HANDLER void *Context UINT32 HandlerType
Definition: acpixf.h:817
#define FALSE
Definition: types.h:117
VOID NTAPI RtlpCheckLogException(IN PEXCEPTION_RECORD ExceptionRecord, IN PCONTEXT ContextRecord, IN PVOID ContextData, IN ULONG Size)
Definition: libsupp.c:203
VOID NTAPI RtlpGetStackLimits(OUT PULONG_PTR LowLimit, OUT PULONG_PTR HighLimit)
Definition: libsupp.c:337
@ ExceptionContinueSearch
Definition: compat.h:91
@ ExceptionCollidedUnwind
Definition: compat.h:93
@ ExceptionNestedException
Definition: compat.h:92
@ ExceptionContinueExecution
Definition: compat.h:90
EXCEPTION_ROUTINE * PEXCEPTION_ROUTINE
Definition: compat.h:709
enum _EXCEPTION_DISPOSITION EXCEPTION_DISPOSITION
#define EXCEPTION_NONCONTINUABLE_EXCEPTION
Definition: minwinbase.h:61
#define ASSERT(a)
Definition: mode.c:44
unsigned __int64 ULONG64
Definition: imports.h:198
static PRUNTIME_FUNCTION(WINAPI *pRtlLookupFunctionEntry)(ULONG_PTR
_In_ ACCESS_MASK _In_ POBJECT_ATTRIBUTES _Reserved_ ULONG _In_opt_ PUNICODE_STRING _In_ ULONG _Out_opt_ PULONG Disposition
Definition: cmfuncs.h:56
NTSYSAPI NTSTATUS NTAPI ZwRaiseException(_In_ PEXCEPTION_RECORD ExceptionRecord, _In_ PCONTEXT Context, _In_ BOOLEAN SearchFrames)
DECLSPEC_NORETURN NTSYSAPI VOID NTAPI RtlRaiseStatus(_In_ NTSTATUS Status)
_IRQL_requires_same_ _In_ PVOID EstablisherFrame
Definition: ntbasedef.h:665
_IRQL_requires_same_ _In_ PVOID _Inout_ struct _CONTEXT _In_ PVOID DispatcherContext
Definition: ntbasedef.h:667
#define STATUS_INVALID_DISPOSITION
Definition: ntstatus.h:368
#define STATUS_UNWIND_CONSOLIDATE
Definition: ntstatus.h:300
#define STATUS_BAD_FUNCTION_TABLE
Definition: ntstatus.h:585
#define STATUS_BAD_STACK
Definition: ntstatus.h:370
EXCEPTION_DISPOSITION NTAPI RtlpExecuteHandlerForUnwind(_Inout_ struct _EXCEPTION_RECORD *ExceptionRecord, _In_ PVOID EstablisherFrame, _Inout_ struct _CONTEXT *ContextRecord, _In_ PVOID DispatcherContext)
NTSYSAPI PRUNTIME_FUNCTION WINAPI RtlLookupFunctionEntry(ULONG_PTR, ULONG_PTR *, UNWIND_HISTORY_TABLE *)
void __cdecl __debugbreak(void)
Definition: intrin_ppc.h:698
PEXCEPTION_ROUTINE NTAPI RtlVirtualUnwind(_In_ ULONG HandlerType, _In_ ULONG64 ImageBase, _In_ ULONG64 ControlPc, _In_ PRUNTIME_FUNCTION FunctionEntry, _Inout_ PCONTEXT Context, _Outptr_ PVOID *HandlerData, _Out_ PULONG64 EstablisherFrame, _Inout_opt_ PKNONVOLATILE_CONTEXT_POINTERS ContextPointers)
Definition: unwind.c:478
VOID RtlRestoreContext(_In_ PCONTEXT ContextRecord, _In_ PEXCEPTION_RECORD ExceptionRecord)
Definition: unwind.c:1288
static __inline BOOL RtlpIsStackPointerValid(_In_ ULONG64 StackPointer, _In_ ULONG64 LowLimit, _In_ ULONG64 HighLimit)
Definition: unwind.c:658
#define EXCEPTION_NONCONTINUABLE
Definition: stubs.h:23
uint64_t DWORD64
Definition: typedefs.h:67
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define EXCEPTION_STACK_INVALID
Definition: rtltypes.h:157
#define EXCEPTION_TARGET_UNWIND
Definition: rtltypes.h:159
#define EXCEPTION_COLLIDED_UNWIND
Definition: rtltypes.h:160

Referenced by RtlDispatchException(), and RtlUnwindEx().