ReactOS 0.4.15-dev-7113-g9ea2222
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

VOID NTAPI RtlRaiseException (IN PEXCEPTION_RECORD ExceptionRecord)
 
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 87 of file except.c.

90{
92
93 /* Perform vectored exception handling for user mode */
95 {
96 /* Exception handled, now call vectored continue handlers */
98
99 /* Continue execution */
100 return TRUE;
101 }
102
103 /* Call the internal unwind routine */
104 Handled = RtlpUnwindInternal(NULL, // TargetFrame
105 NULL, // TargetIp
106 ExceptionRecord,
107 0, // ReturnValue
109 NULL, // HistoryTable
111
112 /* In user mode, call any registered vectored continue handlers */
114
115 return Handled;
116}
unsigned char BOOLEAN
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
_IRQL_requires_same_ _In_ PVOID _Inout_ struct _CONTEXT * ContextRecord
Definition: ntbasedef.h:654
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
@ UNW_FLAG_EHANDLER
Definition: rsym64.h:108
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:666
_In_ BOOLEAN Handled
Definition: ketypes.h:349

◆ RtlpGetExceptionAddress()

PVOID NTAPI RtlpGetExceptionAddress ( VOID  )

Definition at line 65 of file except.c.

66{
68 return NULL;
69}
#define UNIMPLEMENTED
Definition: debug.h:115

◆ 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: call RtlpExecuteHandlerForUnwind instead

TODO

TODO

TODO: Check for DPC stack

Definition at line 666 of file unwind.c.

674{
676 PEXCEPTION_ROUTINE ExceptionRoutine;
678 PRUNTIME_FUNCTION FunctionEntry;
679 ULONG_PTR StackLow, StackHigh;
680 ULONG64 ImageBase, EstablisherFrame;
681 CONTEXT UnwindContext;
682
683 /* Get the current stack limits and registration frame */
684 RtlpGetStackLimits(&StackLow, &StackHigh);
685
686 /* If we have a target frame, then this is our high limit */
687 if (TargetFrame != NULL)
688 {
689 StackHigh = (ULONG64)TargetFrame + 1;
690 }
691
692 /* Copy the context */
693 UnwindContext = *ContextRecord;
694
695 /* Set up the constant fields of the dispatcher context */
696 DispatcherContext.ContextRecord = &UnwindContext;
697 DispatcherContext.HistoryTable = HistoryTable;
698 DispatcherContext.TargetIp = (ULONG64)TargetIp;
699
700 /* Start looping */
701 while (TRUE)
702 {
703 /* Lookup the FunctionEntry for the current RIP */
704 FunctionEntry = RtlLookupFunctionEntry(UnwindContext.Rip, &ImageBase, NULL);
705 if (FunctionEntry == NULL)
706 {
707 /* No function entry, so this must be a leaf function. Pop the return address from the stack.
708 Note: this can happen after the first frame as the result of an exception */
709 UnwindContext.Rip = *(DWORD64*)UnwindContext.Rsp;
710 UnwindContext.Rsp += sizeof(DWORD64);
711
712 /* Copy the context back for the next iteration */
713 *ContextRecord = UnwindContext;
714 continue;
715 }
716
717 /* Save Rip before the virtual unwind */
718 DispatcherContext.ControlPc = UnwindContext.Rip;
719
720 /* Do a virtual unwind to get the next frame */
721 ExceptionRoutine = RtlVirtualUnwind(HandlerType,
722 ImageBase,
723 UnwindContext.Rip,
724 FunctionEntry,
725 &UnwindContext,
726 &DispatcherContext.HandlerData,
728 NULL);
729
730 /* Check, if we are still within the stack boundaries */
731 if ((EstablisherFrame < StackLow) ||
732 (EstablisherFrame >= StackHigh) ||
733 (EstablisherFrame & 7))
734 {
736
737 /* If we are handling an exception, we are done here. */
739 {
740 ExceptionRecord->ExceptionFlags |= EXCEPTION_STACK_INVALID;
741 return FALSE;
742 }
743
744 __debugbreak();
746 }
747
748 /* Check if we have an exception routine */
749 if (ExceptionRoutine != NULL)
750 {
751 /* Check if this is the target frame */
752 if (EstablisherFrame == (ULONG64)TargetFrame)
753 {
754 /* Set flag to inform the language handler */
755 ExceptionRecord->ExceptionFlags |= EXCEPTION_TARGET_UNWIND;
756 }
757
758 /* Log the exception if it's enabled */
759 RtlpCheckLogException(ExceptionRecord,
762 sizeof(DispatcherContext));
763
764 /* Set up the variable fields of the dispatcher context */
765 DispatcherContext.ImageBase = ImageBase;
766 DispatcherContext.FunctionEntry = FunctionEntry;
767 DispatcherContext.LanguageHandler = ExceptionRoutine;
768 DispatcherContext.EstablisherFrame = EstablisherFrame;
769 DispatcherContext.ScopeIndex = 0;
770
771 /* Store the return value in the unwind context */
772 UnwindContext.Rax = (ULONG64)ReturnValue;
773
774 /* Loop all nested handlers */
775 do
776 {
778 /* Call the language specific handler */
779 Disposition = ExceptionRoutine(ExceptionRecord,
783
784 /* Clear exception flags for the next iteration */
785 ExceptionRecord->ExceptionFlags &= ~(EXCEPTION_TARGET_UNWIND |
787
788 /* Check if we do exception handling */
790 {
792 {
793 /* Check if it was non-continuable */
794 if (ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE)
795 {
796 __debugbreak();
798 }
799
800 /* Execution continues */
801 return TRUE;
802 }
804 {
806 __debugbreak();
807 }
808 }
809
811 {
813 __debugbreak();
814 }
815
816 /* This must be ExceptionContinueSearch now */
818 {
819 __debugbreak();
821 }
822 } while (ExceptionRecord->ExceptionFlags & EXCEPTION_COLLIDED_UNWIND);
823 }
824
825 /* Check, if we have left our stack (8.) */
826 if ((EstablisherFrame < StackLow) ||
827 (EstablisherFrame > StackHigh) ||
828 (EstablisherFrame & 7))
829 {
831 __debugbreak();
832
833 if (UnwindContext.Rip == ContextRecord->Rip)
834 {
836 }
837 else
838 {
839 ZwRaiseException(ExceptionRecord, ContextRecord, FALSE);
840 }
841 }
842
843 if (EstablisherFrame == (ULONG64)TargetFrame)
844 {
845 break;
846 }
847
848 /* We have successfully unwound a frame. Copy the unwind context back. */
849 *ContextRecord = UnwindContext;
850 }
851
852 if (ExceptionRecord->ExceptionCode != STATUS_UNWIND_CONSOLIDATE)
853 {
854 ContextRecord->Rip = (ULONG64)TargetIp;
855 }
856
857 /* Set the return value */
859
860 /* Restore the context */
861 RtlRestoreContext(ContextRecord, ExceptionRecord);
862
863 /* Should never get here! */
864 ASSERT(FALSE);
865 return FALSE;
866}
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:201
VOID NTAPI RtlpGetStackLimits(OUT PULONG_PTR LowLimit, OUT PULONG_PTR HighLimit)
Definition: libsupp.c:335
@ 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
void __cdecl __debugbreak(void)
Definition: intrin_ppc.h:698
#define ASSERT(a)
Definition: mode.c:44
unsigned __int64 ULONG64
Definition: imports.h:198
_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:653
_IRQL_requires_same_ _In_ PVOID _Inout_ struct _CONTEXT _In_ PVOID DispatcherContext
Definition: ntbasedef.h:655
#define STATUS_INVALID_DISPOSITION
Definition: ntstatus.h:275
#define STATUS_UNWIND_CONSOLIDATE
Definition: ntstatus.h:220
#define STATUS_BAD_FUNCTION_TABLE
Definition: ntstatus.h:491
#define STATUS_BAD_STACK
Definition: ntstatus.h:277
#define EXCEPTION_NONCONTINUABLE
Definition: stubs.h:23
uint64_t DWORD64
Definition: typedefs.h:67
uint32_t ULONG_PTR
Definition: typedefs.h:65
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:479
PRUNTIME_FUNCTION NTAPI RtlLookupFunctionEntry(IN DWORD64 ControlPc, OUT PDWORD64 ImageBase, OUT PUNWIND_HISTORY_TABLE HistoryTable)
Locates the RUNTIME_FUNCTION entry corresponding to a code address. http://msdn.microsoft....
Definition: unwind.c:124
#define EXCEPTION_NONCONTINUABLE_EXCEPTION
Definition: winbase.h:328
#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().

◆ RtlRaiseException()

VOID NTAPI RtlRaiseException ( IN PEXCEPTION_RECORD  ExceptionRecord)

Definition at line 18 of file except.c.

19{
22
23 /* Capture the current context */
25
26 /* Fix up Context.Rip for the caller */
28
29 /* Fix up Context.Rsp for the caller */
31
32 /* Save the exception address */
33 ExceptionRecord->ExceptionAddress = (PVOID)Context.Rip;
34
35 /* Check if user mode debugger is active */
37 {
38 /* Raise an exception immediately */
39 Status = ZwRaiseException(ExceptionRecord, &Context, TRUE);
40 }
41 else
42 {
43 /* Dispatch the exception and check if we should continue */
44 if (!RtlDispatchException(ExceptionRecord, &Context))
45 {
46 /* Raise the exception */
47 Status = ZwRaiseException(ExceptionRecord, &Context, FALSE);
48 }
49 else
50 {
51 /* Continue, go back to previous context */
53 }
54 }
55
56 /* If we returned, raise a status */
58}
LONG NTSTATUS
Definition: precomp.h:26
BOOLEAN NTAPI RtlpCheckForActiveDebugger(VOID)
Definition: libsupp.c:25
Status
Definition: gdiplustypes.h:25
#define _ReturnAddress()
Definition: intrin_arm.h:35
#define _AddressOfReturnAddress()
Definition: intrin_ppc.h:40
if(dx< 0)
Definition: linetemp.h:194
NTSYSAPI NTSTATUS NTAPI ZwContinue(_In_ PCONTEXT Context, _In_ BOOLEAN TestAlert)
NTSYSAPI BOOLEAN NTAPI RtlDispatchException(_In_ PEXCEPTION_RECORD ExceptionRecord, _In_ PCONTEXT Context)
Definition: except.c:87
NTSYSAPI VOID NTAPI RtlCaptureContext(_Out_ PCONTEXT ContextRecord)
void * PVOID
Definition: typedefs.h:50