Pyrogenesis  trunk
debug.h
Go to the documentation of this file.
1 /* Copyright (c) 2015 Wildfire Games
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining
4  * a copy of this software and associated documentation files (the
5  * "Software"), to deal in the Software without restriction, including
6  * without limitation the rights to use, copy, modify, merge, publish,
7  * distribute, sublicense, and/or sell copies of the Software, and to
8  * permit persons to whom the Software is furnished to do so, subject to
9  * the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included
12  * in all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  */
22 
23 /*
24  * platform-independent debug support code.
25  */
26 
27 #ifndef INCLUDED_DEBUG
28 #define INCLUDED_DEBUG
29 
30 // this module provides platform-independent debug facilities, useful for
31 // diagnosing and reporting program errors.
32 // - a symbol engine provides access to compiler-generated debug information and
33 // can also give a stack trace including local variables;
34 // - our more powerful assert() replacement gives a stack trace so
35 // that the underlying problem becomes apparent;
36 // - the output routines make for platform-independent logging and
37 // crashlogs with "last-known activity" reporting.
38 
39 #include "lib/lib_api.h"
40 #include "lib/types.h" // intptr_t
41 #include "lib/status.h"
42 #include "lib/alignment.h"
43 #include "lib/code_annotation.h"
44 #include "lib/code_generation.h"
45 
46 /**
47  * trigger a breakpoint when reached/"called".
48  * if defined as a macro, the debugger can break directly into the
49  * target function instead of one frame below it as with a conventional
50  * call-based implementation.
51  **/
52 #if MSC_VERSION
53 # define debug_break __debugbreak // intrinsic "function"
54 #else
55 extern void debug_break();
56 #endif
57 
58 
59 //-----------------------------------------------------------------------------
60 // output
61 //-----------------------------------------------------------------------------
62 
63 /**
64  * write a formatted string to the debug channel, subject to filtering
65  * (see below). implemented via debug_puts - see performance note there.
66  *
67  * @param fmt Format string and varargs; see printf.
68  **/
69 LIB_API void debug_printf(const char* fmt, ...) PRINTF_ARGS(1);
70 
71 
72 /**
73  * translates and displays the given strings in a dialog.
74  * this is typically only used when debug_DisplayError has failed or
75  * is unavailable because that function is much more capable.
76  * implemented via sys_display_msg; see documentation there.
77  **/
78 LIB_API void debug_DisplayMessage(const wchar_t* caption, const wchar_t* msg);
79 
80 /// flags to customize debug_DisplayError behavior
82 {
83  /**
84  * disallow the Continue button. used e.g. if an exception is fatal.
85  **/
87 
88  /**
89  * enable the Suppress button. set automatically by debug_DisplayError if
90  * it receives a non-NULL suppress pointer. a flag is necessary because
91  * the sys_display_error interface doesn't get that pointer.
92  * rationale for automatic setting: this may prevent someone from
93  * forgetting to specify it, and disabling Suppress despite having
94  * passed a non-NULL pointer doesn't make much sense.
95  **/
97 
98  /**
99  * do not trigger a breakpoint inside debug_DisplayError; caller
100  * will take care of this if ER_BREAK is returned. this is so that the
101  * debugger can jump directly into the offending function.
102  **/
104 
105  /**
106  * display just the given message; do not add any information about the
107  * call stack, do not write crashlogs, etc.
108  */
110 };
111 
112 /**
113  * a bool that is reasonably certain to be set atomically.
114  * we cannot assume support for OpenMP (requires GCC 4.2) or C++0x,
115  * so we'll have to resort to intptr_t, cpu_CAS and COMPILER_FENCE.
116  **/
117 typedef volatile intptr_t atomic_bool;
118 
119 /**
120  * value for suppress flag once set by debug_DisplayError.
121  * rationale: this value is fairly distinctive and helps when
122  * debugging the symbol engine.
123  * use 0 as the initial value to avoid allocating .rdata space.
124  **/
125 static const atomic_bool DEBUG_SUPPRESS = 0xAB;
126 
127 /**
128  * choices offered by the error dialog that are returned
129  * by debug_DisplayError.
130  **/
132 {
133  /**
134  * ignore, continue as if nothing happened.
135  * note: value doesn't start at 0 because that is interpreted as a
136  * DialogBoxParam failure.
137  **/
139 
140  /**
141  * trigger breakpoint, i.e. enter debugger.
142  * only returned if DE_MANUAL_BREAK was passed; otherwise,
143  * debug_DisplayError will trigger a breakpoint itself.
144  **/
146 };
147 
148 /**
149  * all choices offered by the error dialog. those not defined in
150  * ErrorReaction are acted upon by debug_DisplayError and
151  * never returned to callers.
152  * (this separation avoids enumerator-not-handled warnings)
153  **/
155 {
158 
159  /**
160  * ignore and do not report again.
161  * note: non-persistent; only applicable during this program run.
162  **/
164 
165  /**
166  * exit the program immediately.
167  **/
169 
170  /**
171  * special return value for the display_error app hook stub to indicate
172  * that it has done nothing and that the normal sys_display_error
173  * implementation should be called instead.
174  **/
176 };
177 
178 
179 /**
180  * display an error dialog with a message and stack trace.
181  *
182  * @param description text to show.
183  * @param flags: see DebugDisplayErrorFlags.
184  * @param context, lastFuncToSkip: see debug_DumpStack.
185  * @param file, line, func: location of the error (typically passed as
186  * WIDEN(__FILE__), __LINE__, __func__ from a macro)
187  * @param suppress pointer to a caller-allocated flag that can be used to
188  * suppress this error. if NULL, this functionality is skipped and the
189  * "Suppress" dialog button will be disabled.
190  * note: this flag is read and written exclusively here; caller only
191  * provides the storage. values: see DEBUG_SUPPRESS above.
192  * @return ErrorReaction (user's choice: continue running or stop?)
193  **/
194 LIB_API ErrorReaction debug_DisplayError(const wchar_t* description, size_t flags, void* context, const wchar_t* lastFuncToSkip, const wchar_t* file, int line, const char* func, atomic_bool* suppress);
195 
196 // simplified version for just displaying an error message
197 #define DEBUG_DISPLAY_ERROR(description)\
198  do\
199  {\
200  CACHE_ALIGNED(u8) context[DEBUG_CONTEXT_SIZE];\
201  (void)debug_CaptureContext(context);\
202  (void)debug_DisplayError(description, 0, context, L"debug_DisplayError", WIDEN(__FILE__), __LINE__, __func__, 0);\
203  }\
204  while(0)
205 
206 
207 //
208 // filtering
209 //
210 
211 /**
212  * debug output is very useful, but "too much of a good thing can kill you".
213  * we don't want to require different LOGn() macros that are enabled
214  * depending on "debug level", because changing that entails lengthy
215  * compiles and it's too coarse-grained. instead, we require all
216  * strings to start with "tag_string|" (exact case and no quotes;
217  * the alphanumeric-only <tag_string> identifies output type).
218  * they are then subject to filtering: only if the tag has been
219  * "added" via debug_filter_add is the appendant string displayed.
220  *
221  * this approach is easiest to implement and is fine because we control
222  * all logging code. LIMODS falls from consideration since it's not
223  * portable and too complex.
224  *
225  * notes:
226  * - filter changes only affect subsequent debug_*printf calls;
227  * output that didn't pass the filter is permanently discarded.
228  * - strings not starting with a tag are always displayed.
229  * - debug_filter_* can be called at any time and from the debugger,
230  * but are not reentrant.
231  *
232  * in future, allow output with the given tag to proceed.
233  * no effect if already added.
234  **/
235 LIB_API void debug_filter_add(const char* tag);
236 
237 /**
238  * in future, discard output with the given tag.
239  * no effect if not currently added.
240  **/
241 LIB_API void debug_filter_remove(const char* tag);
242 
243 /**
244  * clear all filter state; equivalent to debug_filter_remove for
245  * each tag that was debug_filter_add-ed.
246  **/
247 LIB_API void debug_filter_clear();
248 
249 /**
250  * indicate if the given text would be printed.
251  * useful for a series of debug_printfs - avoids needing to add a tag to
252  * each of their format strings.
253  **/
254 LIB_API bool debug_filter_allows(const char* text);
255 
256 /**
257  * call debug_puts if debug_filter_allows allows the string.
258  **/
259 LIB_API void debug_puts_filtered(const char* text);
260 
261 /**
262  * write an error description and all logs into crashlog.txt
263  * (in unicode format).
264  *
265  * @param text description of the error (including stack trace);
266  * typically generated by debug_BuildErrorMessage.
267  *
268  * @return Status; ERR::REENTERED if reentered via recursion or
269  * multithreading (not allowed since an infinite loop may result).
270  **/
271 LIB_API Status debug_WriteCrashlog(const char* text);
272 
273 
274 //-----------------------------------------------------------------------------
275 // assertions
276 //-----------------------------------------------------------------------------
277 
278 /**
279  * ensure the expression <expr> evaluates to non-zero. used to validate
280  * invariants in the program during development and thus gives a
281  * very helpful warning if something isn't going as expected.
282  * sprinkle these liberally throughout your code!
283  *
284  * to pass more information to users at runtime, you can write
285  * ENSURE(expression && "descriptive string").
286  **/
287 #define ENSURE(expr)\
288  do\
289  {\
290  static atomic_bool suppress__;\
291  if(!(expr))\
292  {\
293  switch(debug_OnAssertionFailure(WIDEN(#expr), &suppress__, WIDEN(__FILE__), __LINE__, __func__))\
294  {\
295  case ER_CONTINUE:\
296  break;\
297  case ER_BREAK:\
298  default:\
299  debug_break();\
300  break;\
301  }\
302  }\
303  }\
304  while(0)
305 
306 /**
307  * same as ENSURE in debug mode, does nothing in release mode.
308  * (we don't override the `assert' macro because users may
309  * inadvertently include <assert.h> afterwards)
310  * (we do not provide an MFC-style VERIFY macro because the distinction
311  * between ENSURE and VERIFY is unclear. to always run code but only
312  * check for success in debug builds without raising unused-variable warnings,
313  * use ASSERT + UNUSED2.)
314  **/
315 #define ASSERT(expr) ENSURE(expr)
316 #ifdef NDEBUG
317 # undef ASSERT
318 # define ASSERT(expr)
319 #endif
320 
321 /**
322  * display the error dialog with the given text. this is less error-prone than
323  * ENSURE(0 && "text"). note that "conditional expression is constant" warnings
324  * are disabled anyway.
325  *
326  * if being able to suppress the warning is desirable (e.g. for self-tests),
327  * then use DEBUG_WARN_ERR instead.
328  **/
329 #define debug_warn(expr) ENSURE(0 && (expr))
330 
331 /**
332  * display the error dialog with text corresponding to the given error code.
333  * used by WARN_RETURN_STATUS_IF_ERR et al., which wrap function calls and automatically
334  * raise warnings and return to the caller.
335  **/
336 #define DEBUG_WARN_ERR(status)\
337  do\
338  {\
339  static atomic_bool suppress__;\
340  switch(debug_OnError(status, &suppress__, WIDEN(__FILE__), __LINE__, __func__))\
341  {\
342  case ER_CONTINUE:\
343  break;\
344  case ER_BREAK:\
345  default:\
346  debug_break();\
347  break;\
348  }\
349  }\
350  while(0)
351 
352 /**
353  * called when a ENSURE/ASSERT fails;
354  * notifies the user via debug_DisplayError.
355  *
356  * @param assert_expr the expression that failed; typically passed as
357  * \#expr in the assert macro.
358  * @param suppress see debug_DisplayError.
359  * @param file, line source file name and line number of the spot that failed
360  * @param func name of the function containing it
361  * @return ErrorReaction (user's choice: continue running or stop?)
362  **/
363 LIB_API ErrorReaction debug_OnAssertionFailure(const wchar_t* assert_expr, atomic_bool* suppress, const wchar_t* file, int line, const char* func) ANALYZER_NORETURN;
364 
365 /**
366  * called when a DEBUG_WARN_ERR indicates an error occurred;
367  * notifies the user via debug_DisplayError.
368  *
369  * @param err Status value indicating the error that occurred
370  * @param suppress see debug_DisplayError.
371  * @param file, line source file name and line number of the spot that failed
372  * @param func name of the function containing it
373  * @return ErrorReaction (user's choice: continue running or stop?)
374  **/
375 LIB_API ErrorReaction debug_OnError(Status err, atomic_bool* suppress, const wchar_t* file, int line, const char* func) ANALYZER_NORETURN;
376 
377 
378 /**
379  * suppress (prevent from showing) the error dialog from subsequent
380  * debug_OnError for the given Status.
381  *
382  * rationale: for edge cases in some functions, warnings are raised in
383  * addition to returning an error code. self-tests deliberately trigger
384  * these cases and check for the latter but shouldn't cause the former.
385  * we therefore need to squelch them.
386  *
387  * @param err the Status to skip.
388  *
389  * note: only one concurrent skip request is allowed; call
390  * debug_StopSkippingErrors before the next debug_SkipErrors.
391  */
392 LIB_API void debug_SkipErrors(Status err);
393 
394 /**
395  * @return how many errors were skipped since the call to debug_SkipErrors()
396  **/
397 LIB_API size_t debug_StopSkippingErrors();
398 
399 
400 //-----------------------------------------------------------------------------
401 // symbol access
402 //-----------------------------------------------------------------------------
403 
404 namespace ERR
405 {
408  const Status SYM_UNRETRIEVABLE = -100402;
410  const Status SYM_INTERNAL_ERROR = -100404;
411  const Status SYM_UNSUPPORTED = -100405;
412  const Status SYM_CHILD_NOT_FOUND = -100406;
413  // this limit is to prevent infinite recursion.
414  const Status SYM_NESTING_LIMIT = -100407;
415  // this limit is to prevent large symbols (e.g. arrays or linked lists)
416  // from taking up all available output space.
418 }
419 
420 namespace INFO
421 {
422  // one of the dump_sym* functions decided not to output anything at
423  // all (e.g. for member functions in UDTs - we don't want those).
424  // therefore, skip any post-symbol formatting (e.g. ) as well.
425  const Status SYM_SUPPRESS_OUTPUT = +100409;
426 }
427 
428 
429 /**
430  * Maximum number of characters (including null terminator) written to
431  * user's buffers by debug_ResolveSymbol.
432  **/
433 static const size_t DEBUG_SYMBOL_CHARS = 1000;
434 static const size_t DEBUG_FILE_CHARS = 100;
435 
436 /**
437  * read and return symbol information for the given address.
438  *
439  * NOTE: the PDB implementation is rather slow (~500 us).
440  *
441  * @param ptr_of_interest address of symbol (e.g. function, variable)
442  * @param sym_name optional out; holds at least DEBUG_SYMBOL_CHARS;
443  * receives symbol name returned via debug info.
444  * @param file optional out; holds at least DEBUG_FILE_CHARS;
445  * receives base name only (no path; see rationale in wdbg_sym) of
446  * source file containing the symbol.
447  * @param line optional out; receives source file line number of symbol.
448  *
449  * note: all of the output parameters are optional; we pass back as much
450  * information as is available and desired.
451  * @return Status; INFO::OK iff any information was successfully
452  * retrieved and stored.
453  **/
454 LIB_API Status debug_ResolveSymbol(void* ptr_of_interest, wchar_t* sym_name, wchar_t* file, int* line);
455 
456 static const size_t DEBUG_CONTEXT_SIZE = 2048; // Win32 CONTEXT is currently 1232 bytes
457 
458 /**
459  * @param context must point to an instance of the platform-specific type
460  * (e.g. CONTEXT) or CACHE_ALIGNED storage of DEBUG_CONTEXT_SIZE bytes.
461  **/
462 LIB_API Status debug_CaptureContext(void* context);
463 
464 
465 /**
466  * write a complete stack trace (including values of local variables) into
467  * the specified buffer.
468  *
469  * @param buf Target buffer.
470  * @param maxChars Max chars of buffer (should be several thousand).
471  * @param context Platform-specific representation of execution state
472  * (e.g. Win32 CONTEXT). either specify an SEH exception's
473  * context record or use debug_CaptureContext to retrieve the current state.
474  * Rationale: intermediates such as debug_DisplayError change the
475  * context, so it should be captured as soon as possible.
476  * @param lastFuncToSkip Is used for omitting error-reporting functions like
477  * debug_OnAssertionFailure from the stack trace. It is either 0 (skip nothing) or
478  * a substring of a function's name (this allows platform-independent
479  * matching of stdcall-decorated names).
480  * Rationale: this is safer than specifying a fixed number of frames,
481  * which can be incorrect due to inlining.
482  * @return Status; ERR::REENTERED if reentered via recursion or
483  * multithreading (not allowed since static data is used).
484  **/
485 LIB_API Status debug_DumpStack(wchar_t* buf, size_t maxChars, void* context, const wchar_t* lastFuncToSkip);
486 
487 
488 //-----------------------------------------------------------------------------
489 // helper functions (used by implementation)
490 //-----------------------------------------------------------------------------
491 
492 /**
493  * [system-dependent] write a string to the debug channel.
494  * this can be quite slow (~1 ms)! On Windows, it uses OutputDebugString
495  * (entails context switch), otherwise stdout+fflush (waits for IO).
496  **/
497 LIB_API void debug_puts(const char* text);
498 
499 /**
500  * return the caller of a certain function on the call stack.
501  *
502  * this function is useful for recording (partial) stack traces for
503  * memory allocation tracking, etc.
504  *
505  * @param context, lastFuncToSkip - see debug_DumpStack
506  * @return address of the caller
507  **/
508 LIB_API void* debug_GetCaller(void* context, const wchar_t* lastFuncToSkip);
509 
510 /**
511  * check if a pointer appears to be totally invalid.
512  *
513  * this check is not authoritative (the pointer may be "valid" but incorrect)
514  * but can be used to filter out obviously wrong values in a portable manner.
515  *
516  * @param p pointer
517  * @return 1 if totally bogus, otherwise 0.
518  **/
519 LIB_API int debug_IsPointerBogus(const void* p);
520 
521 /// does the given pointer appear to point to code?
522 LIB_API bool debug_IsCodePointer(void* p);
523 
524 /// does the given pointer appear to point to the stack?
525 LIB_API bool debug_IsStackPointer(void* p);
526 
527 
528 /**
529  * inform the debugger of the current thread's name.
530  *
531  * (threads are easier to keep apart when they are identified by
532  * name rather than TID.)
533  **/
534 LIB_API void debug_SetThreadName(const char* name);
535 
536 
537 /**
538  * holds memory for an error message.
539  **/
541 {
542  // rationale:
543  // - error messages with stack traces require a good deal of memory
544  // (hundreds of KB). static buffers of that size are undesirable.
545  // - the heap may be corrupted, so don't use malloc.
546  // instead, "lib/sysdep/vm.h" functions should be safe.
547  // - alloca is a bit iffy (the stack may be maxed out), non-portable and
548  // complicates the code because it can't be allocated by a subroutine.
549  // - this method is probably slow, but error messages aren't built often.
550  // if necessary, first try malloc and use mmap if that fails.
551  void* pa_mem;
552 };
553 
554 /**
555  * free memory from the error message.
556  *
557  * @param emm ErrorMessageMem*
558  **/
559 LIB_API void debug_FreeErrorMessage(ErrorMessageMem* emm);
560 
561 /**
562  * build a string describing the given error.
563  *
564  * this is a helper function used by debug_DumpStack and is made available
565  * so that the self-test doesn't have to display the error dialog.
566  *
567  * @param description: general description of the problem.
568  * @param fn_only filename (no path) of source file that triggered the error.
569  * @param line, func: exact position of the error.
570  * @param context, lastFuncToSkip: see debug_DumpStack.
571  * @param emm memory for the error message. caller should allocate
572  * stack memory and set alloc_buf*; if not, there will be no
573  * fallback in case heap alloc fails. should be freed via
574  * debug_FreeErrorMessage when no longer needed.
575  **/
576 LIB_API const wchar_t* debug_BuildErrorMessage(const wchar_t* description, const wchar_t* fn_only, int line, const char* func, void* context, const wchar_t* lastFuncToSkip, ErrorMessageMem* emm);
577 
578 #endif // #ifndef INCLUDED_DEBUG
LIB_API Status debug_WriteCrashlog(const char *text)
write an error description and all logs into crashlog.txt (in unicode format).
LIB_API ErrorReaction debug_DisplayError(const wchar_t *description, size_t flags, void *context, const wchar_t *lastFuncToSkip, const wchar_t *file, int line, const char *func, atomic_bool *suppress)
display an error dialog with a message and stack trace.
Definition: debug.cpp:431
const Status SYM_UNSUPPORTED
Definition: debug.h:411
static const size_t DEBUG_SYMBOL_CHARS
Maximum number of characters (including null terminator) written to user&#39;s buffers by debug_ResolveSy...
Definition: debug.h:433
LIB_API void debug_puts_filtered(const char *text)
call debug_puts if debug_filter_allows allows the string.
Definition: debug.cpp:156
DebugDisplayErrorFlags
flags to customize debug_DisplayError behavior
Definition: debug.h:81
const Status SYM_SUPPRESS_OUTPUT
Definition: debug.h:425
#define ANALYZER_NORETURN
mark a function as noreturn for static analyzer purposes.
Definition: code_annotation.h:97
enable the Suppress button.
Definition: debug.h:96
LIB_API bool debug_IsCodePointer(void *p)
does the given pointer appear to point to code?
Definition: wdbg.cpp:62
special return value for the display_error app hook stub to indicate that it has done nothing and tha...
Definition: debug.h:175
LIB_API void debug_SkipErrors(Status err)
suppress (prevent from showing) the error dialog from subsequent debug_OnError for the given Status...
Definition: debug.cpp:496
LIB_API void debug_puts(const char *text)
[system-dependent] write a string to the debug channel.
Definition: udbg.cpp:102
LIB_API ErrorReaction debug_OnAssertionFailure(const wchar_t *assert_expr, atomic_bool *suppress, const wchar_t *file, int line, const char *func) ANALYZER_NORETURN
called when a ENSURE/ASSERT fails; notifies the user via debug_DisplayError.
Definition: debug.cpp:555
ErrorReaction
choices offered by the error dialog that are returned by debug_DisplayError.
Definition: debug.h:131
const Status SYM_CHILD_NOT_FOUND
Definition: debug.h:412
#define PRINTF_ARGS(fmtpos)
Definition: code_annotation.h:243
trigger breakpoint, i.e.
Definition: debug.h:145
Definition: debug.h:420
const Status SYM_UNRETRIEVABLE_STATIC
Definition: debug.h:407
LIB_API bool debug_filter_allows(const char *text)
indicate if the given text would be printed.
Definition: debug.cpp:119
LIB_API void debug_SetThreadName(const char *name)
inform the debugger of the current thread&#39;s name.
Definition: bdbg.cpp:126
LIB_API void debug_FreeErrorMessage(ErrorMessageMem *emm)
free memory from the error message.
Definition: debug.cpp:214
LIB_API Status debug_CaptureContext(void *context)
Definition: udbg.cpp:42
const Status SYM_UNRETRIEVABLE
Definition: debug.h:408
exit the program immediately.
Definition: debug.h:168
volatile intptr_t atomic_bool
a bool that is reasonably certain to be set atomically.
Definition: debug.h:117
LIB_API int debug_IsPointerBogus(const void *p)
check if a pointer appears to be totally invalid.
Definition: udbg.cpp:110
LIB_API void debug_filter_remove(const char *tag)
in future, discard output with the given tag.
Definition: debug.cpp:96
const Status SYM_NO_STACK_FRAMES_FOUND
Definition: debug.h:406
display just the given message; do not add any information about the call stack, do not write crashlo...
Definition: debug.h:109
static const atomic_bool DEBUG_SUPPRESS
value for suppress flag once set by debug_DisplayError.
Definition: debug.h:125
LIB_API ErrorReaction debug_OnError(Status err, atomic_bool *suppress, const wchar_t *file, int line, const char *func) ANALYZER_NORETURN
called when a DEBUG_WARN_ERR indicates an error occurred; notifies the user via debug_DisplayError.
Definition: debug.cpp:539
LIB_API void debug_DisplayMessage(const wchar_t *caption, const wchar_t *msg)
translates and displays the given strings in a dialog.
Definition: debug.cpp:349
LIB_API bool debug_IsStackPointer(void *p)
does the given pointer appear to point to the stack?
Definition: wdbg.cpp:77
static const size_t DEBUG_FILE_CHARS
Definition: debug.h:434
Definition: debug.h:157
const Status SYM_TYPE_INFO_UNAVAILABLE
Definition: debug.h:409
LIB_API void * debug_GetCaller(void *context, const wchar_t *lastFuncToSkip)
return the caller of a certain function on the call stack.
Definition: bdbg.cpp:38
i64 Status
Error handling system.
Definition: status.h:171
void debug_break()
trigger a breakpoint when reached/"called".
Definition: udbg.cpp:48
LIB_API size_t debug_StopSkippingErrors()
Definition: debug.cpp:509
disallow the Continue button.
Definition: debug.h:86
do not trigger a breakpoint inside debug_DisplayError; caller will take care of this if ER_BREAK is r...
Definition: debug.h:103
Introduction
Definition: debug.h:404
ignore and do not report again.
Definition: debug.h:163
LIB_API const wchar_t * debug_BuildErrorMessage(const wchar_t *description, const wchar_t *fn_only, int line, const char *func, void *context, const wchar_t *lastFuncToSkip, ErrorMessageMem *emm)
build a string describing the given error.
Definition: debug.cpp:267
LIB_API void debug_filter_add(const char *tag)
debug output is very useful, but "too much of a good thing can kill you".
Definition: debug.cpp:77
void * pa_mem
Definition: debug.h:551
const Status SYM_INTERNAL_ERROR
Definition: debug.h:410
holds memory for an error message.
Definition: debug.h:540
static const size_t DEBUG_CONTEXT_SIZE
Definition: debug.h:456
LIB_API Status debug_ResolveSymbol(void *ptr_of_interest, wchar_t *sym_name, wchar_t *file, int *line)
read and return symbol information for the given address.
Definition: bdbg.cpp:99
Definition: format.h:119
const Status SYM_NESTING_LIMIT
Definition: debug.h:414
const Status SYM_SINGLE_SYMBOL_LIMIT
Definition: debug.h:417
LIB_API void debug_filter_clear()
clear all filter state; equivalent to debug_filter_remove for each tag that was debug_filter_add-ed.
Definition: debug.cpp:114
LIB_API void debug_printf(const char *fmt,...) PRINTF_ARGS(1)
write a formatted string to the debug channel, subject to filtering (see below).
Definition: debug.cpp:142
ignore, continue as if nothing happened.
Definition: debug.h:138
LIB_API Status debug_DumpStack(wchar_t *buf, size_t maxChars, void *context, const wchar_t *lastFuncToSkip)
write a complete stack trace (including values of local variables) into the specified buffer...
Definition: bdbg.cpp:52
ErrorReactionInternal
all choices offered by the error dialog.
Definition: debug.h:154
Definition: debug.h:156