ReactOS 0.4.16-dev-835-gd769f56
exception_filter.cpp
Go to the documentation of this file.
1//
2// exception_filter.cpp
3//
4// Copyright (c) Microsoft Corporation. All rights reserved.
5//
6// The exception filter used by the startup code to transform various exceptions
7// into C signals.
8//
9#include <corecrt_internal.h>
10#include <float.h>
11#include <signal.h>
12#include <stddef.h>
13
14
15
16// The default exception action table. Exceptions corresponding to the same
17// signal (e.g. SIGFPE) must be grouped together. If any _action field is
18// changed in this table, that field must be initialized with an encoded
19// function pointer during CRT startup.
21{
22// _exception_number _signal_number _action
23// --------------------------------------------------------
36};
37
38// WARNING!!! This constant must be the integer value for which
39// __acrt_exception_action_table[__acrt_signal_action_first_fpe_index] is the very FIRST entry in the table
40// corresponding to a floating point exception.
41extern "C" { size_t const __acrt_signal_action_first_fpe_index = 3; }
42
43// There are __acrt_signal_action_fpe_count entries in XcptActTab for floating point exceptions:
44extern "C" { size_t const __acrt_signal_action_fpe_count = 9; }
45
46// Size of the exception-action table in bytes
48
49// Number of entries in the exception-action table
51
52
53
54// Finds an exception-action entry by exception number
56 unsigned long const xcptnum,
57 __crt_signal_action_t* const action_table
58 ) throw()
59{
60 __crt_signal_action_t* const first = action_table;
62
63 // Search for the matching entry and return it if we find it:
64 for (__crt_signal_action_t* it = first; it != last; ++it)
65 if (it->_exception_number == xcptnum)
66 return it;
67
68 // Otherwise, return nullptr on failure:
69 return nullptr;
70}
71
72
73
74// Wrapper that only calls the exception filter for C++ exceptions
75extern "C" int __cdecl _seh_filter_dll(
76 unsigned long const xcptnum,
77 PEXCEPTION_POINTERS const pxcptinfoptrs
78 )
79{
80 if (xcptnum != ('msc' | 0xE0000000))
82
83 return _seh_filter_exe(xcptnum,pxcptinfoptrs);
84}
85
86
87
88// Identifies an exception and the action to be taken with it
89//
90// This function is called by the exception filter expression of the __try-
91// __except statement in the startup code, which guards the call to the user-
92// provided main (or DllMain) function. This function consults the per-thread
93// exception-action table to identify the exception and determine its
94// disposition. The disposition of an exception corresponding to a C signal may
95// be modified by a call to signal(). There are three broad cases:
96//
97// (1) Unrecognized exceptions and exceptions for which the action is SIG_DFL
98//
99// In both of these cases, EXCEPTION_CONTINUE_SEARCH is returned to cause
100// the OS exception dispatcher to pass the exception on to the next exception
101// handler in the chain--usually a system default handler.
102//
103// (2) Exceptions corresponding to C signals with an action other than SIG_DFL
104//
105// These are the C signals whose disposition has been affected by a call to
106// signal() or whose default semantics differ slightly from the corresponding
107// OS exception. In all cases, the appropriate disposition of the C signal is
108// made by the function (e.g., calling a user-specified signal handler).
109// Then, EXCEPTION_CONTINUE_EXECUTION is returned to cause the OS exception
110// dispatcher to dismiss the exception and resume execution at the point
111// where the exception occurred.
112//
113// (3) Exception for which the action is SIG_DIE
114//
115// These are the exceptions corresponding to fatal C Runtime errors. For
116// these, EXCEPTION_EXECUTE_HANDLER is returned to cause control to pass
117// into the __except block of the __try-__except statement. There, the
118// runtime error is identified, an appropriate error message is printed out,
119// and the program is terminated.
121 unsigned long const xcptnum,
122 PEXCEPTION_POINTERS const pxcptinfoptrs
123 )
124{
125 // Get the PTD and find the action for this exception. If either of these
126 // fails, return to let the handler search continue.
128 if (ptd == nullptr)
130
131 __crt_signal_action_t* const pxcptact = xcptlookup(xcptnum, ptd->_pxcptacttab);
132 if (pxcptact == nullptr)
134
135 __crt_signal_handler_t const phandler = pxcptact->_action;
136
137 // The default behavior (SIG_DFL) is not to handle the exception:
138 if (phandler == SIG_DFL)
140
141 // If the behavior is to die, execute the handler:
142 if (phandler == SIG_DIE)
143 {
144 // Reset the _action (in case of recursion) and enter the __except:
145 pxcptact->_action = SIG_DFL;
147 }
148
149 // If an exception is ignored, just ignore it:
150 if (phandler == SIG_IGN)
152
153 // The remaining exceptions all correspond to C signals which have signal
154 // handlers associated with them. For some, special setup is required
155 // before the signal handler is called. In all cases, if the signal handler
156 // returns, -1 is returned by this function to resume execution at the point
157 // where the exception occurred.
158
159 // Save the old exception pointers in case this is a nested exception/signal.
160 PEXCEPTION_POINTERS const old_pxcptinfoptrs = ptd->_tpxcptinfoptrs;
161 ptd->_tpxcptinfoptrs = pxcptinfoptrs;
162
163 // Call the user-supplied signal handler. Floating point exceptions must be
164 // handled specially since, from the C point of view, there is only one
165 // signal. The exact identity of the exception is passed in the per-thread
166 // variable _tfpecode.
167 if (pxcptact->_signal_number == SIGFPE)
168 {
169 // Reset the _action field to the default for all SIGFPE entries:
172
173 for (__crt_signal_action_t* it = first; it != last; ++it)
174 it->_action = SIG_DFL;
175
176 // Save the current _tfpecode in case this is a nested floating point
177 // exception. It's not clear that we need to support this, but it's
178 // easy to support.
179 int const old_fpecode = ptd->_tfpecode;
180
181 // Note: There are no exceptions corresponding to _FPE_UNEMULATED and
182 // _FPE_SQRTNEG. Furthermore, STATUS_FLOATING_STACK_CHECK is raised for
183 // both stack overflow and underflow, thus the exception does not
184 // distinguish between _FPE_STACKOVERFLOW and _FPE_STACKUNDERFLOW.
185 // Arbitrarily, _tfpecode is set to the formr value.
186 switch (pxcptact->_exception_number)
187 {
188 case STATUS_FLOAT_DIVIDE_BY_ZERO: ptd->_tfpecode = _FPE_ZERODIVIDE; break;
189 case STATUS_FLOAT_INVALID_OPERATION: ptd->_tfpecode = _FPE_INVALID; break;
190 case STATUS_FLOAT_OVERFLOW: ptd->_tfpecode = _FPE_OVERFLOW; break;
191 case STATUS_FLOAT_UNDERFLOW: ptd->_tfpecode = _FPE_UNDERFLOW; break;
192 case STATUS_FLOAT_DENORMAL_OPERAND: ptd->_tfpecode = _FPE_DENORMAL; break;
193 case STATUS_FLOAT_INEXACT_RESULT: ptd->_tfpecode = _FPE_INEXACT; break;
194 case STATUS_FLOAT_STACK_CHECK: ptd->_tfpecode = _FPE_STACKOVERFLOW; break;
195 case STATUS_FLOAT_MULTIPLE_TRAPS: ptd->_tfpecode = _FPE_MULTIPLE_TRAPS; break;
196 case STATUS_FLOAT_MULTIPLE_FAULTS: ptd->_tfpecode = _FPE_MULTIPLE_FAULTS; break;
197 }
198
199 // Call the SIGFPE handler. Note that we cast to the given function
200 // type to support old MS C programs whose SIGFPE handlers expect two
201 // arguments.
202 //
203 // CRT_REFACTOR TODO Can we remove this support? It's not clear that
204 // this is correct for all architectures (e.g. x64 and ARM).
205 reinterpret_cast<void (__cdecl *)(int, int)>(phandler)(SIGFPE, ptd->_tfpecode);
206
207 // Restore the stored value of _tfpecode:
208 ptd->_tfpecode = old_fpecode;
209 }
210 else
211 {
212 // Reset the _action field to the default, then call the user-
213 // supplied handler:
214 pxcptact->_action = SIG_DFL;
215 phandler(pxcptact->_signal_number);
216 }
217
218 // Restore the stored value of _pxcptinfoptrs:
219 ptd->_tpxcptinfoptrs = old_pxcptinfoptrs;
220
222}
#define __cdecl
Definition: accygwin.h:79
void(__cdecl * __crt_signal_handler_t)(int)
__acrt_ptd *__cdecl __acrt_getptd_noexit(void)
#define SIG_DFL
Definition: signal.h:47
#define SIGILL
Definition: signal.h:25
#define SIGFPE
Definition: signal.h:30
#define SIG_IGN
Definition: signal.h:48
#define SIGSEGV
Definition: signal.h:33
_In_ size_t const _In_ int _In_ bool const _In_ unsigned const _In_ __acrt_rounding_mode const _Inout_ __crt_cached_ptd_host & ptd
Definition: cvt.cpp:355
#define STATUS_ILLEGAL_INSTRUCTION
Definition: d3dkmdt.h:41
switch(r->id)
Definition: btrfs.c:3046
int __cdecl _seh_filter_dll(unsigned long const xcptnum, PEXCEPTION_POINTERS const pxcptinfoptrs)
size_t const __acrt_signal_action_first_fpe_index
static __crt_signal_action_t *__cdecl xcptlookup(unsigned long const xcptnum, __crt_signal_action_t *const action_table)
size_t const __acrt_signal_action_fpe_count
struct __crt_signal_action_t const __acrt_exception_action_table[]
int __cdecl _seh_filter_exe(unsigned long const xcptnum, PEXCEPTION_POINTERS const pxcptinfoptrs)
size_t const __acrt_signal_action_table_count
size_t const __acrt_signal_action_table_size
const GLint * first
Definition: glext.h:5794
#define _FPE_INEXACT
Definition: float.h:104
#define _FPE_OVERFLOW
Definition: float.h:102
#define _FPE_ZERODIVIDE
Definition: float.h:101
#define _FPE_STACKOVERFLOW
Definition: float.h:107
#define _FPE_INVALID
Definition: float.h:99
#define _FPE_DENORMAL
Definition: float.h:100
#define _FPE_UNDERFLOW
Definition: float.h:103
#define _FPE_MULTIPLE_TRAPS
Definition: float.h:192
#define _FPE_MULTIPLE_FAULTS
Definition: float.h:193
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:90
#define EXCEPTION_CONTINUE_SEARCH
Definition: excpt.h:91
#define EXCEPTION_CONTINUE_EXECUTION
Definition: excpt.h:92
static UINT UINT last
Definition: font.c:45
#define STATUS_FLOAT_UNDERFLOW
Definition: ntstatus.h:383
#define STATUS_FLOAT_OVERFLOW
Definition: ntstatus.h:381
#define STATUS_FLOAT_STACK_CHECK
Definition: ntstatus.h:382
#define STATUS_FLOAT_DIVIDE_BY_ZERO
Definition: ntstatus.h:378
#define STATUS_FLOAT_MULTIPLE_FAULTS
Definition: ntstatus.h:807
#define STATUS_PRIVILEGED_INSTRUCTION
Definition: ntstatus.h:386
#define STATUS_FLOAT_MULTIPLE_TRAPS
Definition: ntstatus.h:808
#define STATUS_ACCESS_VIOLATION
Definition: ntstatus.h:242
#define STATUS_FLOAT_INVALID_OPERATION
Definition: ntstatus.h:380
#define STATUS_FLOAT_INEXACT_RESULT
Definition: ntstatus.h:379
#define STATUS_FLOAT_DENORMAL_OPERAND
Definition: ntstatus.h:377
unsigned long _exception_number
__crt_signal_handler_t _action
#define const
Definition: zconf.h:233