p_debug.h File Reference

Cross-platform debugging helpers. More...

Include dependency graph for p_debug.h:

Go to the source code of this file.

Data Structures

struct  debug_named_value
 Used by debug_dump_enum and debug_dump_flags to describe symbols. More...

Defines

#define NDEBUG   1
#define debug_vprintf(_format, _ap)   ((void)0)
#define debug_print_blob(_name, _blob, _size)   ((void)0)
#define debug_print_format(_msg, _fmt)   ((void)0)
#define debug_break()   ((void)0)
 Hard-coded breakpoint.
#define debug_assert(expr)   ((void)0)
 Assert macro.
#define assert(expr)   debug_assert(expr)
 Override standard assert macro.
#define debug_checkpoint()   ((void)0)
 Output the current function name.
#define debug_checkpoint_full()   ((void)0)
 Output the full source code position.
#define debug_warning(__msg)   ((void)0)
 Output a warning message.
#define debug_error(__msg)   _debug_printf("error: %s\n", __msg)
 Output an error message.
#define DEBUG_NAMED_VALUE(__symbol)   {#__symbol, (unsigned long)__symbol}
 Some C pre-processor magic to simplify creating named values.
#define DEBUG_NAMED_VALUE_END   {NULL, 0}
#define debug_dump_image(prefix, format, cpp, width, height, stride, data)   ((void)0)
#define debug_dump_surface(prefix, surface)   ((void)0)
#define debug_dump_surface_bmp(filename, surface)   ((void)0)

Functions

void _debug_vprintf (const char *format, va_list ap)
static void _debug_printf (const char *format,...)
static void debug_printf (const char *format,...)
 Print debug messages.
void _debug_break (void)
long debug_get_num_option (const char *name, long dfault)
void _debug_assert_fail (const char *expr, const char *file, unsigned line, const char *function)
const char * debug_dump_enum (const struct debug_named_value *names, unsigned long value)
 Convert a enum value to a string.
const char * debug_dump_flags (const struct debug_named_value *names, unsigned long value)
 Convert binary flags value to a string.
const char * debug_get_option (const char *name, const char *dfault)
 Get option.
boolean debug_get_bool_option (const char *name, boolean dfault)
unsigned long debug_get_flags_option (const char *name, const struct debug_named_value *flags, unsigned long dfault)
void * debug_malloc (const char *file, unsigned line, const char *function, size_t size)
void debug_free (const char *file, unsigned line, const char *function, void *ptr)
void * debug_calloc (const char *file, unsigned line, const char *function, size_t count, size_t size)
void * debug_realloc (const char *file, unsigned line, const char *function, void *old_ptr, size_t old_size, size_t new_size)
unsigned long debug_memory_begin (void)
void debug_memory_end (unsigned long beginning)


Detailed Description

Cross-platform debugging helpers.

For now it just has assert and printf replacements, but it might be extended with stack trace reports and more advanced logging in the near future.

Author:
Jose Fonseca <jrfonseca@tungstengraphics.com>

Definition in file p_debug.h.


Define Documentation

#define assert ( expr   )     debug_assert(expr)

Override standard assert macro.

Definition at line 171 of file p_debug.h.

#define debug_assert ( expr   )     ((void)0)

Assert macro.

Do not expect that the assert call terminates -- errors must be handled regardless of assert behavior.

Definition at line 163 of file p_debug.h.

 
#define debug_break (  )     ((void)0)

Hard-coded breakpoint.

Definition at line 141 of file p_debug.h.

 
#define debug_checkpoint (  )     ((void)0)

Output the current function name.

Definition at line 181 of file p_debug.h.

 
#define debug_checkpoint_full (  )     ((void)0)

Output the full source code position.

Definition at line 193 of file p_debug.h.

#define debug_dump_image ( prefix,
format,
cpp,
width,
height,
stride,
data   )     ((void)0)

Definition at line 344 of file p_debug.h.

#define debug_dump_surface ( prefix,
surface   )     ((void)0)

Definition at line 345 of file p_debug.h.

#define debug_dump_surface_bmp ( filename,
surface   )     ((void)0)

Definition at line 346 of file p_debug.h.

#define debug_error ( __msg   )     _debug_printf("error: %s\n", __msg)

Output an error message.

Not muted on release version.

Definition at line 217 of file p_debug.h.

#define DEBUG_NAMED_VALUE ( __symbol   )     {#__symbol, (unsigned long)__symbol}

Some C pre-processor magic to simplify creating named values.

Example:

 static const debug_named_value my_names[] = {
    DEBUG_NAMED_VALUE(MY_ENUM_VALUE_X),
    DEBUG_NAMED_VALUE(MY_ENUM_VALUE_Y),
    DEBUG_NAMED_VALUE(MY_ENUM_VALUE_Z),
    DEBUG_NAMED_VALUE_END
 };
 
    ...
    debug_printf("%s = %s\n", 
                 name,
                 debug_dump_enum(my_names, my_value));
    ...

Definition at line 251 of file p_debug.h.

#define DEBUG_NAMED_VALUE_END   {NULL, 0}

Definition at line 252 of file p_debug.h.

#define debug_print_blob ( _name,
_blob,
_size   )     ((void)0)

Definition at line 121 of file p_debug.h.

#define debug_print_format ( _msg,
_fmt   )     ((void)0)

Definition at line 122 of file p_debug.h.

#define debug_vprintf ( _format,
_ap   )     ((void)0)

Definition at line 108 of file p_debug.h.

#define debug_warning ( __msg   )     ((void)0)

Output a warning message.

Muted on release version.

Definition at line 205 of file p_debug.h.

#define NDEBUG   1

Definition at line 58 of file p_debug.h.


Function Documentation

void _debug_assert_fail ( const char *  expr,
const char *  file,
unsigned  line,
const char *  function 
)

Definition at line 337 of file p_debug.c.

References _debug_printf(), debug_break, debug_get_bool_option(), FALSE, and TRUE.

00341 {
00342    _debug_printf("%s:%u:%s: Assertion `%s' failed.\n", file, line, function, expr);
00343 #if defined(PIPE_OS_WINDOWS) && !defined(PIPE_SUBSYSTEM_WINDOWS_USER)
00344    if (debug_get_bool_option("GALLIUM_ABORT_ON_ASSERT", FALSE))
00345 #else
00346    if (debug_get_bool_option("GALLIUM_ABORT_ON_ASSERT", TRUE))
00347 #endif
00348       debug_break();
00349    else
00350       _debug_printf("continuing...\n");
00351 }

void _debug_break ( void   ) 

Definition at line 140 of file p_debug.c.

00141 {
00142 #if defined(PIPE_ARCH_X86) && defined(PIPE_CC_GCC)
00143    __asm("int3");
00144 #elif defined(PIPE_ARCH_X86) && defined(PIPE_CC_MSVC)
00145    _asm {int 3};
00146 #elif defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY)
00147    EngDebugBreak();
00148 #else
00149    abort();
00150 #endif
00151 }

static void _debug_printf ( const char *  format,
  ... 
) [static]

Definition at line 73 of file p_debug.h.

References _debug_vprintf().

00074 {
00075    va_list ap;
00076    va_start(ap, format);
00077    _debug_vprintf(format, ap);
00078    va_end(ap);
00079 }

void _debug_vprintf ( const char *  format,
va_list  ap 
)

Definition at line 79 of file p_debug.c.

References util_strchr, and util_vsnprintf.

00080 {
00081 #if defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY)
00082    /* EngDebugPrint does not handle float point arguments, so we need to use
00083     * our own vsnprintf implementation. It is also very slow, so buffer until
00084     * we find a newline. */
00085    static char buf[512] = {'\0'};
00086    size_t len = strlen(buf);
00087    int ret = util_vsnprintf(buf + len, sizeof(buf) - len, format, ap);
00088    if(ret > (int)(sizeof(buf) - len - 1) || util_strchr(buf + len, '\n')) {
00089       _EngDebugPrint("%s", buf);
00090       buf[0] = '\0';
00091    }
00092 #elif defined(PIPE_SUBSYSTEM_WINDOWS_USER)
00093    /* EngDebugPrint does not handle float point arguments, so we need to use
00094     * our own vsnprintf implementation. It is also very slow, so buffer until
00095     * we find a newline. */
00096    static char buf[512 + 1] = {'\0'};
00097    size_t len = strlen(buf);
00098    int ret = util_vsnprintf(buf + len, sizeof(buf) - len, format, ap);
00099    if(ret > (int)(sizeof(buf) - len - 1) || util_strchr(buf + len, '\n')) {
00100       OutputDebugStringA(buf);
00101       buf[0] = '\0';
00102    }
00103 
00104    
00105    if(GetConsoleWindow() && !IsDebuggerPresent()) {
00106       fflush(stdout);
00107       vfprintf(stderr, format, ap);
00108       fflush(stderr);
00109    }
00110    
00111 
00112 #elif defined(PIPE_SUBSYSTEM_WINDOWS_CE) || defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT) 
00113    /* TODO */
00114 #else /* !PIPE_SUBSYSTEM_WINDOWS */
00115 #ifdef DEBUG
00116    vfprintf(stderr, format, ap);
00117 #endif
00118 #endif
00119 }

void* debug_calloc ( const char *  file,
unsigned  line,
const char *  function,
size_t  count,
size_t  size 
)

Definition at line 184 of file p_debug_mem.c.

References debug_malloc().

00186 {
00187    void *ptr = debug_malloc( file, line, function, count * size );
00188    if( ptr )
00189       memset( ptr, 0, count * size );
00190    return ptr;
00191 }

const char* debug_dump_enum ( const struct debug_named_value names,
unsigned long  value 
)

Convert a enum value to a string.

Definition at line 355 of file p_debug.c.

References debug_named_value::name, util_snprintf, and debug_named_value::value.

00357 {
00358    static char rest[64];
00359    
00360    while(names->name) {
00361       if(names->value == value)
00362          return names->name;
00363       ++names;
00364    }
00365 
00366    util_snprintf(rest, sizeof(rest), "0x%08lx", value);
00367    return rest;
00368 }

const char* debug_dump_flags ( const struct debug_named_value names,
unsigned long  value 
)

Convert binary flags value to a string.

Definition at line 372 of file p_debug.c.

References debug_named_value::name, util_snprintf, util_strncat, and debug_named_value::value.

00374 {
00375    static char output[4096];
00376    static char rest[256];
00377    int first = 1;
00378 
00379    output[0] = '\0';
00380 
00381    while(names->name) {
00382       if((names->value & value) == names->value) {
00383          if (!first)
00384             util_strncat(output, "|", sizeof(output));
00385          else
00386             first = 0;
00387          util_strncat(output, names->name, sizeof(output));
00388          value &= ~names->value;
00389       }
00390       ++names;
00391    }
00392    
00393    if (value) {
00394       if (!first)
00395          util_strncat(output, "|", sizeof(output));
00396       else
00397          first = 0;
00398       
00399       util_snprintf(rest, sizeof(rest), "0x%08lx", value);
00400       util_strncat(output, rest, sizeof(output));
00401    }
00402    
00403    if(first)
00404       return "0";
00405    
00406    return output;
00407 }

void debug_free ( const char *  file,
unsigned  line,
const char *  function,
void *  ptr 
)

Definition at line 150 of file p_debug_mem.c.

References debug_assert, DEBUG_MEMORY_MAGIC, debug_printf(), debug_memory_header::file, footer_from_header(), debug_memory_header::function, debug_memory_header::head, header_from_data(), debug_memory_header::line, LIST_DEL, debug_memory_footer::magic, debug_memory_header::magic, and real_free.

00152 {
00153    struct debug_memory_header *hdr;
00154    struct debug_memory_footer *ftr;
00155    
00156    if(!ptr)
00157       return;
00158    
00159    hdr = header_from_data(ptr);
00160    if(hdr->magic != DEBUG_MEMORY_MAGIC) {
00161       debug_printf("%s:%u:%s: freeing bad or corrupted memory %p\n",
00162                    file, line, function,
00163                    ptr);
00164       debug_assert(0);
00165       return;
00166    }
00167 
00168    ftr = footer_from_header(hdr);
00169    if(ftr->magic != DEBUG_MEMORY_MAGIC) {
00170       debug_printf("%s:%u:%s: buffer overflow %p\n",
00171                    hdr->file, hdr->line, hdr->function,
00172                    ptr);
00173       debug_assert(0);
00174    }
00175 
00176    LIST_DEL(&hdr->head);
00177    hdr->magic = 0;
00178    ftr->magic = 0;
00179    
00180    real_free(hdr);
00181 }

boolean debug_get_bool_option ( const char *  name,
boolean  dfault 
)

Definition at line 251 of file p_debug.c.

References _debug_get_option(), debug_printf(), FALSE, TRUE, and util_strcmp.

00252 {
00253    const char *str = _debug_get_option(name);
00254    boolean result;
00255    
00256    if(str == NULL)
00257       result = dfault;
00258    else if(!util_strcmp(str, "n"))
00259       result = FALSE;
00260    else if(!util_strcmp(str, "no"))
00261       result = FALSE;
00262    else if(!util_strcmp(str, "0"))
00263       result = FALSE;
00264    else if(!util_strcmp(str, "f"))
00265       result = FALSE;
00266    else if(!util_strcmp(str, "false"))
00267       result = FALSE;
00268    else
00269       result = TRUE;
00270 
00271    debug_printf("%s: %s = %s\n", __FUNCTION__, name, result ? "TRUE" : "FALSE");
00272    
00273    return result;
00274 }

unsigned long debug_get_flags_option ( const char *  name,
const struct debug_named_value flags,
unsigned long  dfault 
)

Definition at line 312 of file p_debug.c.

References _debug_get_option(), debug_printf(), debug_named_value::name, util_strcmp, util_strstr, and debug_named_value::value.

00315 {
00316    unsigned long result;
00317    const char *str;
00318    
00319    str = _debug_get_option(name);
00320    if(!str)
00321       result = dfault;
00322    else {
00323       result = 0;
00324       while( flags->name ) {
00325          if (!util_strcmp(str, "all") || util_strstr(str, flags->name ))
00326             result |= flags->value;
00327          ++flags;
00328       }
00329    }
00330 
00331    debug_printf("%s: %s = 0x%lx\n", __FUNCTION__, name, result);
00332 
00333    return result;
00334 }

long debug_get_num_option ( const char *  name,
long  dfault 
)

Definition at line 278 of file p_debug.c.

References _debug_get_option(), and debug_printf().

00279 {
00280    long result;
00281    const char *str;
00282    
00283    str = _debug_get_option(name);
00284    if(!str)
00285       result = dfault;
00286    else {
00287       long sign;
00288       char c;
00289       c = *str++;
00290       if(c == '-') {
00291          sign = -1;
00292          c = *str++;
00293       } 
00294       else {
00295          sign = 1;
00296       }
00297       result = 0;
00298       while('0' <= c && c <= '9') {
00299          result = result*10 + (c - '0');
00300          c = *str++;
00301       }
00302       result *= sign;
00303    }
00304    
00305    debug_printf("%s: %s = %li\n", __FUNCTION__, name, result);
00306 
00307    return result;
00308 }

const char* debug_get_option ( const char *  name,
const char *  dfault 
)

Get option.

It is an alias for getenv on Linux.

On Windows it reads C:.cfg, which is a text file with CR+LF line endings with one option per line as

NAME=value

This file must be terminated with an extra empty line.

Definition at line 237 of file p_debug.c.

References _debug_get_option(), and debug_printf().

00238 {
00239    const char *result;
00240 
00241    result = _debug_get_option(name);
00242    if(!result)
00243       result = dfault;
00244       
00245    debug_printf("%s: %s = %s\n", __FUNCTION__, name, result ? result : "(null)");
00246    
00247    return result;
00248 }

void* debug_malloc ( const char *  file,
unsigned  line,
const char *  function,
size_t  size 
)

Definition at line 118 of file p_debug_mem.c.

References assert, data_from_header(), DEBUG_MEMORY_MAGIC, debug_printf(), debug_memory_header::file, footer_from_header(), debug_memory_header::function, debug_memory_header::head, last_no, debug_memory_header::line, LIST_ADDTAIL, debug_memory_footer::magic, debug_memory_header::magic, debug_memory_header::no, real_malloc, and debug_memory_header::size.

00120 {
00121    struct debug_memory_header *hdr;
00122    struct debug_memory_footer *ftr;
00123    
00124    assert(size);
00125    
00126    hdr = real_malloc(sizeof(*hdr) + size + sizeof(*ftr));
00127    if(!hdr) {
00128       debug_printf("%s:%u:%s: out of memory when trying to allocate %lu bytes\n",
00129                    file, line, function,
00130                    (long unsigned)size);
00131       return NULL;
00132    }
00133  
00134    hdr->no = last_no++;
00135    hdr->file = file;
00136    hdr->line = line;
00137    hdr->function = function;
00138    hdr->size = size;
00139    hdr->magic = DEBUG_MEMORY_MAGIC;
00140 
00141    ftr = footer_from_header(hdr);
00142    ftr->magic = DEBUG_MEMORY_MAGIC;
00143    
00144    LIST_ADDTAIL(&hdr->head, &list);
00145    
00146    return data_from_header(hdr);
00147 }

unsigned long debug_memory_begin ( void   ) 

Definition at line 259 of file p_debug_mem.c.

References last_no.

00260 {
00261    return last_no;
00262 }

void debug_memory_end ( unsigned long  beginning  ) 

Definition at line 265 of file p_debug_mem.c.

References data_from_header(), debug_assert, DEBUG_MEMORY_MAGIC, debug_printf(), debug_memory_header::file, footer_from_header(), debug_memory_header::function, last_no, debug_memory_header::line, LIST_ENTRY, debug_memory_footer::magic, debug_memory_header::magic, debug_memory_header::no, list_head::prev, and debug_memory_header::size.

00266 {
00267    size_t total_size = 0;
00268    struct list_head *entry;
00269 
00270    if(start_no == last_no)
00271       return;
00272 
00273    entry = list.prev;
00274    for (; entry != &list; entry = entry->prev) {
00275       struct debug_memory_header *hdr;
00276       void *ptr;
00277       struct debug_memory_footer *ftr;
00278 
00279       hdr = LIST_ENTRY(struct debug_memory_header, entry, head);
00280       ptr = data_from_header(hdr);
00281       ftr = footer_from_header(hdr);
00282 
00283       if(hdr->magic != DEBUG_MEMORY_MAGIC) {
00284          debug_printf("%s:%u:%s: bad or corrupted memory %p\n",
00285                       hdr->file, hdr->line, hdr->function,
00286                       ptr);
00287          debug_assert(0);
00288       }
00289 
00290       if((start_no <= hdr->no && hdr->no < last_no) ||
00291          (last_no < start_no && (hdr->no < last_no || start_no <= hdr->no))) {
00292          debug_printf("%s:%u:%s: %u bytes at %p not freed\n",
00293                       hdr->file, hdr->line, hdr->function,
00294                       hdr->size, ptr);
00295          total_size += hdr->size;
00296       }
00297 
00298       if(ftr->magic != DEBUG_MEMORY_MAGIC) {
00299          debug_printf("%s:%u:%s: buffer overflow %p\n",
00300                       hdr->file, hdr->line, hdr->function,
00301                       ptr);
00302          debug_assert(0);
00303       }
00304    }
00305 
00306    if(total_size) {
00307       debug_printf("Total of %u KB of system memory apparently leaked\n",
00308                    (total_size + 1023)/1024);
00309    }
00310    else {
00311       debug_printf("No memory leaks detected.\n");
00312    }
00313 }

static void debug_printf ( const char *  format,
  ... 
) [static]

Print debug messages.

The actual channel used to output debug message is platform specific. To avoid misformating or truncation, follow these rules of thumb:

Definition at line 92 of file p_debug.h.

References _debug_vprintf().

00093 {
00094 #ifdef DEBUG
00095    va_list ap;
00096    va_start(ap, format);
00097    _debug_vprintf(format, ap);
00098    va_end(ap);
00099 #else
00100    (void) format; /* silence warning */
00101 #endif
00102 }

void* debug_realloc ( const char *  file,
unsigned  line,
const char *  function,
void *  old_ptr,
size_t  old_size,
size_t  new_size 
)

Definition at line 194 of file p_debug_mem.c.

References data_from_header(), debug_assert, debug_free(), debug_malloc(), DEBUG_MEMORY_MAGIC, debug_printf(), debug_memory_header::file, footer_from_header(), debug_memory_header::function, debug_memory_header::head, header_from_data(), debug_memory_header::line, LIST_REPLACE, debug_memory_footer::magic, debug_memory_header::magic, debug_memory_header::no, real_free, real_malloc, and debug_memory_header::size.

00196 {
00197    struct debug_memory_header *old_hdr, *new_hdr;
00198    struct debug_memory_footer *old_ftr, *new_ftr;
00199    void *new_ptr;
00200    
00201    if(!old_ptr)
00202       return debug_malloc( file, line, function, new_size );
00203    
00204    if(!new_size) {
00205       debug_free( file, line, function, old_ptr );
00206       return NULL;
00207    }
00208    
00209    old_hdr = header_from_data(old_ptr);
00210    if(old_hdr->magic != DEBUG_MEMORY_MAGIC) {
00211       debug_printf("%s:%u:%s: reallocating bad or corrupted memory %p\n",
00212                    file, line, function,
00213                    old_ptr);
00214       debug_assert(0);
00215       return NULL;
00216    }
00217    
00218    old_ftr = footer_from_header(old_hdr);
00219    if(old_ftr->magic != DEBUG_MEMORY_MAGIC) {
00220       debug_printf("%s:%u:%s: buffer overflow %p\n",
00221                    old_hdr->file, old_hdr->line, old_hdr->function,
00222                    old_ptr);
00223       debug_assert(0);
00224    }
00225 
00226    /* alloc new */
00227    new_hdr = real_malloc(sizeof(*new_hdr) + new_size + sizeof(*new_ftr));
00228    if(!new_hdr) {
00229       debug_printf("%s:%u:%s: out of memory when trying to allocate %lu bytes\n",
00230                    file, line, function,
00231                    (long unsigned)new_size);
00232       return NULL;
00233    }
00234    new_hdr->no = old_hdr->no;
00235    new_hdr->file = old_hdr->file;
00236    new_hdr->line = old_hdr->line;
00237    new_hdr->function = old_hdr->function;
00238    new_hdr->size = new_size;
00239    new_hdr->magic = DEBUG_MEMORY_MAGIC;
00240    
00241    new_ftr = footer_from_header(new_hdr);
00242    new_ftr->magic = DEBUG_MEMORY_MAGIC;
00243    
00244    LIST_REPLACE(&old_hdr->head, &new_hdr->head);
00245 
00246    /* copy data */
00247    new_ptr = data_from_header(new_hdr);
00248    memcpy( new_ptr, old_ptr, old_size < new_size ? old_size : new_size );
00249 
00250    /* free old */
00251    old_hdr->magic = 0;
00252    old_ftr->magic = 0;
00253    real_free(old_hdr);
00254 
00255    return new_ptr;
00256 }


Generated on Tue Sep 29 06:25:43 2009 for Gallium3D by  doxygen 1.5.4