u_debug.h revision 01e04c3f
101e04c3fSmrg/************************************************************************** 201e04c3fSmrg * 301e04c3fSmrg * Copyright 2008 VMware, Inc. 401e04c3fSmrg * All Rights Reserved. 501e04c3fSmrg * 601e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a 701e04c3fSmrg * copy of this software and associated documentation files (the 801e04c3fSmrg * "Software"), to deal in the Software without restriction, including 901e04c3fSmrg * without limitation the rights to use, copy, modify, merge, publish, 1001e04c3fSmrg * distribute, sub license, and/or sell copies of the Software, and to 1101e04c3fSmrg * permit persons to whom the Software is furnished to do so, subject to 1201e04c3fSmrg * the following conditions: 1301e04c3fSmrg * 1401e04c3fSmrg * The above copyright notice and this permission notice (including the 1501e04c3fSmrg * next paragraph) shall be included in all copies or substantial portions 1601e04c3fSmrg * of the Software. 1701e04c3fSmrg * 1801e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 1901e04c3fSmrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 2001e04c3fSmrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 2101e04c3fSmrg * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 2201e04c3fSmrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 2301e04c3fSmrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 2401e04c3fSmrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2501e04c3fSmrg * 2601e04c3fSmrg **************************************************************************/ 2701e04c3fSmrg 2801e04c3fSmrg/** 2901e04c3fSmrg * @file 3001e04c3fSmrg * Cross-platform debugging helpers. 3101e04c3fSmrg * 3201e04c3fSmrg * For now it just has assert and printf replacements, but it might be extended 3301e04c3fSmrg * with stack trace reports and more advanced logging in the near future. 3401e04c3fSmrg * 3501e04c3fSmrg * @author Jose Fonseca <jfonseca@vmware.com> 3601e04c3fSmrg */ 3701e04c3fSmrg 3801e04c3fSmrg#ifndef U_DEBUG_H_ 3901e04c3fSmrg#define U_DEBUG_H_ 4001e04c3fSmrg 4101e04c3fSmrg 4201e04c3fSmrg#include "util/os_misc.h" 4301e04c3fSmrg 4401e04c3fSmrg#if defined(PIPE_OS_HAIKU) 4501e04c3fSmrg/* Haiku provides debug_printf in libroot with OS.h */ 4601e04c3fSmrg#include <OS.h> 4701e04c3fSmrg#endif 4801e04c3fSmrg 4901e04c3fSmrg#include "pipe/p_defines.h" 5001e04c3fSmrg 5101e04c3fSmrg 5201e04c3fSmrg#ifdef __cplusplus 5301e04c3fSmrgextern "C" { 5401e04c3fSmrg#endif 5501e04c3fSmrg 5601e04c3fSmrg 5701e04c3fSmrg#if defined(__GNUC__) 5801e04c3fSmrg#define _util_printf_format(fmt, list) __attribute__ ((format (printf, fmt, list))) 5901e04c3fSmrg#else 6001e04c3fSmrg#define _util_printf_format(fmt, list) 6101e04c3fSmrg#endif 6201e04c3fSmrg 6301e04c3fSmrgvoid _debug_vprintf(const char *format, va_list ap); 6401e04c3fSmrg 6501e04c3fSmrg 6601e04c3fSmrgstatic inline void 6701e04c3fSmrg_debug_printf(const char *format, ...) 6801e04c3fSmrg{ 6901e04c3fSmrg va_list ap; 7001e04c3fSmrg va_start(ap, format); 7101e04c3fSmrg _debug_vprintf(format, ap); 7201e04c3fSmrg va_end(ap); 7301e04c3fSmrg} 7401e04c3fSmrg 7501e04c3fSmrg 7601e04c3fSmrg/** 7701e04c3fSmrg * Print debug messages. 7801e04c3fSmrg * 7901e04c3fSmrg * The actual channel used to output debug message is platform specific. To 8001e04c3fSmrg * avoid misformating or truncation, follow these rules of thumb: 8101e04c3fSmrg * - output whole lines 8201e04c3fSmrg * - avoid outputing large strings (512 bytes is the current maximum length 8301e04c3fSmrg * that is guaranteed to be printed in all platforms) 8401e04c3fSmrg */ 8501e04c3fSmrg#if !defined(PIPE_OS_HAIKU) 8601e04c3fSmrgstatic inline void 8701e04c3fSmrgdebug_printf(const char *format, ...) _util_printf_format(1,2); 8801e04c3fSmrg 8901e04c3fSmrgstatic inline void 9001e04c3fSmrgdebug_printf(const char *format, ...) 9101e04c3fSmrg{ 9201e04c3fSmrg#ifdef DEBUG 9301e04c3fSmrg va_list ap; 9401e04c3fSmrg va_start(ap, format); 9501e04c3fSmrg _debug_vprintf(format, ap); 9601e04c3fSmrg va_end(ap); 9701e04c3fSmrg#else 9801e04c3fSmrg (void) format; /* silence warning */ 9901e04c3fSmrg#endif 10001e04c3fSmrg} 10101e04c3fSmrg#endif 10201e04c3fSmrg 10301e04c3fSmrg 10401e04c3fSmrg/* 10501e04c3fSmrg * ... isn't portable so we need to pass arguments in parentheses. 10601e04c3fSmrg * 10701e04c3fSmrg * usage: 10801e04c3fSmrg * debug_printf_once(("answer: %i\n", 42)); 10901e04c3fSmrg */ 11001e04c3fSmrg#define debug_printf_once(args) \ 11101e04c3fSmrg do { \ 11201e04c3fSmrg static boolean once = TRUE; \ 11301e04c3fSmrg if (once) { \ 11401e04c3fSmrg once = FALSE; \ 11501e04c3fSmrg debug_printf args; \ 11601e04c3fSmrg } \ 11701e04c3fSmrg } while (0) 11801e04c3fSmrg 11901e04c3fSmrg 12001e04c3fSmrg#ifdef DEBUG 12101e04c3fSmrg#define debug_vprintf(_format, _ap) _debug_vprintf(_format, _ap) 12201e04c3fSmrg#else 12301e04c3fSmrg#define debug_vprintf(_format, _ap) ((void)0) 12401e04c3fSmrg#endif 12501e04c3fSmrg 12601e04c3fSmrg 12701e04c3fSmrg#ifdef DEBUG 12801e04c3fSmrg/** 12901e04c3fSmrg * Dump a blob in hex to the same place that debug_printf sends its 13001e04c3fSmrg * messages. 13101e04c3fSmrg */ 13201e04c3fSmrgvoid debug_print_blob( const char *name, const void *blob, unsigned size ); 13301e04c3fSmrg#else 13401e04c3fSmrg#define debug_print_blob(_name, _blob, _size) ((void)0) 13501e04c3fSmrg#endif 13601e04c3fSmrg 13701e04c3fSmrg 13801e04c3fSmrg/** 13901e04c3fSmrg * Disable interactive error message boxes. 14001e04c3fSmrg * 14101e04c3fSmrg * Should be called as soon as possible for effectiveness. 14201e04c3fSmrg */ 14301e04c3fSmrgvoid 14401e04c3fSmrgdebug_disable_error_message_boxes(void); 14501e04c3fSmrg 14601e04c3fSmrg 14701e04c3fSmrg/** 14801e04c3fSmrg * Hard-coded breakpoint. 14901e04c3fSmrg */ 15001e04c3fSmrg#ifdef DEBUG 15101e04c3fSmrg#define debug_break() os_break() 15201e04c3fSmrg#else /* !DEBUG */ 15301e04c3fSmrg#define debug_break() ((void)0) 15401e04c3fSmrg#endif /* !DEBUG */ 15501e04c3fSmrg 15601e04c3fSmrg 15701e04c3fSmrglong 15801e04c3fSmrgdebug_get_num_option(const char *name, long dfault); 15901e04c3fSmrg 16001e04c3fSmrg#ifdef _MSC_VER 16101e04c3fSmrg__declspec(noreturn) 16201e04c3fSmrg#endif 16301e04c3fSmrgvoid _debug_assert_fail(const char *expr, 16401e04c3fSmrg const char *file, 16501e04c3fSmrg unsigned line, 16601e04c3fSmrg const char *function) 16701e04c3fSmrg#if defined(__GNUC__) && !defined(DEBUG) 16801e04c3fSmrg __attribute__((noreturn)) 16901e04c3fSmrg#endif 17001e04c3fSmrg; 17101e04c3fSmrg 17201e04c3fSmrg 17301e04c3fSmrg/** 17401e04c3fSmrg * Assert macro 17501e04c3fSmrg * 17601e04c3fSmrg * Do not expect that the assert call terminates -- errors must be handled 17701e04c3fSmrg * regardless of assert behavior. 17801e04c3fSmrg * 17901e04c3fSmrg * For non debug builds the assert macro will expand to a no-op, so do not 18001e04c3fSmrg * call functions with side effects in the assert expression. 18101e04c3fSmrg */ 18201e04c3fSmrg#ifndef NDEBUG 18301e04c3fSmrg#define debug_assert(expr) ((expr) ? (void)0 : _debug_assert_fail(#expr, __FILE__, __LINE__, __FUNCTION__)) 18401e04c3fSmrg#else 18501e04c3fSmrg#define debug_assert(expr) (void)(0 && (expr)) 18601e04c3fSmrg#endif 18701e04c3fSmrg 18801e04c3fSmrg 18901e04c3fSmrg/** Override standard assert macro */ 19001e04c3fSmrg#ifdef assert 19101e04c3fSmrg#undef assert 19201e04c3fSmrg#endif 19301e04c3fSmrg#define assert(expr) debug_assert(expr) 19401e04c3fSmrg 19501e04c3fSmrg 19601e04c3fSmrg/** 19701e04c3fSmrg * Output the current function name. 19801e04c3fSmrg */ 19901e04c3fSmrg#ifdef DEBUG 20001e04c3fSmrg#define debug_checkpoint() \ 20101e04c3fSmrg _debug_printf("%s\n", __FUNCTION__) 20201e04c3fSmrg#else 20301e04c3fSmrg#define debug_checkpoint() \ 20401e04c3fSmrg ((void)0) 20501e04c3fSmrg#endif 20601e04c3fSmrg 20701e04c3fSmrg 20801e04c3fSmrg/** 20901e04c3fSmrg * Output the full source code position. 21001e04c3fSmrg */ 21101e04c3fSmrg#ifdef DEBUG 21201e04c3fSmrg#define debug_checkpoint_full() \ 21301e04c3fSmrg _debug_printf("%s:%u:%s\n", __FILE__, __LINE__, __FUNCTION__) 21401e04c3fSmrg#else 21501e04c3fSmrg#define debug_checkpoint_full() \ 21601e04c3fSmrg ((void)0) 21701e04c3fSmrg#endif 21801e04c3fSmrg 21901e04c3fSmrg 22001e04c3fSmrg/** 22101e04c3fSmrg * Output a warning message. Muted on release version. 22201e04c3fSmrg */ 22301e04c3fSmrg#ifdef DEBUG 22401e04c3fSmrg#define debug_warning(__msg) \ 22501e04c3fSmrg _debug_printf("%s:%u:%s: warning: %s\n", __FILE__, __LINE__, __FUNCTION__, __msg) 22601e04c3fSmrg#else 22701e04c3fSmrg#define debug_warning(__msg) \ 22801e04c3fSmrg ((void)0) 22901e04c3fSmrg#endif 23001e04c3fSmrg 23101e04c3fSmrg 23201e04c3fSmrg/** 23301e04c3fSmrg * Emit a warning message, but only once. 23401e04c3fSmrg */ 23501e04c3fSmrg#ifdef DEBUG 23601e04c3fSmrg#define debug_warn_once(__msg) \ 23701e04c3fSmrg do { \ 23801e04c3fSmrg static bool warned = FALSE; \ 23901e04c3fSmrg if (!warned) { \ 24001e04c3fSmrg _debug_printf("%s:%u:%s: one time warning: %s\n", \ 24101e04c3fSmrg __FILE__, __LINE__, __FUNCTION__, __msg); \ 24201e04c3fSmrg warned = TRUE; \ 24301e04c3fSmrg } \ 24401e04c3fSmrg } while (0) 24501e04c3fSmrg#else 24601e04c3fSmrg#define debug_warn_once(__msg) \ 24701e04c3fSmrg ((void)0) 24801e04c3fSmrg#endif 24901e04c3fSmrg 25001e04c3fSmrg 25101e04c3fSmrg/** 25201e04c3fSmrg * Output an error message. Not muted on release version. 25301e04c3fSmrg */ 25401e04c3fSmrg#ifdef DEBUG 25501e04c3fSmrg#define debug_error(__msg) \ 25601e04c3fSmrg _debug_printf("%s:%u:%s: error: %s\n", __FILE__, __LINE__, __FUNCTION__, __msg) 25701e04c3fSmrg#else 25801e04c3fSmrg#define debug_error(__msg) \ 25901e04c3fSmrg _debug_printf("error: %s\n", __msg) 26001e04c3fSmrg#endif 26101e04c3fSmrg 26201e04c3fSmrg/** 26301e04c3fSmrg * Output a debug log message to the debug info callback. 26401e04c3fSmrg */ 26501e04c3fSmrg#define pipe_debug_message(cb, type, fmt, ...) do { \ 26601e04c3fSmrg static unsigned id = 0; \ 26701e04c3fSmrg if ((cb) && (cb)->debug_message) { \ 26801e04c3fSmrg _pipe_debug_message(cb, &id, \ 26901e04c3fSmrg PIPE_DEBUG_TYPE_ ## type, \ 27001e04c3fSmrg fmt, ##__VA_ARGS__); \ 27101e04c3fSmrg } \ 27201e04c3fSmrg} while (0) 27301e04c3fSmrg 27401e04c3fSmrgstruct pipe_debug_callback; 27501e04c3fSmrg 27601e04c3fSmrgvoid 27701e04c3fSmrg_pipe_debug_message( 27801e04c3fSmrg struct pipe_debug_callback *cb, 27901e04c3fSmrg unsigned *id, 28001e04c3fSmrg enum pipe_debug_type type, 28101e04c3fSmrg const char *fmt, ...) _util_printf_format(4, 5); 28201e04c3fSmrg 28301e04c3fSmrg 28401e04c3fSmrg/** 28501e04c3fSmrg * Used by debug_dump_enum and debug_dump_flags to describe symbols. 28601e04c3fSmrg */ 28701e04c3fSmrgstruct debug_named_value 28801e04c3fSmrg{ 28901e04c3fSmrg const char *name; 29001e04c3fSmrg uint64_t value; 29101e04c3fSmrg const char *desc; 29201e04c3fSmrg}; 29301e04c3fSmrg 29401e04c3fSmrg 29501e04c3fSmrg/** 29601e04c3fSmrg * Some C pre-processor magic to simplify creating named values. 29701e04c3fSmrg * 29801e04c3fSmrg * Example: 29901e04c3fSmrg * @code 30001e04c3fSmrg * static const debug_named_value my_names[] = { 30101e04c3fSmrg * DEBUG_NAMED_VALUE(MY_ENUM_VALUE_X), 30201e04c3fSmrg * DEBUG_NAMED_VALUE(MY_ENUM_VALUE_Y), 30301e04c3fSmrg * DEBUG_NAMED_VALUE(MY_ENUM_VALUE_Z), 30401e04c3fSmrg * DEBUG_NAMED_VALUE_END 30501e04c3fSmrg * }; 30601e04c3fSmrg * 30701e04c3fSmrg * ... 30801e04c3fSmrg * debug_printf("%s = %s\n", 30901e04c3fSmrg * name, 31001e04c3fSmrg * debug_dump_enum(my_names, my_value)); 31101e04c3fSmrg * ... 31201e04c3fSmrg * @endcode 31301e04c3fSmrg */ 31401e04c3fSmrg#define DEBUG_NAMED_VALUE(__symbol) {#__symbol, (unsigned long)__symbol, NULL} 31501e04c3fSmrg#define DEBUG_NAMED_VALUE_WITH_DESCRIPTION(__symbol, __desc) {#__symbol, (unsigned long)__symbol, __desc} 31601e04c3fSmrg#define DEBUG_NAMED_VALUE_END {NULL, 0, NULL} 31701e04c3fSmrg 31801e04c3fSmrg 31901e04c3fSmrg/** 32001e04c3fSmrg * Convert a enum value to a string. 32101e04c3fSmrg */ 32201e04c3fSmrgconst char * 32301e04c3fSmrgdebug_dump_enum(const struct debug_named_value *names, 32401e04c3fSmrg unsigned long value); 32501e04c3fSmrg 32601e04c3fSmrgconst char * 32701e04c3fSmrgdebug_dump_enum_noprefix(const struct debug_named_value *names, 32801e04c3fSmrg const char *prefix, 32901e04c3fSmrg unsigned long value); 33001e04c3fSmrg 33101e04c3fSmrg 33201e04c3fSmrg/** 33301e04c3fSmrg * Convert binary flags value to a string. 33401e04c3fSmrg */ 33501e04c3fSmrgconst char * 33601e04c3fSmrgdebug_dump_flags(const struct debug_named_value *names, 33701e04c3fSmrg unsigned long value); 33801e04c3fSmrg 33901e04c3fSmrg 34001e04c3fSmrg/** 34101e04c3fSmrg * Function enter exit loggers 34201e04c3fSmrg */ 34301e04c3fSmrg#ifdef DEBUG 34401e04c3fSmrgint debug_funclog_enter(const char* f, const int line, const char* file); 34501e04c3fSmrgvoid debug_funclog_exit(const char* f, const int line, const char* file); 34601e04c3fSmrgvoid debug_funclog_enter_exit(const char* f, const int line, const char* file); 34701e04c3fSmrg 34801e04c3fSmrg#define DEBUG_FUNCLOG_ENTER() \ 34901e04c3fSmrg int __debug_decleration_work_around = \ 35001e04c3fSmrg debug_funclog_enter(__FUNCTION__, __LINE__, __FILE__) 35101e04c3fSmrg#define DEBUG_FUNCLOG_EXIT() \ 35201e04c3fSmrg do { \ 35301e04c3fSmrg (void)__debug_decleration_work_around; \ 35401e04c3fSmrg debug_funclog_exit(__FUNCTION__, __LINE__, __FILE__); \ 35501e04c3fSmrg return; \ 35601e04c3fSmrg } while(0) 35701e04c3fSmrg#define DEBUG_FUNCLOG_EXIT_RET(ret) \ 35801e04c3fSmrg do { \ 35901e04c3fSmrg (void)__debug_decleration_work_around; \ 36001e04c3fSmrg debug_funclog_exit(__FUNCTION__, __LINE__, __FILE__); \ 36101e04c3fSmrg return ret; \ 36201e04c3fSmrg } while(0) 36301e04c3fSmrg#define DEBUG_FUNCLOG_ENTER_EXIT() \ 36401e04c3fSmrg debug_funclog_enter_exit(__FUNCTION__, __LINE__, __FILE__) 36501e04c3fSmrg 36601e04c3fSmrg#else 36701e04c3fSmrg#define DEBUG_FUNCLOG_ENTER() \ 36801e04c3fSmrg int __debug_decleration_work_around 36901e04c3fSmrg#define DEBUG_FUNCLOG_EXIT() \ 37001e04c3fSmrg do { (void)__debug_decleration_work_around; return; } while(0) 37101e04c3fSmrg#define DEBUG_FUNCLOG_EXIT_RET(ret) \ 37201e04c3fSmrg do { (void)__debug_decleration_work_around; return ret; } while(0) 37301e04c3fSmrg#define DEBUG_FUNCLOG_ENTER_EXIT() 37401e04c3fSmrg#endif 37501e04c3fSmrg 37601e04c3fSmrg 37701e04c3fSmrg/** 37801e04c3fSmrg * Get option. 37901e04c3fSmrg * 38001e04c3fSmrg * It is an alias for getenv on Linux. 38101e04c3fSmrg * 38201e04c3fSmrg * On Windows it reads C:\gallium.cfg, which is a text file with CR+LF line 38301e04c3fSmrg * endings with one option per line as 38401e04c3fSmrg * 38501e04c3fSmrg * NAME=value 38601e04c3fSmrg * 38701e04c3fSmrg * This file must be terminated with an extra empty line. 38801e04c3fSmrg */ 38901e04c3fSmrgconst char * 39001e04c3fSmrgdebug_get_option(const char *name, const char *dfault); 39101e04c3fSmrg 39201e04c3fSmrgboolean 39301e04c3fSmrgdebug_get_bool_option(const char *name, boolean dfault); 39401e04c3fSmrg 39501e04c3fSmrglong 39601e04c3fSmrgdebug_get_num_option(const char *name, long dfault); 39701e04c3fSmrg 39801e04c3fSmrguint64_t 39901e04c3fSmrgdebug_get_flags_option(const char *name, 40001e04c3fSmrg const struct debug_named_value *flags, 40101e04c3fSmrg uint64_t dfault); 40201e04c3fSmrg 40301e04c3fSmrg#define DEBUG_GET_ONCE_OPTION(suffix, name, dfault) \ 40401e04c3fSmrgstatic const char * \ 40501e04c3fSmrgdebug_get_option_ ## suffix (void) \ 40601e04c3fSmrg{ \ 40701e04c3fSmrg static boolean first = TRUE; \ 40801e04c3fSmrg static const char * value; \ 40901e04c3fSmrg if (first) { \ 41001e04c3fSmrg first = FALSE; \ 41101e04c3fSmrg value = debug_get_option(name, dfault); \ 41201e04c3fSmrg } \ 41301e04c3fSmrg return value; \ 41401e04c3fSmrg} 41501e04c3fSmrg 41601e04c3fSmrg#define DEBUG_GET_ONCE_BOOL_OPTION(sufix, name, dfault) \ 41701e04c3fSmrgstatic boolean \ 41801e04c3fSmrgdebug_get_option_ ## sufix (void) \ 41901e04c3fSmrg{ \ 42001e04c3fSmrg static boolean first = TRUE; \ 42101e04c3fSmrg static boolean value; \ 42201e04c3fSmrg if (first) { \ 42301e04c3fSmrg first = FALSE; \ 42401e04c3fSmrg value = debug_get_bool_option(name, dfault); \ 42501e04c3fSmrg } \ 42601e04c3fSmrg return value; \ 42701e04c3fSmrg} 42801e04c3fSmrg 42901e04c3fSmrg#define DEBUG_GET_ONCE_NUM_OPTION(sufix, name, dfault) \ 43001e04c3fSmrgstatic long \ 43101e04c3fSmrgdebug_get_option_ ## sufix (void) \ 43201e04c3fSmrg{ \ 43301e04c3fSmrg static boolean first = TRUE; \ 43401e04c3fSmrg static long value; \ 43501e04c3fSmrg if (first) { \ 43601e04c3fSmrg first = FALSE; \ 43701e04c3fSmrg value = debug_get_num_option(name, dfault); \ 43801e04c3fSmrg } \ 43901e04c3fSmrg return value; \ 44001e04c3fSmrg} 44101e04c3fSmrg 44201e04c3fSmrg#define DEBUG_GET_ONCE_FLAGS_OPTION(sufix, name, flags, dfault) \ 44301e04c3fSmrgstatic unsigned long \ 44401e04c3fSmrgdebug_get_option_ ## sufix (void) \ 44501e04c3fSmrg{ \ 44601e04c3fSmrg static boolean first = TRUE; \ 44701e04c3fSmrg static unsigned long value; \ 44801e04c3fSmrg if (first) { \ 44901e04c3fSmrg first = FALSE; \ 45001e04c3fSmrg value = debug_get_flags_option(name, flags, dfault); \ 45101e04c3fSmrg } \ 45201e04c3fSmrg return value; \ 45301e04c3fSmrg} 45401e04c3fSmrg 45501e04c3fSmrg 45601e04c3fSmrg#ifdef __cplusplus 45701e04c3fSmrg} 45801e04c3fSmrg#endif 45901e04c3fSmrg 46001e04c3fSmrg#endif /* U_DEBUG_H_ */ 461