ReactOS  0.4.15-dev-3303-g1ade494
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 */
94  if (RtlCallVectoredExceptionHandlers(ExceptionRecord, ContextRecord))
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 }
#define TRUE
Definition: types.h:120
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:686
unsigned char BOOLEAN
_In_ BOOLEAN Handled
Definition: ketypes.h:337
BOOLEAN NTAPI RtlCallVectoredExceptionHandlers(_In_ PEXCEPTION_RECORD ExceptionRecord, _In_ PCONTEXT Context)
Definition: libsupp.c:817
_IRQL_requires_same_ _In_ PVOID _Inout_ struct _CONTEXT * ContextRecord
Definition: ntbasedef.h:654
#define NULL
Definition: types.h:112
VOID NTAPI RtlCallVectoredContinueHandlers(_In_ PEXCEPTION_RECORD ExceptionRecord, _In_ PCONTEXT Context)
Definition: libsupp.c:826

Referenced by KiDispatchException(), and RtlRaiseException().

◆ RtlpGetExceptionAddress()

PVOID NTAPI RtlpGetExceptionAddress ( VOID  )

Definition at line 65 of file except.c.

66 {
68  return NULL;
69 }
#define NULL
Definition: types.h:112
#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 686 of file unwind.c.

694 {
696  PEXCEPTION_ROUTINE ExceptionRoutine;
698  PRUNTIME_FUNCTION FunctionEntry;
699  ULONG_PTR StackLow, StackHigh;
700  ULONG64 ImageBase, EstablisherFrame;
701  CONTEXT UnwindContext;
702 
703  /* Get the current stack limits and registration frame */
704  RtlpGetStackLimits(&StackLow, &StackHigh);
705 
706  /* If we have a target frame, then this is our high limit */
707  if (TargetFrame != NULL)
708  {
709  StackHigh = (ULONG64)TargetFrame + 1;
710  }
711 
712  /* Copy the context */
713  UnwindContext = *ContextRecord;
714 
715  /* Set up the constant fields of the dispatcher context */
716  DispatcherContext.ContextRecord = ContextRecord;
717  DispatcherContext.HistoryTable = HistoryTable;
718  DispatcherContext.TargetIp = (ULONG64)TargetIp;
719 
720  /* Start looping */
721  while (TRUE)
722  {
723  /* Lookup the FunctionEntry for the current RIP */
724  FunctionEntry = RtlLookupFunctionEntry(UnwindContext.Rip, &ImageBase, NULL);
725  if (FunctionEntry == NULL)
726  {
727  /* No function entry, so this must be a leaf function. Pop the return address from the stack.
728  Note: this can happen after the first frame as the result of an exception */
729  UnwindContext.Rip = *(DWORD64*)UnwindContext.Rsp;
730  UnwindContext.Rsp += sizeof(DWORD64);
731  continue;
732  }
733 
734  /* Do a virtual unwind to get the next frame */
735  ExceptionRoutine = RtlVirtualUnwind(HandlerType,
736  ImageBase,
737  UnwindContext.Rip,
738  FunctionEntry,
739  &UnwindContext,
740  &DispatcherContext.HandlerData,
742  NULL);
743 
744  /* Check, if we are still within the stack boundaries */
745  if ((EstablisherFrame < StackLow) ||
746  (EstablisherFrame >= StackHigh) ||
747  (EstablisherFrame & 7))
748  {
750 
751  /* If we are handling an exception, we are done here. */
753  {
754  ExceptionRecord->ExceptionFlags |= EXCEPTION_STACK_INVALID;
755  return FALSE;
756  }
757 
758  __debugbreak();
760  }
761 
762  /* Check if we have an exception routine */
763  if (ExceptionRoutine != NULL)
764  {
765  /* Check if this is the target frame */
766  if (EstablisherFrame == (ULONG64)TargetFrame)
767  {
768  /* Set flag to inform the language handler */
769  ExceptionRecord->ExceptionFlags |= EXCEPTION_TARGET_UNWIND;
770  }
771 
772  /* Log the exception if it's enabled */
773  RtlpCheckLogException(ExceptionRecord,
776  sizeof(DispatcherContext));
777 
778  /* Set up the variable fields of the dispatcher context */
779  DispatcherContext.ControlPc = ContextRecord->Rip;
780  DispatcherContext.ImageBase = ImageBase;
781  DispatcherContext.FunctionEntry = FunctionEntry;
782  DispatcherContext.LanguageHandler = ExceptionRoutine;
783  DispatcherContext.EstablisherFrame = EstablisherFrame;
784  DispatcherContext.ScopeIndex = 0;
785 
786  /* Store the return value in the unwind context */
787  UnwindContext.Rax = (ULONG64)ReturnValue;
788 
789  /* Loop all nested handlers */
790  do
791  {
793  /* Call the language specific handler */
794  Disposition = ExceptionRoutine(ExceptionRecord,
796  &UnwindContext,
798 
799  /* Clear exception flags for the next iteration */
800  ExceptionRecord->ExceptionFlags &= ~(EXCEPTION_TARGET_UNWIND |
802 
803  /* Check if we do exception handling */
805  {
807  {
808  /* Check if it was non-continuable */
809  if (ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE)
810  {
811  __debugbreak();
813  }
814 
815  /* Execution continues */
816  return TRUE;
817  }
819  {
821  __debugbreak();
822  }
823  }
824 
826  {
828  __debugbreak();
829  }
830 
831  /* This must be ExceptionContinueSearch now */
833  {
834  __debugbreak();
836  }
837  } while (ExceptionRecord->ExceptionFlags & EXCEPTION_COLLIDED_UNWIND);
838  }
839 
840  /* Check, if we have left our stack (8.) */
841  if ((EstablisherFrame < StackLow) ||
842  (EstablisherFrame > StackHigh) ||
843  (EstablisherFrame & 7))
844  {
846  __debugbreak();
847 
848  if (UnwindContext.Rip == ContextRecord->Rip)
849  {
851  }
852  else
853  {
854  ZwRaiseException(ExceptionRecord, ContextRecord, FALSE);
855  }
856  }
857 
858  if (EstablisherFrame == (ULONG64)TargetFrame)
859  {
860  break;
861  }
862 
863  /* We have successfully unwound a frame. Copy the unwind context back. */
864  *ContextRecord = UnwindContext;
865  }
866 
867  if (ExceptionRecord->ExceptionCode != STATUS_UNWIND_CONSOLIDATE)
868  {
869  ContextRecord->Rip = (ULONG64)TargetIp;
870  }
871 
872  /* Set the return value */
874 
875  /* Restore the context */
876  RtlRestoreContext(ContextRecord, ExceptionRecord);
877 
878  /* Should never get here! */
879  ASSERT(FALSE);
880  return FALSE;
881 }
#define STATUS_UNWIND_CONSOLIDATE
Definition: ntstatus.h:220
#define EXCEPTION_NONCONTINUABLE_EXCEPTION
Definition: winbase.h:325
DECLSPEC_NORETURN NTSYSAPI VOID NTAPI RtlRaiseStatus(_In_ NTSTATUS Status)
_IRQL_requires_same_ _In_ PVOID EstablisherFrame
Definition: ntbasedef.h:653
#define TRUE
Definition: types.h:120
#define STATUS_BAD_STACK
Definition: ntstatus.h:277
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:496
NTSYSAPI NTSTATUS NTAPI ZwRaiseException(_In_ PEXCEPTION_RECORD ExceptionRecord, _In_ PCONTEXT Context, _In_ BOOLEAN SearchFrames)
#define EXCEPTION_NONCONTINUABLE
Definition: rtltypes.h:154
void __cdecl __debugbreak(void)
Definition: intrin_ppc.h:698
_In_ ACCESS_MASK _In_ POBJECT_ATTRIBUTES _Reserved_ ULONG _In_opt_ PUNICODE_STRING _In_ ULONG _Out_opt_ PULONG Disposition
Definition: cmfuncs.h:50
#define STATUS_BAD_FUNCTION_TABLE
Definition: ntstatus.h:491
uint32_t ULONG_PTR
Definition: typedefs.h:65
ACPI_PHYSICAL_ADDRESS ACPI_SIZE BOOLEAN Warn BOOLEAN Physical 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:813
UINT32 void void ** ReturnValue
Definition: acevents.h:214
#define FALSE
Definition: types.h:117
#define STATUS_INVALID_DISPOSITION
Definition: ntstatus.h:275
_IRQL_requires_same_ _In_ PVOID _Inout_ struct _CONTEXT _In_ PVOID DispatcherContext
Definition: ntbasedef.h:654
#define EXCEPTION_TARGET_UNWIND
Definition: rtltypes.h:159
#define EXCEPTION_STACK_INVALID
Definition: rtltypes.h:157
EXCEPTION_ROUTINE * PEXCEPTION_ROUTINE
Definition: compat.h:568
#define ASSERT(a)
Definition: mode.c:44
#define EXCEPTION_COLLIDED_UNWIND
Definition: rtltypes.h:160
_IRQL_requires_same_ _In_ PVOID _Inout_ struct _CONTEXT * ContextRecord
Definition: ntbasedef.h:654
unsigned __int64 ULONG64
Definition: imports.h:198
VOID NTAPI RtlpGetStackLimits(PULONG_PTR StackBase, PULONG_PTR StackLimit)
uint64_t DWORD64
Definition: typedefs.h:67
#define NULL
Definition: types.h:112
VOID NTAPI RtlpCheckLogException(IN PEXCEPTION_RECORD ExceptionRecord, IN PCONTEXT ContextRecord, IN PVOID ContextData, IN ULONG Size)
Definition: libsupp.c:201
enum _EXCEPTION_DISPOSITION EXCEPTION_DISPOSITION
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:117

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 }
DECLSPEC_NORETURN NTSYSAPI VOID NTAPI RtlRaiseStatus(_In_ NTSTATUS Status)
#define TRUE
Definition: types.h:120
LONG NTSTATUS
Definition: precomp.h:26
NTSYSAPI NTSTATUS NTAPI ZwRaiseException(_In_ PEXCEPTION_RECORD ExceptionRecord, _In_ PCONTEXT Context, _In_ BOOLEAN SearchFrames)
void * _AddressOfReturnAddress(void)
if(dx==0 &&dy==0)
Definition: linetemp.h:174
NTSYSAPI VOID NTAPI RtlCaptureContext(_Out_ PCONTEXT ContextRecord)
NTSYSAPI NTSTATUS NTAPI ZwContinue(_In_ PCONTEXT Context, _In_ BOOLEAN TestAlert)
#define FALSE
Definition: types.h:117
#define STATUS_INVALID_DISPOSITION
Definition: ntstatus.h:275
void * PVOID
Definition: retypes.h:9
Status
Definition: gdiplustypes.h:24
unsigned __int64 ULONG64
Definition: imports.h:198
BOOLEAN NTAPI RtlpCheckForActiveDebugger(VOID)
Definition: libsupp.c:25
void * _ReturnAddress(void)
struct tagContext Context
Definition: acpixf.h:1034
BOOLEAN NTAPI RtlDispatchException(_In_ PEXCEPTION_RECORD ExceptionRecord, _In_ PCONTEXT ContextRecord)
Definition: except.c:87

Referenced by RaiseException(), RtlDispatchException(), and RtlUnwind().