Pyrogenesis  13997
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Classes | Namespaces | Macros | Typedefs | Enumerations | Functions | Variables
debug.h File Reference
#include "lib/lib_api.h"
#include "lib/types.h"
#include "lib/status.h"
#include "lib/alignment.h"
#include "lib/code_annotation.h"
#include "lib/code_generation.h"

Go to the source code of this file.

Classes

struct  ErrorMessageMem
 holds memory for an error message. More...
 

Namespaces

 ERR
 

Introduction


 
 INFO
 

Macros

#define DEBUG_DISPLAY_ERROR(description)
 
#define ENSURE(expr)
 ensure the expression <expr> evaluates to non-zero. More...
 
#define ASSERT(expr)   ENSURE(expr)
 same as ENSURE in debug mode, does nothing in release mode. More...
 
#define debug_warn(expr)   ENSURE(0 && (expr))
 display the error dialog with the given text. More...
 
#define DEBUG_WARN_ERR(status)
 display the error dialog with text corresponding to the given error code. More...
 

Typedefs

typedef volatile intptr_t atomic_bool
 a bool that is reasonably certain to be set atomically. More...
 

Enumerations

enum  DebugDisplayErrorFlags { DE_NO_CONTINUE = 1, DE_ALLOW_SUPPRESS = 2, DE_MANUAL_BREAK = 4, DE_NO_DEBUG_INFO = 8 }
 flags to customize debug_DisplayError behavior More...
 
enum  ErrorReaction { ER_CONTINUE = 1, ER_BREAK }
 choices offered by the error dialog that are returned by debug_DisplayError. More...
 
enum  ErrorReactionInternal {
  ERI_CONTINUE = ER_CONTINUE, ERI_BREAK = ER_BREAK, ERI_SUPPRESS, ERI_EXIT,
  ERI_NOT_IMPLEMENTED
}
 all choices offered by the error dialog. More...
 

Functions

void debug_break ()
 trigger a breakpoint when reached/"called". More...
 
LIB_API void debug_printf (const wchar_t *fmt,...) WPRINTF_ARGS(1)
 write a formatted string to the debug channel, subject to filtering (see below). More...
 
LIB_API void debug_DisplayMessage (const wchar_t *caption, const wchar_t *msg)
 translates and displays the given strings in a dialog. More...
 
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. More...
 
LIB_API void debug_filter_add (const wchar_t *tag)
 debug output is very useful, but "too much of a good thing can kill you". More...
 
LIB_API void debug_filter_remove (const wchar_t *tag)
 in future, discard output with the given tag. More...
 
LIB_API void debug_filter_clear ()
 clear all filter state; equivalent to debug_filter_remove for each tag that was debug_filter_add-ed. More...
 
LIB_API bool debug_filter_allows (const wchar_t *text)
 indicate if the given text would be printed. More...
 
LIB_API Status debug_WriteCrashlog (const wchar_t *text)
 write an error description and all logs into crashlog.txt (in unicode format). More...
 
LIB_API ErrorReaction debug_OnAssertionFailure (const wchar_t *assert_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. More...
 
LIB_API 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. More...
 
LIB_API void debug_SkipErrors (Status err)
 suppress (prevent from showing) the error dialog from subsequent debug_OnError for the given Status. More...
 
LIB_API size_t debug_StopSkippingErrors ()
 
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. More...
 
LIB_API Status debug_CaptureContext (void *context)
 
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. More...
 
LIB_API void debug_puts (const wchar_t *text)
 [system-dependent] write a string to the debug channel. More...
 
LIB_API void * debug_GetCaller (void *context, const wchar_t *lastFuncToSkip)
 return the caller of a certain function on the call stack. More...
 
LIB_API int debug_IsPointerBogus (const void *p)
 check if a pointer appears to be totally invalid. More...
 
LIB_API bool debug_IsCodePointer (void *p)
 does the given pointer appear to point to code? More...
 
LIB_API bool debug_IsStackPointer (void *p)
 does the given pointer appear to point to the stack? More...
 
LIB_API void debug_SetThreadName (const char *name)
 inform the debugger of the current thread's name. More...
 
LIB_API void debug_FreeErrorMessage (ErrorMessageMem *emm)
 free memory from the error message. More...
 
LIB_API const wchar_tdebug_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. More...
 

Variables

static const atomic_bool DEBUG_SUPPRESS = 0xAB
 value for suppress flag once set by debug_DisplayError. More...
 
const Status ERR::SYM_NO_STACK_FRAMES_FOUND = -100400
 
const Status ERR::SYM_UNRETRIEVABLE_STATIC = -100401
 
const Status ERR::SYM_UNRETRIEVABLE = -100402
 
const Status ERR::SYM_TYPE_INFO_UNAVAILABLE = -100403
 
const Status ERR::SYM_INTERNAL_ERROR = -100404
 
const Status ERR::SYM_UNSUPPORTED = -100405
 
const Status ERR::SYM_CHILD_NOT_FOUND = -100406
 
const Status ERR::SYM_NESTING_LIMIT = -100407
 
const Status ERR::SYM_SINGLE_SYMBOL_LIMIT = -100408
 
const Status INFO::SYM_SUPPRESS_OUTPUT = +100409
 
static const size_t DEBUG_SYMBOL_CHARS = 1000
 Maximum number of characters (including null terminator) written to user's buffers by debug_ResolveSymbol. More...
 
static const size_t DEBUG_FILE_CHARS = 100
 
static const size_t DEBUG_CONTEXT_SIZE = 2048
 

Macro Definition Documentation

#define ASSERT (   expr)    ENSURE(expr)

same as ENSURE in debug mode, does nothing in release mode.

(we don't override the `assert' macro because users may inadvertently include <assert.h> afterwards) (we do not provide an MFC-style VERIFY macro because the distinction between ENSURE and VERIFY is unclear. to always run code but only check for success in debug builds without raising unused-variable warnings, use ASSERT + UNUSED2.)

Definition at line 310 of file debug.h.

#define DEBUG_DISPLAY_ERROR (   description)
Value:
do\
{\
(void)debug_CaptureContext(context);\
(void)debug_DisplayError(description, 0, context, L"debug_DisplayError", WIDEN(__FILE__), __LINE__, __func__, 0);\
}\
while(0)
#define u8
Definition: types.h:39
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
LIB_API Status debug_CaptureContext(void *context)
Definition: udbg.cpp:42
#define WIDEN(x)
static const size_t DEBUG_CONTEXT_SIZE
Definition: debug.h:451
#define CACHE_ALIGNED(type)
Definition: alignment.h:52
#define __func__

Definition at line 197 of file debug.h.

#define debug_warn (   expr)    ENSURE(0 && (expr))

display the error dialog with the given text.

this is less error-prone than ENSURE(0 && "text"). note that "conditional expression is constant" warnings are disabled anyway.

if being able to suppress the warning is desirable (e.g. for self-tests), then use DEBUG_WARN_ERR instead.

Definition at line 324 of file debug.h.

#define DEBUG_WARN_ERR (   status)
Value:
do\
{\
static atomic_bool suppress__;\
switch(debug_OnError(status, &suppress__, WIDEN(__FILE__), __LINE__, __func__))\
{\
case ER_CONTINUE:\
break;\
case ER_BREAK:\
default:\
break;\
}\
}\
while(0)
trigger breakpoint, i.e.
Definition: debug.h:145
#define WIDEN(x)
volatile intptr_t atomic_bool
a bool that is reasonably certain to be set atomically.
Definition: debug.h:117
void debug_break()
trigger a breakpoint when reached/&quot;called&quot;.
Definition: udbg.cpp:48
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
#define __func__
ignore, continue as if nothing happened.
Definition: debug.h:138

display the error dialog with text corresponding to the given error code.

used by WARN_RETURN_STATUS_IF_ERR et al., which wrap function calls and automatically raise warnings and return to the caller.

Definition at line 331 of file debug.h.

#define ENSURE (   expr)
Value:
do\
{\
static atomic_bool suppress__;\
if(!(expr))\
{\
switch(debug_OnAssertionFailure(WIDEN(#expr), &suppress__, WIDEN(__FILE__), __LINE__, __func__))\
{\
case ER_CONTINUE:\
break;\
case ER_BREAK:\
default:\
break;\
}\
}\
}\
while(0)
trigger breakpoint, i.e.
Definition: debug.h:145
#define WIDEN(x)
volatile intptr_t atomic_bool
a bool that is reasonably certain to be set atomically.
Definition: debug.h:117
void debug_break()
trigger a breakpoint when reached/&quot;called&quot;.
Definition: udbg.cpp:48
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
#define __func__
ignore, continue as if nothing happened.
Definition: debug.h:138

ensure the expression <expr> evaluates to non-zero.

used to validate invariants in the program during development and thus gives a very helpful warning if something isn't going as expected. sprinkle these liberally throughout your code!

to pass more information to users at runtime, you can write ENSURE(expression && "descriptive string").

Definition at line 282 of file debug.h.

Typedef Documentation

typedef volatile intptr_t atomic_bool

a bool that is reasonably certain to be set atomically.

we cannot assume support for OpenMP (requires GCC 4.2) or C++0x, so we'll have to resort to intptr_t, cpu_CAS and COMPILER_FENCE.

Definition at line 117 of file debug.h.

Enumeration Type Documentation

flags to customize debug_DisplayError behavior

Enumerator
DE_NO_CONTINUE 

disallow the Continue button.

used e.g. if an exception is fatal.

DE_ALLOW_SUPPRESS 

enable the Suppress button.

set automatically by debug_DisplayError if it receives a non-NULL suppress pointer. a flag is necessary because the sys_display_error interface doesn't get that pointer. rationale for automatic setting: this may prevent someone from forgetting to specify it, and disabling Suppress despite having passed a non-NULL pointer doesn't make much sense.

DE_MANUAL_BREAK 

do not trigger a breakpoint inside debug_DisplayError; caller will take care of this if ER_BREAK is returned.

this is so that the debugger can jump directly into the offending function.

DE_NO_DEBUG_INFO 

display just the given message; do not add any information about the call stack, do not write crashlogs, etc.

Definition at line 81 of file debug.h.

choices offered by the error dialog that are returned by debug_DisplayError.

Enumerator
ER_CONTINUE 

ignore, continue as if nothing happened.

note: value doesn't start at 0 because that is interpreted as a DialogBoxParam failure.

ER_BREAK 

trigger breakpoint, i.e.

enter debugger. only returned if DE_MANUAL_BREAK was passed; otherwise, debug_DisplayError will trigger a breakpoint itself.

Definition at line 131 of file debug.h.

all choices offered by the error dialog.

those not defined in ErrorReaction are acted upon by debug_DisplayError and never returned to callers. (this separation avoids enumerator-not-handled warnings)

Enumerator
ERI_CONTINUE 
ERI_BREAK 
ERI_SUPPRESS 

ignore and do not report again.

note: non-persistent; only applicable during this program run.

ERI_EXIT 

exit the program immediately.

ERI_NOT_IMPLEMENTED 

special return value for the display_error app hook stub to indicate that it has done nothing and that the normal sys_display_error implementation should be called instead.

Definition at line 154 of file debug.h.

Function Documentation

void debug_break ( )

trigger a breakpoint when reached/"called".

if defined as a macro, the debugger can break directly into the target function instead of one frame below it as with a conventional call-based implementation.

Definition at line 48 of file udbg.cpp.

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.

this is a helper function used by debug_DumpStack and is made available so that the self-test doesn't have to display the error dialog.

Parameters
description,:general description of the problem.
fn_onlyfilename (no path) of source file that triggered the error.
line,func,:exact position of the error.
context,lastFuncToSkip,:see debug_DumpStack.
emmmemory for the error message. caller should allocate stack memory and set alloc_buf*; if not, there will be no fallback in case heap alloc fails. should be freed via debug_FreeErrorMessage when no longer needed.

Definition at line 262 of file debug.cpp.

LIB_API Status debug_CaptureContext ( void *  context)
Parameters
contextmust point to an instance of the platform-specific type (e.g. CONTEXT) or CACHE_ALIGNED storage of DEBUG_CONTEXT_SIZE bytes.

Definition at line 42 of file udbg.cpp.

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.

Parameters
descriptiontext to show.
flags,:see DebugDisplayErrorFlags.
context,lastFuncToSkip,:see debug_DumpStack.
file,line,func,:location of the error (typically passed as WIDEN(FILE), LINE, func from a macro)
suppresspointer to a caller-allocated flag that can be used to suppress this error. if NULL, this functionality is skipped and the "Suppress" dialog button will be disabled. note: this flag is read and written exclusively here; caller only provides the storage. values: see DEBUG_SUPPRESS above.
Returns
ErrorReaction (user's choice: continue running or stop?)

Definition at line 426 of file debug.cpp.

LIB_API void debug_DisplayMessage ( const wchar_t caption,
const wchar_t msg 
)

translates and displays the given strings in a dialog.

this is typically only used when debug_DisplayError has failed or is unavailable because that function is much more capable. implemented via sys_display_msg; see documentation there.

Definition at line 344 of file debug.cpp.

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.

Parameters
bufTarget buffer.
maxCharsMax chars of buffer (should be several thousand).
contextPlatform-specific representation of execution state (e.g. Win32 CONTEXT). either specify an SEH exception's context record or use debug_CaptureContext to retrieve the current state. Rationale: intermediates such as debug_DisplayError change the context, so it should be captured as soon as possible.
lastFuncToSkipIs used for omitting error-reporting functions like debug_OnAssertionFailure from the stack trace. It is either 0 (skip nothing) or a substring of a function's name (this allows platform-independent matching of stdcall-decorated names). Rationale: this is safer than specifying a fixed number of frames, which can be incorrect due to inlining.
Returns
Status; ERR::REENTERED if reentered via recursion or multithreading (not allowed since static data is used).

Definition at line 52 of file bdbg.cpp.

LIB_API void debug_filter_add ( const wchar_t tag)

debug output is very useful, but "too much of a good thing can kill you".

we don't want to require different LOGn() macros that are enabled depending on "debug level", because changing that entails lengthy compiles and it's too coarse-grained. instead, we require all strings to start with "tag_string|" (exact case and no quotes; the alphanumeric-only <tag_string> identifies output type). they are then subject to filtering: only if the tag has been "added" via debug_filter_add is the appendant string displayed.

this approach is easiest to implement and is fine because we control all logging code. LIMODS falls from consideration since it's not portable and too complex.

notes:

  • filter changes only affect subsequent debug_*printf calls; output that didn't pass the filter is permanently discarded.
  • strings not starting with a tag are always displayed.
  • debug_filter_* can be called at any time and from the debugger, but are not reentrant.

in future, allow output with the given tag to proceed. no effect if already added.

Definition at line 77 of file debug.cpp.

LIB_API bool debug_filter_allows ( const wchar_t text)

indicate if the given text would be printed.

useful for a series of debug_printfs - avoids needing to add a tag to each of their format strings.

Definition at line 119 of file debug.cpp.

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 at line 114 of file debug.cpp.

LIB_API void debug_filter_remove ( const wchar_t tag)

in future, discard output with the given tag.

no effect if not currently added.

Definition at line 96 of file debug.cpp.

LIB_API void debug_FreeErrorMessage ( ErrorMessageMem emm)

free memory from the error message.

Parameters
emmErrorMessageMem*

Definition at line 209 of file debug.cpp.

LIB_API void* debug_GetCaller ( void *  context,
const wchar_t lastFuncToSkip 
)

return the caller of a certain function on the call stack.

this function is useful for recording (partial) stack traces for memory allocation tracking, etc.

Parameters
context,lastFuncToSkip- see debug_DumpStack
Returns
address of the caller

Definition at line 38 of file bdbg.cpp.

LIB_API bool debug_IsCodePointer ( void *  p)

does the given pointer appear to point to code?

Definition at line 62 of file wdbg.cpp.

LIB_API int debug_IsPointerBogus ( const void *  p)

check if a pointer appears to be totally invalid.

this check is not authoritative (the pointer may be "valid" but incorrect) but can be used to filter out obviously wrong values in a portable manner.

Parameters
ppointer
Returns
1 if totally bogus, otherwise 0.

Definition at line 114 of file udbg.cpp.

LIB_API bool debug_IsStackPointer ( void *  p)

does the given pointer appear to point to the stack?

Definition at line 77 of file wdbg.cpp.

LIB_API ErrorReaction debug_OnAssertionFailure ( const wchar_t assert_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.

Parameters
assert_exprthe expression that failed; typically passed as #expr in the assert macro.
suppresssee debug_DisplayError.
file,linesource file name and line number of the spot that failed
funcname of the function containing it
Returns
ErrorReaction (user's choice: continue running or stop?)

Definition at line 550 of file debug.cpp.

LIB_API 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.

Parameters
errStatus value indicating the error that occurred
suppresssee debug_DisplayError.
file,linesource file name and line number of the spot that failed
funcname of the function containing it
Returns
ErrorReaction (user's choice: continue running or stop?)

Definition at line 534 of file debug.cpp.

LIB_API void debug_printf ( const wchar_t fmt,
  ... 
)

write a formatted string to the debug channel, subject to filtering (see below).

implemented via debug_puts - see performance note there.

Parameters
fmtFormat string and varargs; see printf.

Definition at line 142 of file debug.cpp.

LIB_API void debug_puts ( const wchar_t text)

[system-dependent] write a string to the debug channel.

this can be quite slow (~1 ms)! On Windows, it uses OutputDebugString (entails context switch), otherwise stdout+fflush (waits for IO).

Definition at line 106 of file udbg.cpp.

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.

NOTE: the PDB implementation is rather slow (~500 us).

Parameters
ptr_of_interestaddress of symbol (e.g. function, variable)
sym_nameoptional out; holds at least DEBUG_SYMBOL_CHARS; receives symbol name returned via debug info.
fileoptional out; holds at least DEBUG_FILE_CHARS; receives base name only (no path; see rationale in wdbg_sym) of source file containing the symbol.
lineoptional out; receives source file line number of symbol.

note: all of the output parameters are optional; we pass back as much information as is available and desired.

Returns
Status; INFO::OK iff any information was successfully retrieved and stored.

Definition at line 99 of file bdbg.cpp.

LIB_API void debug_SetThreadName ( const char *  name)

inform the debugger of the current thread's name.

(threads are easier to keep apart when they are identified by name rather than TID.)

Definition at line 126 of file bdbg.cpp.

LIB_API void debug_SkipErrors ( Status  err)

suppress (prevent from showing) the error dialog from subsequent debug_OnError for the given Status.

rationale: for edge cases in some functions, warnings are raised in addition to returning an error code. self-tests deliberately trigger these cases and check for the latter but shouldn't cause the former. we therefore need to squelch them.

Parameters
errthe Status to skip.

note: only one concurrent skip request is allowed; call debug_StopSkippingErrors before the next debug_SkipErrors.

Definition at line 491 of file debug.cpp.

LIB_API size_t debug_StopSkippingErrors ( )
Returns
how many errors were skipped since the call to debug_SkipErrors()

Definition at line 504 of file debug.cpp.

LIB_API Status debug_WriteCrashlog ( const wchar_t text)

write an error description and all logs into crashlog.txt (in unicode format).

Parameters
textdescription of the error (including stack trace); typically generated by debug_BuildErrorMessage.
Returns
Status; ERR::REENTERED if reentered via recursion or multithreading (not allowed since an infinite loop may result).

Definition at line 160 of file debug.cpp.

Variable Documentation

const size_t DEBUG_CONTEXT_SIZE = 2048
static

Definition at line 451 of file debug.h.

const size_t DEBUG_FILE_CHARS = 100
static

Definition at line 429 of file debug.h.

const atomic_bool DEBUG_SUPPRESS = 0xAB
static

value for suppress flag once set by debug_DisplayError.

rationale: this value is fairly distinctive and helps when debugging the symbol engine. use 0 as the initial value to avoid allocating .rdata space.

Definition at line 125 of file debug.h.

const size_t DEBUG_SYMBOL_CHARS = 1000
static

Maximum number of characters (including null terminator) written to user's buffers by debug_ResolveSymbol.

Definition at line 428 of file debug.h.