ReactOS  0.4.13-dev-100-gc8611ae
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  */
30 VOID
31 NTAPI
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  */
83 VOID
84 NTAPI
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;
98  ExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
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  */
131 USHORT
132 NTAPI
134  IN ULONG FramesToCapture,
135  OUT PVOID *BackTrace,
136  OUT PULONG BackTraceHash OPTIONAL)
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 */
166  if (BackTraceHash) *BackTraceHash = 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 */
177 static 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 
202 static 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 
236 static VOID
237  PrintStackTrace(struct _EXCEPTION_POINTERS *ExceptionInfo)
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 
255  _module_name_from_addr(ExceptionRecord->ExceptionAddress, &StartAddr, szMod, sizeof(szMod));
256  DbgPrint("Address:\n %8x+%-8x %s\n",
257  (PVOID) StartAddr,
258  (ULONG_PTR) ExceptionRecord->ExceptionAddress - (ULONG_PTR) StartAddr,
259  szMod);
260 #ifdef _M_IX86
261  DbgPrint("Frames:\n");
262 
263  _SEH2_TRY
264  {
265  UINT i;
266  PULONG Frame = (PULONG) ContextRecord->Ebp;
267 
268  for (i = 0; Frame[1] != 0 && Frame[1] != 0xdeadbeef && i < 128; i++)
269  {
270  //if (IsBadReadPtr((PVOID) Frame[1], 4))
271  if (Frame[1] == 0)
272  {
273  DbgPrint(" %8x%9s %s\n", Frame[1], "<invalid address>", " ");
274  }
275  else
276  {
277  _module_name_from_addr((const void*) Frame[1], &StartAddr,
278  szMod, sizeof(szMod));
279  DbgPrint(" %8x+%-8x %s\n",
280  (PVOID) StartAddr,
281  (ULONG_PTR) Frame[1] - (ULONG_PTR) StartAddr,
282  szMod);
283  }
284 
285  if (Frame[0] == 0) break;
286  //if (IsBadReadPtr((PVOID) Frame[0], sizeof(*Frame) * 2))
287  //break;
288 
289  Frame = (PULONG) Frame[0];
290  }
291  }
293  {
294  DbgPrint("<error dumping stack trace: 0x%x>\n", _SEH2_GetExceptionCode());
295  }
296  _SEH2_END;
297 #endif
298 }
299 
300 
301 /*
302  * @unimplemented
303  */
304 LONG
305 NTAPI
307 {
308  /* This is used by the security cookie checks, and also called externally */
310  PrintStackTrace(ExceptionInfo);
312 }
313 
314 /*
315  * @implemented
316  */
317 VOID
318 NTAPI
320 {
321  /* Set the filter which is used by the CriticalSection package */
322  RtlpUnhandledExceptionFilter = RtlEncodePointer(TopLevelExceptionFilter);
323 }
static int Hash(const char *)
Definition: reader.c:2257
VOID NTAPI RtlRaiseException(IN PEXCEPTION_RECORD ExceptionRecord)
Definition: exception.c:32
#define IN
Definition: typedefs.h:38
#define TRUE
Definition: types.h:120
ULONG Esp
Definition: nt_native.h:1479
ULONG Eip
Definition: nt_native.h:1476
#define DbgPrint
Definition: loader.c:25
char CHAR
Definition: xmlstorage.h:175
ULONG Ecx
Definition: nt_native.h:1467
LONG NTSTATUS
Definition: precomp.h:26
NTSYSAPI NTSTATUS NTAPI ZwRaiseException(_In_ PEXCEPTION_RECORD ExceptionRecord, _In_ PCONTEXT Context, _In_ BOOLEAN SearchFrames)
#define EXCEPTION_NONCONTINUABLE
Definition: rtltypes.h:150
ULONG R6
Definition: compat.h:341
ULONG R0
Definition: compat.h:335
ULONG SegGs
Definition: nt_native.h:1453
#define CONTEXT_FULL
Definition: compat.h:270
ULONG SegFs
Definition: nt_native.h:1454
ULONG SegDs
Definition: nt_native.h:1456
NTSYSAPI VOID NTAPI RtlCaptureContext(_Out_ PCONTEXT ContextRecord)
DWORD WINAPI GetModuleFileNameA(HINSTANCE hModule, LPSTR lpFilename, DWORD nSize)
Definition: loader.c:546
PVOID ExceptionAddress
Definition: compat.h:199
_SEH2_TRY
Definition: create.c:4250
uint32_t ULONG_PTR
Definition: typedefs.h:63
NTSYSAPI NTSTATUS NTAPI ZwContinue(_In_ PCONTEXT Context, _In_ BOOLEAN TestAlert)
static const char * _module_name_from_addr(const void *addr, void **module_start_addr, char *psz, size_t nChars)
Definition: exception.c:178
DWORD ExceptionCode
Definition: compat.h:196
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
ULONG R8
Definition: compat.h:343
USHORT NTAPI RtlCaptureStackBackTrace(IN ULONG FramesToSkip, IN ULONG FramesToCapture, OUT PVOID *BackTrace, OUT PULONG BackTraceHash OPTIONAL)
Definition: exception.c:133
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
long LONG
Definition: pedump.c:60
ULONG SegEs
Definition: nt_native.h:1455
ULONG Esi
Definition: nt_native.h:1464
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
ULONG SegCs
Definition: nt_native.h:1477
NTSYSAPI PVOID WINAPI RtlEncodePointer(PVOID)
smooth NULL
Definition: ftsmooth.c:416
ULONG Edx
Definition: nt_native.h:1466
static VOID _dump_context(PCONTEXT pc)
Definition: exception.c:203
ULONG R9
Definition: compat.h:344
ULONG R1
Definition: compat.h:336
ULONG EFlags
Definition: nt_native.h:1478
ULONG Ebx
Definition: nt_native.h:1465
ULONG R4
Definition: compat.h:339
#define PtrToUlong(u)
Definition: config.h:107
#define RtlFillMemoryUlong(dst, len, val)
Definition: mkhive.h:55
PCONTEXT ContextRecord
Definition: rtltypes.h:197
NTSYSAPI BOOLEAN NTAPI RtlDispatchException(_In_ PEXCEPTION_RECORD ExceptionRecord, _In_ PCONTEXT Context)
Definition: except.c:34
ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]
Definition: compat.h:201
ULONG R11
Definition: ke.h:266
#define for
Definition: utility.h:88
SIZE_T NTAPI VirtualQuery(IN LPCVOID lpAddress, OUT PMEMORY_BASIC_INFORMATION lpBuffer, IN SIZE_T dwLength)
Definition: virtmem.c:220
_IRQL_requires_same_ _In_ PVOID _Inout_ struct _CONTEXT * ContextRecord
Definition: ntbasedef.h:661
BOOLEAN NTAPI RtlpCheckForActiveDebugger(VOID)
Definition: libsupp.c:25
GLenum const GLvoid * addr
Definition: glext.h:9621
VOID NTAPI RtlRaiseStatus(IN NTSTATUS Status)
Definition: exception.c:85
ULONG Eax
Definition: nt_native.h:1468
PRTLP_UNHANDLED_EXCEPTION_FILTER RtlpUnhandledExceptionFilter
Definition: exception.c:21
Status
Definition: gdiplustypes.h:24
struct _EXCEPTION_RECORD * ExceptionRecord
Definition: compat.h:198
LONG NTAPI RtlUnhandledExceptionFilter(IN struct _EXCEPTION_POINTERS *ExceptionInfo)
Definition: exception.c:306
_SEH2_END
Definition: create.c:4424
#define STATUS_ACCESS_VIOLATION
Definition: ntstatus.h:228
unsigned short USHORT
Definition: pedump.c:61
ULONG NTAPI RtlWalkFrameChain(OUT PVOID *Callers, IN ULONG Count, IN ULONG Flags)
Definition: libsupp.c:227
ULONG Cpsr
Definition: compat.h:353
ULONG R5
Definition: compat.h:340
unsigned int * PULONG
Definition: retypes.h:1
unsigned int UINT
Definition: ndis.h:50
ULONG R7
Definition: compat.h:342
RTLP_UNHANDLED_EXCEPTION_FILTER * PRTLP_UNHANDLED_EXCEPTION_FILTER
Definition: rtltypes.h:548
ULONG R12
Definition: ke.h:267
static PULONG
Definition: exception.c:56
void * _ReturnAddress(void)
#define OUT
Definition: typedefs.h:39
struct tagContext Context
Definition: acpixf.h:1012
unsigned int ULONG
Definition: retypes.h:1
ULONG Sp
Definition: compat.h:350
#define ERROR_CALL_NOT_IMPLEMENTED
Definition: compat.h:92
#define UNIMPLEMENTED
Definition: debug.h:114
DWORD ExceptionFlags
Definition: compat.h:197
ULONG R10
Definition: compat.h:345
PEXCEPTION_RECORD ExceptionRecord
Definition: rtltypes.h:196
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
ULONG R2
Definition: compat.h:337
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
static VOID PrintStackTrace(struct _EXCEPTION_POINTERS *ExceptionInfo)
Definition: exception.c:237
DWORD NumberParameters
Definition: compat.h:200
ULONG Pc
Definition: compat.h:352
ULONG R3
Definition: compat.h:338
VOID NTAPI RtlSetUnhandledExceptionFilter(IN PRTLP_UNHANDLED_EXCEPTION_FILTER TopLevelExceptionFilter)
Definition: exception.c:319
ULONG Ebp
Definition: nt_native.h:1475
ULONG Edi
Definition: nt_native.h:1463
ULONG Lr
Definition: compat.h:351
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68