ReactOS 0.4.16-dev-340-g0540c21
exception.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Runtime Library
4 * PURPOSE: User-Mode Exception Support
5 * FILE: lib/rtl/exception.c
6 * PROGRAMERS: Alex Ionescu (alex@relsoft.net)
7 * David Welch <welch@cwcom.net>
8 * Skywing <skywing@valhallalegends.com>
9 * KJK::Hyperion <noog@libero.it>
10 */
11
12/* INCLUDES *****************************************************************/
13
14#include <rtl.h>
15
16#define NDEBUG
17#include <debug.h>
18
19/* GLOBALS *****************************************************************/
20
22
23/* FUNCTIONS ***************************************************************/
24
25#if !defined(_M_IX86) && !defined(_M_AMD64)
26
27/*
28 * @implemented
29 */
30VOID
33{
36
37 /* Capture the context */
39
40 /* Save the exception address */
41 ExceptionRecord->ExceptionAddress = _ReturnAddress();
42
43 /* Write the context flag */
44 Context.ContextFlags = CONTEXT_FULL;
45
46 /* Check if user mode debugger is active */
48 {
49 /* Raise an exception immediately */
50 Status = ZwRaiseException(ExceptionRecord, &Context, TRUE);
51 }
52 else
53 {
54 /* Dispatch the exception and check if we should continue */
55 if (!RtlDispatchException(ExceptionRecord, &Context))
56 {
57 /* Raise the exception */
58 Status = ZwRaiseException(ExceptionRecord, &Context, FALSE);
59 }
60 else
61 {
62 /* Continue, go back to previous context */
64 }
65 }
66
67 /* If we returned, raise a status */
69}
70
71#endif
72
73#if !defined(_M_IX86)
74
75#ifdef _MSC_VER
76#pragma warning(push)
77#pragma warning(disable:4717) // RtlRaiseStatus is recursive by design
78#endif
79
80/*
81 * @implemented
82 */
83VOID
86{
87 EXCEPTION_RECORD ExceptionRecord;
89
90 /* Capture the context */
92
93 /* Create an exception record */
94 ExceptionRecord.ExceptionAddress = _ReturnAddress();
95 ExceptionRecord.ExceptionCode = Status;
96 ExceptionRecord.ExceptionRecord = NULL;
97 ExceptionRecord.NumberParameters = 0;
99
100 /* Write the context flag */
101 Context.ContextFlags = CONTEXT_FULL;
102
103 /* Check if user mode debugger is active */
105 {
106 /* Raise an exception immediately */
107 ZwRaiseException(&ExceptionRecord, &Context, TRUE);
108 }
109 else
110 {
111 /* Dispatch the exception */
112 RtlDispatchException(&ExceptionRecord, &Context);
113
114 /* Raise exception if we got here */
115 Status = ZwRaiseException(&ExceptionRecord, &Context, FALSE);
116 }
117
118 /* If we returned, raise a status */
120}
121
122#ifdef _MSC_VER
123#pragma warning(pop)
124#endif
125
126#endif
127
128/*
129 * @implemented
130 */
131USHORT
132NTAPI
135 OUT PVOID *BackTrace,
137{
138 PVOID Frames[2 * 64];
139 ULONG FrameCount;
140 ULONG Hash = 0, i;
141
142 /* Skip a frame for the caller */
143 FramesToSkip++;
144
145 /* Don't go past the limit */
146 if ((FramesToCapture + FramesToSkip) >= 128) return 0;
147
148 /* Do the back trace */
149 FrameCount = RtlWalkFrameChain(Frames, FramesToCapture + FramesToSkip, 0);
150
151 /* Make sure we're not skipping all of them */
152 if (FrameCount <= FramesToSkip) return 0;
153
154 /* Loop all the frames */
155 for (i = 0; i < FramesToCapture; i++)
156 {
157 /* Don't go past the limit */
158 if ((FramesToSkip + i) >= FrameCount) break;
159
160 /* Save this entry and hash it */
161 BackTrace[i] = Frames[FramesToSkip + i];
162 Hash += PtrToUlong(BackTrace[i]);
163 }
164
165 /* Write the hash */
167
168 /* Clear the other entries and return count */
169 RtlFillMemoryUlong(Frames, 128, 0);
170 return (USHORT)i;
171}
172
173/*
174* Private helper function to lookup the module name from a given address.
175* The address can point to anywhere within the module.
176*/
177static const char*
178 _module_name_from_addr(const void* addr, void **module_start_addr,
179 char* psz, size_t nChars)
180{
181#if 0
183 if (VirtualQuery(addr, &mbi, sizeof(mbi)) != sizeof(mbi) ||
184 !GetModuleFileNameA((HMODULE) mbi.AllocationBase, psz, nChars))
185 {
186 psz[0] = '\0';
187 *module_start_addr = 0;
188 }
189 else
190 {
191 *module_start_addr = (void *) mbi.AllocationBase;
192 }
193 return psz;
194#else
195 psz[0] = '\0';
196 *module_start_addr = 0;
197 return psz;
198#endif
199}
200
201
202static VOID
204{
205#ifdef _M_IX86
206 /*
207 * Print out the CPU registers
208 */
209 DbgPrint("CS:EIP %x:%x\n", pc->SegCs & 0xffff, pc->Eip);
210 DbgPrint("DS %x ES %x FS %x GS %x\n", pc->SegDs & 0xffff, pc->SegEs & 0xffff,
211 pc->SegFs & 0xffff, pc->SegGs & 0xfff);
212 DbgPrint("EAX: %.8x EBX: %.8x ECX: %.8x\n", pc->Eax, pc->Ebx, pc->Ecx);
213 DbgPrint("EDX: %.8x EBP: %.8x ESI: %.8x ESP: %.8x\n", pc->Edx,
214 pc->Ebp, pc->Esi, pc->Esp);
215 DbgPrint("EDI: %.8x EFLAGS: %.8x\n", pc->Edi, pc->EFlags);
216#elif defined(_M_AMD64)
217 DbgPrint("CS:RIP %x:%I64x\n", pc->SegCs & 0xffff, pc->Rip);
218 DbgPrint("DS %x ES %x FS %x GS %x\n", pc->SegDs & 0xffff, pc->SegEs & 0xffff,
219 pc->SegFs & 0xffff, pc->SegGs & 0xfff);
220 DbgPrint("RAX: %I64x RBX: %I64x RCX: %I64x RDI: %I64x\n", pc->Rax, pc->Rbx, pc->Rcx, pc->Rdi);
221 DbgPrint("RDX: %I64x RBP: %I64x RSI: %I64x RSP: %I64x\n", pc->Rdx, pc->Rbp, pc->Rsi, pc->Rsp);
222 DbgPrint("R8: %I64x R9: %I64x R10: %I64x R11: %I64x\n", pc->R8, pc->R9, pc->R10, pc->R11);
223 DbgPrint("R12: %I64x R13: %I64x R14: %I64x R15: %I64x\n", pc->R12, pc->R13, pc->R14, pc->R15);
224 DbgPrint("EFLAGS: %.8x\n", pc->EFlags);
225#elif defined(_M_ARM)
226 DbgPrint("Pc: %lx Lr: %lx Sp: %lx Cpsr: %lx\n", pc->Pc, pc->Lr, pc->Sp, pc->Cpsr);
227 DbgPrint("R0: %lx R1: %lx R2: %lx R3: %lx\n", pc->R0, pc->R1, pc->R2, pc->R3);
228 DbgPrint("R4: %lx R5: %lx R6: %lx R7: %lx\n", pc->R4, pc->R5, pc->R6, pc->R7);
229 DbgPrint("R8: %lx R9: %lx R10: %lx R11: %lx\n", pc->R8, pc->R9, pc->R10, pc->R11);
230 DbgPrint("R12: %lx\n", pc->R12);
231#else
232#pragma message ("Unknown architecture")
233#endif
234}
235
236static VOID
238{
239 PVOID StartAddr;
240 CHAR szMod[128] = "";
241 PEXCEPTION_RECORD ExceptionRecord = ExceptionInfo->ExceptionRecord;
242 PCONTEXT ContextRecord = ExceptionInfo->ContextRecord;
243
244 /* Print a stack trace. */
245 DbgPrint("Unhandled exception\n");
246 DbgPrint("ExceptionCode: %8x\n", ExceptionRecord->ExceptionCode);
247
248 if ((NTSTATUS) ExceptionRecord->ExceptionCode == STATUS_ACCESS_VIOLATION &&
249 ExceptionRecord->NumberParameters == 2)
250 {
251 DbgPrint("Faulting Address: %8x\n", ExceptionRecord->ExceptionInformation[1]);
252 }
253
254 /* Trace the wine special error and show the modulename and functionname */
255 if (ExceptionRecord->ExceptionCode == 0x80000100 /* EXCEPTION_WINE_STUB */ &&
256 ExceptionRecord->NumberParameters == 2)
257 {
258 DbgPrint("Missing function: %s!%s\n", (PSZ)ExceptionRecord->ExceptionInformation[0], (PSZ)ExceptionRecord->ExceptionInformation[1]);
259 }
260
262 _module_name_from_addr(ExceptionRecord->ExceptionAddress, &StartAddr, szMod, sizeof(szMod));
263 DbgPrint("Address:\n %8x+%-8x %s\n",
264 (PVOID) StartAddr,
265 (ULONG_PTR) ExceptionRecord->ExceptionAddress - (ULONG_PTR) StartAddr,
266 szMod);
267#ifdef _M_IX86
268 DbgPrint("Frames:\n");
269
271 {
272 UINT i;
273 PULONG Frame = (PULONG) ContextRecord->Ebp;
274
275 for (i = 0; Frame[1] != 0 && Frame[1] != 0xdeadbeef && i < 128; i++)
276 {
277 //if (IsBadReadPtr((PVOID) Frame[1], 4))
278 if (Frame[1] == 0)
279 {
280 DbgPrint(" %8x%9s %s\n", Frame[1], "<invalid address>", " ");
281 }
282 else
283 {
284 _module_name_from_addr((const void*) Frame[1], &StartAddr,
285 szMod, sizeof(szMod));
286 DbgPrint(" %8x+%-8x %s\n",
287 (PVOID) StartAddr,
288 (ULONG_PTR) Frame[1] - (ULONG_PTR) StartAddr,
289 szMod);
290 }
291
292 if (Frame[0] == 0) break;
293 //if (IsBadReadPtr((PVOID) Frame[0], sizeof(*Frame) * 2))
294 //break;
295
296 Frame = (PULONG) Frame[0];
297 }
298 }
300 {
301 DbgPrint("<error dumping stack trace: 0x%x>\n", _SEH2_GetExceptionCode());
302 }
303 _SEH2_END;
304#endif
305}
306
307
308/*
309 * @unimplemented
310 */
311LONG
312NTAPI
314{
315 /* This is used by the security cookie checks, and also called externally */
317 PrintStackTrace(ExceptionInfo);
319}
320
321/*
322 * @unimplemented
323 */
324LONG
325NTAPI
327 _In_ PEXCEPTION_POINTERS ExceptionInfo,
329{
330 /* This is used by the security cookie checks, and also called externally */
332 PrintStackTrace(ExceptionInfo);
334}
335
336/*
337 * @implemented
338 */
339VOID
340NTAPI
342{
343 /* Set the filter which is used by the CriticalSection package */
344 RtlpUnhandledExceptionFilter = RtlEncodePointer(TopLevelExceptionFilter);
345}
LONG NTSTATUS
Definition: precomp.h:26
#define UNIMPLEMENTED
Definition: ntoskrnl.c:15
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
BOOLEAN NTAPI RtlpCheckForActiveDebugger(VOID)
Definition: libsupp.c:27
ULONG NTAPI RtlWalkFrameChain(OUT PVOID *Callers, IN ULONG Count, IN ULONG Flags)
Definition: libsupp.c:229
#define ERROR_CALL_NOT_IMPLEMENTED
Definition: compat.h:102
DWORD WINAPI GetModuleFileNameA(HINSTANCE hModule, LPSTR lpFilename, DWORD nSize)
Definition: loader.c:539
static int Hash(const char *)
Definition: reader.c:2257
#define PtrToUlong(u)
Definition: config.h:107
_In_ ULONG FramesToCapture
_In_ ULONG _Out_opt_ PULONG BackTraceHash
Status
Definition: gdiplustypes.h:25
GLenum const GLvoid * addr
Definition: glext.h:9621
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define DbgPrint
Definition: hal.h:12
NTSYSAPI PVOID WINAPI RtlEncodePointer(PVOID)
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:90
#define _ReturnAddress()
Definition: intrin_arm.h:35
#define RtlFillMemoryUlong(dst, len, val)
Definition: mkhive.h:55
#define for
Definition: utility.h:88
static PULONG
Definition: exception.c:52
unsigned int UINT
Definition: ndis.h:50
NTSYSAPI NTSTATUS NTAPI ZwContinue(_In_ PCONTEXT Context, _In_ BOOLEAN TestAlert)
NTSYSAPI NTSTATUS NTAPI ZwRaiseException(_In_ PEXCEPTION_RECORD ExceptionRecord, _In_ PCONTEXT Context, _In_ BOOLEAN SearchFrames)
NTSYSAPI BOOLEAN NTAPI RtlDispatchException(_In_ PEXCEPTION_RECORD ExceptionRecord, _In_ PCONTEXT Context)
Definition: except.c:43
NTSYSAPI VOID NTAPI RtlCaptureContext(_Out_ PCONTEXT ContextRecord)
RTLP_UNHANDLED_EXCEPTION_FILTER * PRTLP_UNHANDLED_EXCEPTION_FILTER
Definition: rtltypes.h:552
#define _In_
Definition: no_sal2.h:158
#define CONTEXT_FULL
Definition: nt_native.h:1375
_IRQL_requires_same_ _In_ PVOID _Inout_ struct _CONTEXT * ContextRecord
Definition: ntbasedef.h:662
#define STATUS_ACCESS_VIOLATION
Definition: ntstatus.h:242
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:165
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:66
#define _SEH2_END
Definition: pseh2_64.h:155
#define _SEH2_TRY
Definition: pseh2_64.h:55
VOID NTAPI RtlRaiseException(IN PEXCEPTION_RECORD ExceptionRecord)
Definition: exception.c:32
PRTLP_UNHANDLED_EXCEPTION_FILTER RtlpUnhandledExceptionFilter
Definition: exception.c:21
static VOID PrintStackTrace(struct _EXCEPTION_POINTERS *ExceptionInfo)
Definition: exception.c:237
LONG NTAPI RtlUnhandledExceptionFilter2(_In_ PEXCEPTION_POINTERS ExceptionInfo, _In_ ULONG Flags)
Definition: exception.c:326
VOID NTAPI RtlSetUnhandledExceptionFilter(IN PRTLP_UNHANDLED_EXCEPTION_FILTER TopLevelExceptionFilter)
Definition: exception.c:341
static const char * _module_name_from_addr(const void *addr, void **module_start_addr, char *psz, size_t nChars)
Definition: exception.c:178
static VOID _dump_context(PCONTEXT pc)
Definition: exception.c:203
USHORT NTAPI RtlCaptureStackBackTrace(IN ULONG FramesToSkip, IN ULONG FramesToCapture, OUT PVOID *BackTrace, OUT PULONG BackTraceHash OPTIONAL)
Definition: exception.c:133
LONG NTAPI RtlUnhandledExceptionFilter(IN struct _EXCEPTION_POINTERS *ExceptionInfo)
Definition: exception.c:313
VOID NTAPI RtlRaiseStatus(IN NTSTATUS Status)
Definition: exception.c:85
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
ULONG Esp
Definition: nt_native.h:1479
ULONG Lr
Definition: ke.h:270
ULONG SegFs
Definition: nt_native.h:1454
ULONG R5
Definition: ke.h:260
ULONG Cpsr
Definition: ke.h:272
ULONG Edx
Definition: nt_native.h:1466
ULONG Esi
Definition: nt_native.h:1464
ULONG R2
Definition: ke.h:257
ULONG R7
Definition: ke.h:262
ULONG R6
Definition: ke.h:261
ULONG Ebp
Definition: nt_native.h:1475
ULONG R3
Definition: ke.h:258
ULONG R8
Definition: ke.h:263
ULONG R1
Definition: ke.h:256
ULONG R0
Definition: ke.h:255
ULONG Ecx
Definition: nt_native.h:1467
ULONG R4
Definition: ke.h:259
ULONG Eip
Definition: nt_native.h:1476
ULONG Sp
Definition: ke.h:269
ULONG R12
Definition: ke.h:267
ULONG SegCs
Definition: nt_native.h:1477
ULONG Pc
Definition: ke.h:271
ULONG SegDs
Definition: nt_native.h:1456
ULONG R9
Definition: ke.h:264
ULONG EFlags
Definition: nt_native.h:1478
ULONG SegGs
Definition: nt_native.h:1453
ULONG R10
Definition: ke.h:265
ULONG Eax
Definition: nt_native.h:1468
ULONG SegEs
Definition: nt_native.h:1455
ULONG Ebx
Definition: nt_native.h:1465
ULONG Edi
Definition: nt_native.h:1463
ULONG R11
Definition: ke.h:266
PEXCEPTION_RECORD ExceptionRecord
Definition: rtltypes.h:200
PCONTEXT ContextRecord
Definition: rtltypes.h:201
struct _EXCEPTION_RECORD * ExceptionRecord
Definition: compat.h:210
DWORD ExceptionCode
Definition: compat.h:208
DWORD NumberParameters
Definition: compat.h:212
DWORD ExceptionFlags
Definition: compat.h:209
ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]
Definition: compat.h:213
PVOID ExceptionAddress
Definition: compat.h:211
#define EXCEPTION_NONCONTINUABLE
Definition: stubs.h:23
uint32_t * PULONG
Definition: typedefs.h:59
#define NTAPI
Definition: typedefs.h:36
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
SIZE_T NTAPI VirtualQuery(IN LPCVOID lpAddress, OUT PMEMORY_BASIC_INFORMATION lpBuffer, IN SIZE_T dwLength)
Definition: virtmem.c:211
char * PSZ
Definition: windef.h:57
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
char CHAR
Definition: xmlstorage.h:175