Pyrogenesis  13997
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
debug.h
Go to the documentation of this file.
1 /* Copyright (c) 2010 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 wchar_t* fmt, ...) WPRINTF_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 wchar_t* 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 wchar_t* 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 wchar_t* text);
255 
256 /**
257  * write an error description and all logs into crashlog.txt
258  * (in unicode format).
259  *
260  * @param text description of the error (including stack trace);
261  * typically generated by debug_BuildErrorMessage.
262  *
263  * @return Status; ERR::REENTERED if reentered via recursion or
264  * multithreading (not allowed since an infinite loop may result).
265  **/
266 LIB_API Status debug_WriteCrashlog(const wchar_t* text);
267 
268 
269 //-----------------------------------------------------------------------------
270 // assertions
271 //-----------------------------------------------------------------------------
272 
273 /**
274  * ensure the expression <expr> evaluates to non-zero. used to validate
275  * invariants in the program during development and thus gives a
276  * very helpful warning if something isn't going as expected.
277  * sprinkle these liberally throughout your code!
278  *
279  * to pass more information to users at runtime, you can write
280  * ENSURE(expression && "descriptive string").
281  **/
282 #define ENSURE(expr)\
283  do\
284  {\
285  static atomic_bool suppress__;\
286  if(!(expr))\
287  {\
288  switch(debug_OnAssertionFailure(WIDEN(#expr), &suppress__, WIDEN(__FILE__), __LINE__, __func__))\
289  {\
290  case ER_CONTINUE:\
291  break;\
292  case ER_BREAK:\
293  default:\
294  debug_break();\
295  break;\
296  }\
297  }\
298  }\
299  while(0)
300 
301 /**
302  * same as ENSURE in debug mode, does nothing in release mode.
303  * (we don't override the `assert' macro because users may
304  * inadvertently include <assert.h> afterwards)
305  * (we do not provide an MFC-style VERIFY macro because the distinction
306  * between ENSURE and VERIFY is unclear. to always run code but only
307  * check for success in debug builds without raising unused-variable warnings,
308  * use ASSERT + UNUSED2.)
309  **/
310 #define ASSERT(expr) ENSURE(expr)
311 #ifdef NDEBUG
312 # undef ASSERT
313 # define ASSERT(expr)
314 #endif
315 
316 /**
317  * display the error dialog with the given text. this is less error-prone than
318  * ENSURE(0 && "text"). note that "conditional expression is constant" warnings
319  * are disabled anyway.
320  *
321  * if being able to suppress the warning is desirable (e.g. for self-tests),
322  * then use DEBUG_WARN_ERR instead.
323  **/
324 #define debug_warn(expr) ENSURE(0 && (expr))
325 
326 /**
327  * display the error dialog with text corresponding to the given error code.
328  * used by WARN_RETURN_STATUS_IF_ERR et al., which wrap function calls and automatically
329  * raise warnings and return to the caller.
330  **/
331 #define DEBUG_WARN_ERR(status)\
332  do\
333  {\
334  static atomic_bool suppress__;\
335  switch(debug_OnError(status, &suppress__, WIDEN(__FILE__), __LINE__, __func__))\
336  {\
337  case ER_CONTINUE:\
338  break;\
339  case ER_BREAK:\
340  default:\
341  debug_break();\
342  break;\
343  }\
344  }\
345  while(0)
346 
347 /**
348  * called when a ENSURE/ASSERT fails;
349  * notifies the user via debug_DisplayError.
350  *
351  * @param assert_expr the expression that failed; typically passed as
352  * \#expr in the assert macro.
353  * @param suppress see debug_DisplayError.
354  * @param file, line source file name and line number of the spot that failed
355  * @param func name of the function containing it
356  * @return ErrorReaction (user's choice: continue running or stop?)
357  **/
358 LIB_API ErrorReaction debug_OnAssertionFailure(const wchar_t* assert_expr, atomic_bool* suppress, const wchar_t* file, int line, const char* func);
359 
360 /**
361  * called when a DEBUG_WARN_ERR indicates an error occurred;
362  * notifies the user via debug_DisplayError.
363  *
364  * @param err Status value indicating the error that occurred
365  * @param suppress see debug_DisplayError.
366  * @param file, line source file name and line number of the spot that failed
367  * @param func name of the function containing it
368  * @return ErrorReaction (user's choice: continue running or stop?)
369  **/
370 LIB_API ErrorReaction debug_OnError(Status err, atomic_bool* suppress, const wchar_t* file, int line, const char* func);
371 
372 
373 /**
374  * suppress (prevent from showing) the error dialog from subsequent
375  * debug_OnError for the given Status.
376  *
377  * rationale: for edge cases in some functions, warnings are raised in
378  * addition to returning an error code. self-tests deliberately trigger
379  * these cases and check for the latter but shouldn't cause the former.
380  * we therefore need to squelch them.
381  *
382  * @param err the Status to skip.
383  *
384  * note: only one concurrent skip request is allowed; call
385  * debug_StopSkippingErrors before the next debug_SkipErrors.
386  */
387 LIB_API void debug_SkipErrors(Status err);
388 
389 /**
390  * @return how many errors were skipped since the call to debug_SkipErrors()
391  **/
392 LIB_API size_t debug_StopSkippingErrors();
393 
394 
395 //-----------------------------------------------------------------------------
396 // symbol access
397 //-----------------------------------------------------------------------------
398 
399 namespace ERR
400 {
403  const Status SYM_UNRETRIEVABLE = -100402;
405  const Status SYM_INTERNAL_ERROR = -100404;
406  const Status SYM_UNSUPPORTED = -100405;
407  const Status SYM_CHILD_NOT_FOUND = -100406;
408  // this limit is to prevent infinite recursion.
409  const Status SYM_NESTING_LIMIT = -100407;
410  // this limit is to prevent large symbols (e.g. arrays or linked lists)
411  // from taking up all available output space.
413 }
414 
415 namespace INFO
416 {
417  // one of the dump_sym* functions decided not to output anything at
418  // all (e.g. for member functions in UDTs - we don't want those).
419  // therefore, skip any post-symbol formatting (e.g. ) as well.
420  const Status SYM_SUPPRESS_OUTPUT = +100409;
421 }
422 
423 
424 /**
425  * Maximum number of characters (including null terminator) written to
426  * user's buffers by debug_ResolveSymbol.
427  **/
428 static const size_t DEBUG_SYMBOL_CHARS = 1000;
429 static const size_t DEBUG_FILE_CHARS = 100;
430 
431 /**
432  * read and return symbol information for the given address.
433  *
434  * NOTE: the PDB implementation is rather slow (~500 us).
435  *
436  * @param ptr_of_interest address of symbol (e.g. function, variable)
437  * @param sym_name optional out; holds at least DEBUG_SYMBOL_CHARS;
438  * receives symbol name returned via debug info.
439  * @param file optional out; holds at least DEBUG_FILE_CHARS;
440  * receives base name only (no path; see rationale in wdbg_sym) of
441  * source file containing the symbol.
442  * @param line optional out; receives source file line number of symbol.
443  *
444  * note: all of the output parameters are optional; we pass back as much
445  * information as is available and desired.
446  * @return Status; INFO::OK iff any information was successfully
447  * retrieved and stored.
448  **/
449 LIB_API Status debug_ResolveSymbol(void* ptr_of_interest, wchar_t* sym_name, wchar_t* file, int* line);
450 
451 static const size_t DEBUG_CONTEXT_SIZE = 2048; // Win32 CONTEXT is currently 1232 bytes
452 
453 /**
454  * @param context must point to an instance of the platform-specific type
455  * (e.g. CONTEXT) or CACHE_ALIGNED storage of DEBUG_CONTEXT_SIZE bytes.
456  **/
457 LIB_API Status debug_CaptureContext(void* context);
458 
459 
460 /**
461  * write a complete stack trace (including values of local variables) into
462  * the specified buffer.
463  *
464  * @param buf Target buffer.
465  * @param maxChars Max chars of buffer (should be several thousand).
466  * @param context Platform-specific representation of execution state
467  * (e.g. Win32 CONTEXT). either specify an SEH exception's
468  * context record or use debug_CaptureContext to retrieve the current state.
469  * Rationale: intermediates such as debug_DisplayError change the
470  * context, so it should be captured as soon as possible.
471  * @param lastFuncToSkip Is used for omitting error-reporting functions like
472  * debug_OnAssertionFailure from the stack trace. It is either 0 (skip nothing) or
473  * a substring of a function's name (this allows platform-independent
474  * matching of stdcall-decorated names).
475  * Rationale: this is safer than specifying a fixed number of frames,
476  * which can be incorrect due to inlining.
477  * @return Status; ERR::REENTERED if reentered via recursion or
478  * multithreading (not allowed since static data is used).
479  **/
480 LIB_API Status debug_DumpStack(wchar_t* buf, size_t maxChars, void* context, const wchar_t* lastFuncToSkip);
481 
482 
483 //-----------------------------------------------------------------------------
484 // helper functions (used by implementation)
485 //-----------------------------------------------------------------------------
486 
487 /**
488  * [system-dependent] write a string to the debug channel.
489  * this can be quite slow (~1 ms)! On Windows, it uses OutputDebugString
490  * (entails context switch), otherwise stdout+fflush (waits for IO).
491  **/
492 LIB_API void debug_puts(const wchar_t* text);
493 
494 /**
495  * return the caller of a certain function on the call stack.
496  *
497  * this function is useful for recording (partial) stack traces for
498  * memory allocation tracking, etc.
499  *
500  * @param context, lastFuncToSkip - see debug_DumpStack
501  * @return address of the caller
502  **/
503 LIB_API void* debug_GetCaller(void* context, const wchar_t* lastFuncToSkip);
504 
505 /**
506  * check if a pointer appears to be totally invalid.
507  *
508  * this check is not authoritative (the pointer may be "valid" but incorrect)
509  * but can be used to filter out obviously wrong values in a portable manner.
510  *
511  * @param p pointer
512  * @return 1 if totally bogus, otherwise 0.
513  **/
514 LIB_API int debug_IsPointerBogus(const void* p);
515 
516 /// does the given pointer appear to point to code?
517 LIB_API bool debug_IsCodePointer(void* p);
518 
519 /// does the given pointer appear to point to the stack?
520 LIB_API bool debug_IsStackPointer(void* p);
521 
522 
523 /**
524  * inform the debugger of the current thread's name.
525  *
526  * (threads are easier to keep apart when they are identified by
527  * name rather than TID.)
528  **/
529 LIB_API void debug_SetThreadName(const char* name);
530 
531 
532 /**
533  * holds memory for an error message.
534  **/
536 {
537  // rationale:
538  // - error messages with stack traces require a good deal of memory
539  // (hundreds of KB). static buffers of that size are undesirable.
540  // - the heap may be corrupted, so don't use malloc.
541  // instead, "lib/sysdep/vm.h" functions should be safe.
542  // - alloca is a bit iffy (the stack may be maxed out), non-portable and
543  // complicates the code because it can't be allocated by a subroutine.
544  // - this method is probably slow, but error messages aren't built often.
545  // if necessary, first try malloc and use mmap if that fails.
546  void* pa_mem;
547 };
548 
549 /**
550  * free memory from the error message.
551  *
552  * @param emm ErrorMessageMem*
553  **/
554 LIB_API void debug_FreeErrorMessage(ErrorMessageMem* emm);
555 
556 /**
557  * build a string describing the given error.
558  *
559  * this is a helper function used by debug_DumpStack and is made available
560  * so that the self-test doesn't have to display the error dialog.
561  *
562  * @param description: general description of the problem.
563  * @param fn_only filename (no path) of source file that triggered the error.
564  * @param line, func: exact position of the error.
565  * @param context, lastFuncToSkip: see debug_DumpStack.
566  * @param emm memory for the error message. caller should allocate
567  * stack memory and set alloc_buf*; if not, there will be no
568  * fallback in case heap alloc fails. should be freed via
569  * debug_FreeErrorMessage when no longer needed.
570  **/
571 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);
572 
573 #endif // #ifndef INCLUDED_DEBUG
LIB_API void debug_puts(const wchar_t *text)
[system-dependent] write a string to the debug channel.
Definition: udbg.cpp:106
const wchar_t * debug_BuildErrorMessage(const wchar_t *description, const wchar_t *filename, int line, const char *func, void *context, const wchar_t *lastFuncToSkip, ErrorMessageMem *emm)
build a string describing the given error.
Definition: debug.cpp:262
const Status SYM_UNSUPPORTED
Definition: debug.h:406
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:428
DebugDisplayErrorFlags
flags to customize debug_DisplayError behavior
Definition: debug.h:81
const Status SYM_SUPPRESS_OUTPUT
Definition: debug.h:420
ErrorReaction debug_DisplayError(const wchar_t *description, size_t flags, void *context, const wchar_t *lastFuncToSkip, const wchar_t *pathname, int line, const char *func, atomic_bool *suppress)
display an error dialog with a message and stack trace.
Definition: debug.cpp:426
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
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:407
trigger breakpoint, i.e.
Definition: debug.h:145
Status debug_WriteCrashlog(const wchar_t *text)
write an error description and all logs into crashlog.txt (in unicode format).
Definition: debug.cpp:160
const Status SYM_UNRETRIEVABLE_STATIC
Definition: debug.h:402
LIB_API void debug_SetThreadName(const char *name)
inform the debugger of the current thread&#39;s name.
Definition: bdbg.cpp:126
LIB_API Status debug_CaptureContext(void *context)
Definition: udbg.cpp:42
const Status SYM_UNRETRIEVABLE
Definition: debug.h:403
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:114
const Status SYM_NO_STACK_FRAMES_FOUND
Definition: debug.h:401
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
bool debug_filter_allows(const wchar_t *text)
indicate if the given text would be printed.
Definition: debug.cpp:119
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
void debug_DisplayMessage(const wchar_t *caption, const wchar_t *msg)
translates and displays the given strings in a dialog.
Definition: debug.cpp:344
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:429
void debug_filter_add(const wchar_t *tag)
debug output is very useful, but &quot;too much of a good thing can kill you&quot;.
Definition: debug.cpp:77
const Status SYM_TYPE_INFO_UNAVAILABLE
Definition: debug.h:404
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/&quot;called&quot;.
Definition: udbg.cpp:48
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
#define WPRINTF_ARGS(fmtpos)
ignore and do not report again.
Definition: debug.h:163
void debug_FreeErrorMessage(ErrorMessageMem *emm)
free memory from the error message.
Definition: debug.cpp:209
ErrorReaction debug_OnError(Status err, atomic_bool *suppress, const wchar_t *file, int line, const char *func)
called when a DEBUG_WARN_ERR indicates an error occurred; notifies the user via debug_DisplayError.
Definition: debug.cpp:534
void * pa_mem
Definition: debug.h:546
const Status SYM_INTERNAL_ERROR
Definition: debug.h:405
holds memory for an error message.
Definition: debug.h:535
size_t debug_StopSkippingErrors()
Definition: debug.cpp:504
static const size_t DEBUG_CONTEXT_SIZE
Definition: debug.h:451
void debug_filter_remove(const wchar_t *tag)
in future, discard output with the given tag.
Definition: debug.cpp:96
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
const Status SYM_NESTING_LIMIT
Definition: debug.h:409
const Status SYM_SINGLE_SYMBOL_LIMIT
Definition: debug.h:412
ErrorReaction debug_OnAssertionFailure(const wchar_t *expr, atomic_bool *suppress, const wchar_t *file, int line, const char *func)
called when a ENSURE/ASSERT fails; notifies the user via debug_DisplayError.
Definition: debug.cpp:550
void debug_printf(const wchar_t *fmt,...)
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
void debug_SkipErrors(Status err)
suppress (prevent from showing) the error dialog from subsequent debug_OnError for the given Status...
Definition: debug.cpp:491