ReactOS  0.4.15-dev-5462-g4d0d22a
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:666
unsigned char BOOLEAN
_In_ BOOLEAN Handled
Definition: ketypes.h:337
BOOLEAN NTAPI RtlCallVectoredExceptionHandlers(_In_ PEXCEPTION_RECORD ExceptionRecord, _In_ PCONTEXT Context)
Definition: libsupp.c:810
_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:819

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 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 }
#define STATUS_UNWIND_CONSOLIDATE
Definition: ntstatus.h:220
#define EXCEPTION_NONCONTINUABLE_EXCEPTION
Definition: winbase.h:328
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:479
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
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:709
#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
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 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:124

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:1038
BOOLEAN NTAPI RtlDispatchException(_In_ PEXCEPTION_RECORD ExceptionRecord, _In_ PCONTEXT ContextRecord)
Definition: except.c:87

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