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