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) |
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.
Definition in file p_debug.h.
#define assert | ( | expr | ) | debug_assert(expr) |
#define debug_assert | ( | expr | ) | ((void)0) |
#define debug_checkpoint | ( | ) | ((void)0) |
#define debug_checkpoint_full | ( | ) | ((void)0) |
#define debug_dump_image | ( | prefix, | |||
format, | |||||
cpp, | |||||
width, | |||||
height, | |||||
stride, | |||||
data | ) | ((void)0) |
#define debug_dump_surface_bmp | ( | filename, | |||
surface | ) | ((void)0) |
#define debug_error | ( | __msg | ) | _debug_printf("error: %s\n", __msg) |
#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)); ...
#define debug_print_blob | ( | _name, | |||
_blob, | |||||
_size | ) | ((void)0) |
#define debug_warning | ( | __msg | ) | ((void)0) |
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 }
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 }