1 /* COPYRIGHT: See COPYING in the top level directory
2 * PROJECT: ReactOS Runtime Library
3 * PURPOSE: User-Mode Exception Support
4 * FILE: lib/rtl/exception.c
5 * PROGRAMERS: Alex Ionescu (alex@relsoft.net)
6 * David Welch <welch@cwcom.net>
7 * Skywing <skywing@valhallalegends.com>
8 * KJK::Hyperion <noog@libero.it>
11 /* INCLUDES *****************************************************************/
18 /* FUNCTIONS ***************************************************************/
25 RtlRaiseException(PEXCEPTION_RECORD ExceptionRecord
)
30 /* Capture the context */
31 RtlCaptureContext(&Context
);
33 /* Save the exception address */
34 ExceptionRecord
->ExceptionAddress
= RtlpGetExceptionAddress();
36 /* Write the context flag */
37 Context
.ContextFlags
= CONTEXT_FULL
;
39 /* Check if we're being debugged (user-mode only) */
40 if (!RtlpCheckForActiveDebugger(TRUE
))
42 /* Raise an exception immediately */
43 Status
= ZwRaiseException(ExceptionRecord
, &Context
, TRUE
);
47 /* Dispatch the exception and check if we should continue */
48 if (RtlDispatchException(ExceptionRecord
, &Context
))
50 /* Raise the exception */
51 Status
= ZwRaiseException(ExceptionRecord
, &Context
, FALSE
);
55 /* Continue, go back to previous context */
56 Status
= ZwContinue(&Context
, FALSE
);
60 /* If we returned, raise a status */
61 RtlRaiseStatus(Status
);
69 RtlRaiseStatus(NTSTATUS Status
)
71 EXCEPTION_RECORD ExceptionRecord
;
74 /* Capture the context */
75 RtlCaptureContext(&Context
);
77 /* Add one argument to ESP */
78 Context
.Esp
+= sizeof(PVOID
);
80 /* Create an exception record */
81 ExceptionRecord
.ExceptionAddress
= RtlpGetExceptionAddress();
82 ExceptionRecord
.ExceptionCode
= Status
;
83 ExceptionRecord
.ExceptionRecord
= NULL
;
84 ExceptionRecord
.NumberParameters
= 0;
85 ExceptionRecord
.ExceptionFlags
= EXCEPTION_NONCONTINUABLE
;
87 /* Write the context flag */
88 Context
.ContextFlags
= CONTEXT_FULL
;
90 /* Check if we're being debugged (user-mode only) */
91 if (!RtlpCheckForActiveDebugger(TRUE
))
93 /* Raise an exception immediately */
94 ZwRaiseException(&ExceptionRecord
, &Context
, TRUE
);
98 /* Dispatch the exception */
99 RtlDispatchException(&ExceptionRecord
, &Context
);
101 /* Raise exception if we got here */
102 Status
= ZwRaiseException(&ExceptionRecord
, &Context
, FALSE
);
105 /* If we returned, raise a status */
106 RtlRaiseStatus(Status
);
114 RtlWalkFrameChain(OUT PVOID
*Callers
,
118 PULONG Stack
, NewStack
;
120 ULONG_PTR StackBegin
, StackEnd
;
121 BOOLEAN Result
, StopSearch
= FALSE
;
124 /* Get current EBP */
127 __asm__("mov %%ebp, %0" : "=r" (Stack
) : );
128 #elif defined(_MSC_VER)
133 /* Set it as the stack begin limit as well */
134 StackBegin
= (ULONG_PTR
)Stack
;
136 /* Check if we're called for non-logging mode */
139 /* Get the actual safe limits */
140 Result
= RtlpCaptureStackLimits((ULONG_PTR
)Stack
,
143 if (!Result
) return 0;
146 /* Loop the frames */
147 for (i
= 0; i
< Count
; i
++)
149 /* Check if we're past the stack */
150 if ((ULONG_PTR
)Stack
>= StackEnd
) break;
152 /* Check if this is the first entry */
156 if ((ULONG_PTR
)Stack
!= StackBegin
) break;
160 if ((ULONG_PTR
)Stack
== StackBegin
) break;
164 /* Make sure there's enough frames */
165 if ((StackEnd
- (ULONG_PTR
)Stack
) < (2 * sizeof(ULONG_PTR
))) break;
167 /* Get new stack and EIP */
168 NewStack
= (PULONG
)Stack
[0];
171 /* Check if the new pointer is above the oldone and past the end */
172 if (!((Stack
< NewStack
) && ((ULONG_PTR
)NewStack
< StackEnd
)))
174 /* Stop searching after this entry */
178 /* Also make sure that the EIP isn't a stack address */
179 if ((StackBegin
< Eip
) && (Eip
< StackEnd
)) break;
181 /* Save this frame */
182 Callers
[i
] = (PVOID
)Eip
;
184 /* Check if we should continue */
185 if (StopSearch
) break;
187 /* Move to the next stack */
191 /* Return frames parsed */
200 RtlCaptureStackBackTrace(IN ULONG FramesToSkip
,
201 IN ULONG FramesToCapture
,
202 OUT PVOID
*BackTrace
,
203 OUT PULONG BackTraceHash OPTIONAL
)
205 PVOID Frames
[2 * 64];
209 /* Skip a frame for the caller */
212 /* Don't go past the limit */
213 if ((FramesToCapture
+ FramesToSkip
) >= 128) return 0;
215 /* Do the back trace */
216 FrameCount
= RtlWalkFrameChain(Frames
, FramesToCapture
+ FramesToSkip
, 0);
218 /* Make sure we're not skipping all of them */
219 if (FrameCount
<= FramesToSkip
) return 0;
221 /* Loop all the frames */
222 for (i
= 0; i
< FramesToCapture
; i
++)
224 /* Don't go past the limit */
225 if ((FramesToSkip
+ i
) >= FrameCount
) break;
227 /* Save this entry and hash it */
228 BackTrace
[i
] = Frames
[FramesToSkip
+ i
];
229 Hash
+= PtrToUlong(BackTrace
[i
]);
233 if (BackTraceHash
) *BackTraceHash
= Hash
;
235 /* Clear the other entries and return count */
236 RtlFillMemoryUlong(Frames
, 128, 0);
245 RtlUnhandledExceptionFilter(IN
struct _EXCEPTION_POINTERS
* ExceptionInfo
)
248 return ERROR_CALL_NOT_IMPLEMENTED
;