1b8e80941Smrg/************************************************************************** 2b8e80941Smrg * 3b8e80941Smrg * Copyright 2008 VMware, Inc. 4b8e80941Smrg * All Rights Reserved. 5b8e80941Smrg * 6b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a 7b8e80941Smrg * copy of this software and associated documentation files (the 8b8e80941Smrg * "Software"), to deal in the Software without restriction, including 9b8e80941Smrg * without limitation the rights to use, copy, modify, merge, publish, 10b8e80941Smrg * distribute, sub license, and/or sell copies of the Software, and to 11b8e80941Smrg * permit persons to whom the Software is furnished to do so, subject to 12b8e80941Smrg * the following conditions: 13b8e80941Smrg * 14b8e80941Smrg * The above copyright notice and this permission notice (including the 15b8e80941Smrg * next paragraph) shall be included in all copies or substantial portions 16b8e80941Smrg * of the Software. 17b8e80941Smrg * 18b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19b8e80941Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20b8e80941Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21b8e80941Smrg * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22b8e80941Smrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23b8e80941Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24b8e80941Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25b8e80941Smrg * 26b8e80941Smrg **************************************************************************/ 27b8e80941Smrg 28b8e80941Smrg/** 29b8e80941Smrg * @file 30b8e80941Smrg * Cross-platform debugging helpers. 31b8e80941Smrg * 32b8e80941Smrg * For now it just has assert and printf replacements, but it might be extended 33b8e80941Smrg * with stack trace reports and more advanced logging in the near future. 34b8e80941Smrg * 35b8e80941Smrg * @author Jose Fonseca <jfonseca@vmware.com> 36b8e80941Smrg */ 37b8e80941Smrg 38b8e80941Smrg#ifndef U_DEBUG_H_ 39b8e80941Smrg#define U_DEBUG_H_ 40b8e80941Smrg 41b8e80941Smrg 42b8e80941Smrg#include "util/os_misc.h" 43b8e80941Smrg 44b8e80941Smrg#if defined(PIPE_OS_HAIKU) 45b8e80941Smrg/* Haiku provides debug_printf in libroot with OS.h */ 46b8e80941Smrg#include <OS.h> 47b8e80941Smrg#endif 48b8e80941Smrg 49b8e80941Smrg#include "pipe/p_defines.h" 50b8e80941Smrg 51b8e80941Smrg 52b8e80941Smrg#ifdef __cplusplus 53b8e80941Smrgextern "C" { 54b8e80941Smrg#endif 55b8e80941Smrg 56b8e80941Smrg 57b8e80941Smrg#if defined(__GNUC__) 58b8e80941Smrg#define _util_printf_format(fmt, list) __attribute__ ((format (printf, fmt, list))) 59b8e80941Smrg#else 60b8e80941Smrg#define _util_printf_format(fmt, list) 61b8e80941Smrg#endif 62b8e80941Smrg 63b8e80941Smrgvoid _debug_vprintf(const char *format, va_list ap); 64b8e80941Smrg 65b8e80941Smrg 66b8e80941Smrgstatic inline void 67b8e80941Smrg_debug_printf(const char *format, ...) 68b8e80941Smrg{ 69b8e80941Smrg va_list ap; 70b8e80941Smrg va_start(ap, format); 71b8e80941Smrg _debug_vprintf(format, ap); 72b8e80941Smrg va_end(ap); 73b8e80941Smrg} 74b8e80941Smrg 75b8e80941Smrg 76b8e80941Smrg/** 77b8e80941Smrg * Print debug messages. 78b8e80941Smrg * 79b8e80941Smrg * The actual channel used to output debug message is platform specific. To 80b8e80941Smrg * avoid misformating or truncation, follow these rules of thumb: 81b8e80941Smrg * - output whole lines 82b8e80941Smrg * - avoid outputing large strings (512 bytes is the current maximum length 83b8e80941Smrg * that is guaranteed to be printed in all platforms) 84b8e80941Smrg */ 85b8e80941Smrg#if !defined(PIPE_OS_HAIKU) 86b8e80941Smrgstatic inline void 87b8e80941Smrgdebug_printf(const char *format, ...) _util_printf_format(1,2); 88b8e80941Smrg 89b8e80941Smrgstatic inline void 90b8e80941Smrgdebug_printf(const char *format, ...) 91b8e80941Smrg{ 92b8e80941Smrg#ifdef DEBUG 93b8e80941Smrg va_list ap; 94b8e80941Smrg va_start(ap, format); 95b8e80941Smrg _debug_vprintf(format, ap); 96b8e80941Smrg va_end(ap); 97b8e80941Smrg#else 98b8e80941Smrg (void) format; /* silence warning */ 99b8e80941Smrg#endif 100b8e80941Smrg} 101b8e80941Smrg#endif 102b8e80941Smrg 103b8e80941Smrg 104b8e80941Smrg/* 105b8e80941Smrg * ... isn't portable so we need to pass arguments in parentheses. 106b8e80941Smrg * 107b8e80941Smrg * usage: 108b8e80941Smrg * debug_printf_once(("answer: %i\n", 42)); 109b8e80941Smrg */ 110b8e80941Smrg#define debug_printf_once(args) \ 111b8e80941Smrg do { \ 112b8e80941Smrg static boolean once = TRUE; \ 113b8e80941Smrg if (once) { \ 114b8e80941Smrg once = FALSE; \ 115b8e80941Smrg debug_printf args; \ 116b8e80941Smrg } \ 117b8e80941Smrg } while (0) 118b8e80941Smrg 119b8e80941Smrg 120b8e80941Smrg#ifdef DEBUG 121b8e80941Smrg#define debug_vprintf(_format, _ap) _debug_vprintf(_format, _ap) 122b8e80941Smrg#else 123b8e80941Smrg#define debug_vprintf(_format, _ap) ((void)0) 124b8e80941Smrg#endif 125b8e80941Smrg 126b8e80941Smrg 127b8e80941Smrg#ifdef DEBUG 128b8e80941Smrg/** 129b8e80941Smrg * Dump a blob in hex to the same place that debug_printf sends its 130b8e80941Smrg * messages. 131b8e80941Smrg */ 132b8e80941Smrgvoid debug_print_blob( const char *name, const void *blob, unsigned size ); 133b8e80941Smrg#else 134b8e80941Smrg#define debug_print_blob(_name, _blob, _size) ((void)0) 135b8e80941Smrg#endif 136b8e80941Smrg 137b8e80941Smrg 138b8e80941Smrg/** 139b8e80941Smrg * Disable interactive error message boxes. 140b8e80941Smrg * 141b8e80941Smrg * Should be called as soon as possible for effectiveness. 142b8e80941Smrg */ 143b8e80941Smrgvoid 144b8e80941Smrgdebug_disable_error_message_boxes(void); 145b8e80941Smrg 146b8e80941Smrg 147b8e80941Smrg/** 148b8e80941Smrg * Hard-coded breakpoint. 149b8e80941Smrg */ 150b8e80941Smrg#ifdef DEBUG 151b8e80941Smrg#define debug_break() os_break() 152b8e80941Smrg#else /* !DEBUG */ 153b8e80941Smrg#define debug_break() ((void)0) 154b8e80941Smrg#endif /* !DEBUG */ 155b8e80941Smrg 156b8e80941Smrg 157b8e80941Smrglong 158b8e80941Smrgdebug_get_num_option(const char *name, long dfault); 159b8e80941Smrg 160b8e80941Smrg#ifdef _MSC_VER 161b8e80941Smrg__declspec(noreturn) 162b8e80941Smrg#endif 163b8e80941Smrgvoid _debug_assert_fail(const char *expr, 164b8e80941Smrg const char *file, 165b8e80941Smrg unsigned line, 166b8e80941Smrg const char *function) 167b8e80941Smrg#if defined(__GNUC__) && !defined(DEBUG) 168b8e80941Smrg __attribute__((noreturn)) 169b8e80941Smrg#endif 170b8e80941Smrg; 171b8e80941Smrg 172b8e80941Smrg 173b8e80941Smrg/** 174b8e80941Smrg * Assert macro 175b8e80941Smrg * 176b8e80941Smrg * Do not expect that the assert call terminates -- errors must be handled 177b8e80941Smrg * regardless of assert behavior. 178b8e80941Smrg * 179b8e80941Smrg * For non debug builds the assert macro will expand to a no-op, so do not 180b8e80941Smrg * call functions with side effects in the assert expression. 181b8e80941Smrg */ 182b8e80941Smrg#ifndef NDEBUG 183b8e80941Smrg#define debug_assert(expr) ((expr) ? (void)0 : _debug_assert_fail(#expr, __FILE__, __LINE__, __FUNCTION__)) 184b8e80941Smrg#else 185b8e80941Smrg#define debug_assert(expr) (void)(0 && (expr)) 186b8e80941Smrg#endif 187b8e80941Smrg 188b8e80941Smrg 189b8e80941Smrg/** Override standard assert macro */ 190b8e80941Smrg#ifdef assert 191b8e80941Smrg#undef assert 192b8e80941Smrg#endif 193b8e80941Smrg#define assert(expr) debug_assert(expr) 194b8e80941Smrg 195b8e80941Smrg 196b8e80941Smrg/** 197b8e80941Smrg * Output the current function name. 198b8e80941Smrg */ 199b8e80941Smrg#ifdef DEBUG 200b8e80941Smrg#define debug_checkpoint() \ 201b8e80941Smrg _debug_printf("%s\n", __FUNCTION__) 202b8e80941Smrg#else 203b8e80941Smrg#define debug_checkpoint() \ 204b8e80941Smrg ((void)0) 205b8e80941Smrg#endif 206b8e80941Smrg 207b8e80941Smrg 208b8e80941Smrg/** 209b8e80941Smrg * Output the full source code position. 210b8e80941Smrg */ 211b8e80941Smrg#ifdef DEBUG 212b8e80941Smrg#define debug_checkpoint_full() \ 213b8e80941Smrg _debug_printf("%s:%u:%s\n", __FILE__, __LINE__, __FUNCTION__) 214b8e80941Smrg#else 215b8e80941Smrg#define debug_checkpoint_full() \ 216b8e80941Smrg ((void)0) 217b8e80941Smrg#endif 218b8e80941Smrg 219b8e80941Smrg 220b8e80941Smrg/** 221b8e80941Smrg * Output a warning message. Muted on release version. 222b8e80941Smrg */ 223b8e80941Smrg#ifdef DEBUG 224b8e80941Smrg#define debug_warning(__msg) \ 225b8e80941Smrg _debug_printf("%s:%u:%s: warning: %s\n", __FILE__, __LINE__, __FUNCTION__, __msg) 226b8e80941Smrg#else 227b8e80941Smrg#define debug_warning(__msg) \ 228b8e80941Smrg ((void)0) 229b8e80941Smrg#endif 230b8e80941Smrg 231b8e80941Smrg 232b8e80941Smrg/** 233b8e80941Smrg * Emit a warning message, but only once. 234b8e80941Smrg */ 235b8e80941Smrg#ifdef DEBUG 236b8e80941Smrg#define debug_warn_once(__msg) \ 237b8e80941Smrg do { \ 238b8e80941Smrg static bool warned = FALSE; \ 239b8e80941Smrg if (!warned) { \ 240b8e80941Smrg _debug_printf("%s:%u:%s: one time warning: %s\n", \ 241b8e80941Smrg __FILE__, __LINE__, __FUNCTION__, __msg); \ 242b8e80941Smrg warned = TRUE; \ 243b8e80941Smrg } \ 244b8e80941Smrg } while (0) 245b8e80941Smrg#else 246b8e80941Smrg#define debug_warn_once(__msg) \ 247b8e80941Smrg ((void)0) 248b8e80941Smrg#endif 249b8e80941Smrg 250b8e80941Smrg 251b8e80941Smrg/** 252b8e80941Smrg * Output an error message. Not muted on release version. 253b8e80941Smrg */ 254b8e80941Smrg#ifdef DEBUG 255b8e80941Smrg#define debug_error(__msg) \ 256b8e80941Smrg _debug_printf("%s:%u:%s: error: %s\n", __FILE__, __LINE__, __FUNCTION__, __msg) 257b8e80941Smrg#else 258b8e80941Smrg#define debug_error(__msg) \ 259b8e80941Smrg _debug_printf("error: %s\n", __msg) 260b8e80941Smrg#endif 261b8e80941Smrg 262b8e80941Smrg/** 263b8e80941Smrg * Output a debug log message to the debug info callback. 264b8e80941Smrg */ 265b8e80941Smrg#define pipe_debug_message(cb, type, fmt, ...) do { \ 266b8e80941Smrg static unsigned id = 0; \ 267b8e80941Smrg if ((cb) && (cb)->debug_message) { \ 268b8e80941Smrg _pipe_debug_message(cb, &id, \ 269b8e80941Smrg PIPE_DEBUG_TYPE_ ## type, \ 270b8e80941Smrg fmt, ##__VA_ARGS__); \ 271b8e80941Smrg } \ 272b8e80941Smrg} while (0) 273b8e80941Smrg 274b8e80941Smrgstruct pipe_debug_callback; 275b8e80941Smrg 276b8e80941Smrgvoid 277b8e80941Smrg_pipe_debug_message( 278b8e80941Smrg struct pipe_debug_callback *cb, 279b8e80941Smrg unsigned *id, 280b8e80941Smrg enum pipe_debug_type type, 281b8e80941Smrg const char *fmt, ...) _util_printf_format(4, 5); 282b8e80941Smrg 283b8e80941Smrg 284b8e80941Smrg/** 285b8e80941Smrg * Used by debug_dump_enum and debug_dump_flags to describe symbols. 286b8e80941Smrg */ 287b8e80941Smrgstruct debug_named_value 288b8e80941Smrg{ 289b8e80941Smrg const char *name; 290b8e80941Smrg uint64_t value; 291b8e80941Smrg const char *desc; 292b8e80941Smrg}; 293b8e80941Smrg 294b8e80941Smrg 295b8e80941Smrg/** 296b8e80941Smrg * Some C pre-processor magic to simplify creating named values. 297b8e80941Smrg * 298b8e80941Smrg * Example: 299b8e80941Smrg * @code 300b8e80941Smrg * static const debug_named_value my_names[] = { 301b8e80941Smrg * DEBUG_NAMED_VALUE(MY_ENUM_VALUE_X), 302b8e80941Smrg * DEBUG_NAMED_VALUE(MY_ENUM_VALUE_Y), 303b8e80941Smrg * DEBUG_NAMED_VALUE(MY_ENUM_VALUE_Z), 304b8e80941Smrg * DEBUG_NAMED_VALUE_END 305b8e80941Smrg * }; 306b8e80941Smrg * 307b8e80941Smrg * ... 308b8e80941Smrg * debug_printf("%s = %s\n", 309b8e80941Smrg * name, 310b8e80941Smrg * debug_dump_enum(my_names, my_value)); 311b8e80941Smrg * ... 312b8e80941Smrg * @endcode 313b8e80941Smrg */ 314b8e80941Smrg#define DEBUG_NAMED_VALUE(__symbol) {#__symbol, (unsigned long)__symbol, NULL} 315b8e80941Smrg#define DEBUG_NAMED_VALUE_WITH_DESCRIPTION(__symbol, __desc) {#__symbol, (unsigned long)__symbol, __desc} 316b8e80941Smrg#define DEBUG_NAMED_VALUE_END {NULL, 0, NULL} 317b8e80941Smrg 318b8e80941Smrg 319b8e80941Smrg/** 320b8e80941Smrg * Convert a enum value to a string. 321b8e80941Smrg */ 322b8e80941Smrgconst char * 323b8e80941Smrgdebug_dump_enum(const struct debug_named_value *names, 324b8e80941Smrg unsigned long value); 325b8e80941Smrg 326b8e80941Smrgconst char * 327b8e80941Smrgdebug_dump_enum_noprefix(const struct debug_named_value *names, 328b8e80941Smrg const char *prefix, 329b8e80941Smrg unsigned long value); 330b8e80941Smrg 331b8e80941Smrg 332b8e80941Smrg/** 333b8e80941Smrg * Convert binary flags value to a string. 334b8e80941Smrg */ 335b8e80941Smrgconst char * 336b8e80941Smrgdebug_dump_flags(const struct debug_named_value *names, 337b8e80941Smrg unsigned long value); 338b8e80941Smrg 339b8e80941Smrg 340b8e80941Smrg/** 341b8e80941Smrg * Function enter exit loggers 342b8e80941Smrg */ 343b8e80941Smrg#ifdef DEBUG 344b8e80941Smrgint debug_funclog_enter(const char* f, const int line, const char* file); 345b8e80941Smrgvoid debug_funclog_exit(const char* f, const int line, const char* file); 346b8e80941Smrgvoid debug_funclog_enter_exit(const char* f, const int line, const char* file); 347b8e80941Smrg 348b8e80941Smrg#define DEBUG_FUNCLOG_ENTER() \ 349b8e80941Smrg int __debug_decleration_work_around = \ 350b8e80941Smrg debug_funclog_enter(__FUNCTION__, __LINE__, __FILE__) 351b8e80941Smrg#define DEBUG_FUNCLOG_EXIT() \ 352b8e80941Smrg do { \ 353b8e80941Smrg (void)__debug_decleration_work_around; \ 354b8e80941Smrg debug_funclog_exit(__FUNCTION__, __LINE__, __FILE__); \ 355b8e80941Smrg return; \ 356b8e80941Smrg } while(0) 357b8e80941Smrg#define DEBUG_FUNCLOG_EXIT_RET(ret) \ 358b8e80941Smrg do { \ 359b8e80941Smrg (void)__debug_decleration_work_around; \ 360b8e80941Smrg debug_funclog_exit(__FUNCTION__, __LINE__, __FILE__); \ 361b8e80941Smrg return ret; \ 362b8e80941Smrg } while(0) 363b8e80941Smrg#define DEBUG_FUNCLOG_ENTER_EXIT() \ 364b8e80941Smrg debug_funclog_enter_exit(__FUNCTION__, __LINE__, __FILE__) 365b8e80941Smrg 366b8e80941Smrg#else 367b8e80941Smrg#define DEBUG_FUNCLOG_ENTER() \ 368b8e80941Smrg int __debug_decleration_work_around 369b8e80941Smrg#define DEBUG_FUNCLOG_EXIT() \ 370b8e80941Smrg do { (void)__debug_decleration_work_around; return; } while(0) 371b8e80941Smrg#define DEBUG_FUNCLOG_EXIT_RET(ret) \ 372b8e80941Smrg do { (void)__debug_decleration_work_around; return ret; } while(0) 373b8e80941Smrg#define DEBUG_FUNCLOG_ENTER_EXIT() 374b8e80941Smrg#endif 375b8e80941Smrg 376b8e80941Smrg 377b8e80941Smrg/** 378b8e80941Smrg * Get option. 379b8e80941Smrg * 380b8e80941Smrg * It is an alias for getenv on Linux. 381b8e80941Smrg * 382b8e80941Smrg * On Windows it reads C:\gallium.cfg, which is a text file with CR+LF line 383b8e80941Smrg * endings with one option per line as 384b8e80941Smrg * 385b8e80941Smrg * NAME=value 386b8e80941Smrg * 387b8e80941Smrg * This file must be terminated with an extra empty line. 388b8e80941Smrg */ 389b8e80941Smrgconst char * 390b8e80941Smrgdebug_get_option(const char *name, const char *dfault); 391b8e80941Smrg 392b8e80941Smrgboolean 393b8e80941Smrgdebug_get_bool_option(const char *name, boolean dfault); 394b8e80941Smrg 395b8e80941Smrglong 396b8e80941Smrgdebug_get_num_option(const char *name, long dfault); 397b8e80941Smrg 398b8e80941Smrguint64_t 399b8e80941Smrgdebug_get_flags_option(const char *name, 400b8e80941Smrg const struct debug_named_value *flags, 401b8e80941Smrg uint64_t dfault); 402b8e80941Smrg 403b8e80941Smrg#define DEBUG_GET_ONCE_OPTION(suffix, name, dfault) \ 404b8e80941Smrgstatic const char * \ 405b8e80941Smrgdebug_get_option_ ## suffix (void) \ 406b8e80941Smrg{ \ 407b8e80941Smrg static boolean first = TRUE; \ 408b8e80941Smrg static const char * value; \ 409b8e80941Smrg if (first) { \ 410b8e80941Smrg first = FALSE; \ 411b8e80941Smrg value = debug_get_option(name, dfault); \ 412b8e80941Smrg } \ 413b8e80941Smrg return value; \ 414b8e80941Smrg} 415b8e80941Smrg 416b8e80941Smrg#define DEBUG_GET_ONCE_BOOL_OPTION(sufix, name, dfault) \ 417b8e80941Smrgstatic boolean \ 418b8e80941Smrgdebug_get_option_ ## sufix (void) \ 419b8e80941Smrg{ \ 420b8e80941Smrg static boolean first = TRUE; \ 421b8e80941Smrg static boolean value; \ 422b8e80941Smrg if (first) { \ 423b8e80941Smrg first = FALSE; \ 424b8e80941Smrg value = debug_get_bool_option(name, dfault); \ 425b8e80941Smrg } \ 426b8e80941Smrg return value; \ 427b8e80941Smrg} 428b8e80941Smrg 429b8e80941Smrg#define DEBUG_GET_ONCE_NUM_OPTION(sufix, name, dfault) \ 430b8e80941Smrgstatic long \ 431b8e80941Smrgdebug_get_option_ ## sufix (void) \ 432b8e80941Smrg{ \ 433b8e80941Smrg static boolean first = TRUE; \ 434b8e80941Smrg static long value; \ 435b8e80941Smrg if (first) { \ 436b8e80941Smrg first = FALSE; \ 437b8e80941Smrg value = debug_get_num_option(name, dfault); \ 438b8e80941Smrg } \ 439b8e80941Smrg return value; \ 440b8e80941Smrg} 441b8e80941Smrg 442b8e80941Smrg#define DEBUG_GET_ONCE_FLAGS_OPTION(sufix, name, flags, dfault) \ 443b8e80941Smrgstatic unsigned long \ 444b8e80941Smrgdebug_get_option_ ## sufix (void) \ 445b8e80941Smrg{ \ 446b8e80941Smrg static boolean first = TRUE; \ 447b8e80941Smrg static unsigned long value; \ 448b8e80941Smrg if (first) { \ 449b8e80941Smrg first = FALSE; \ 450b8e80941Smrg value = debug_get_flags_option(name, flags, dfault); \ 451b8e80941Smrg } \ 452b8e80941Smrg return value; \ 453b8e80941Smrg} 454b8e80941Smrg 455b8e80941Smrg 456b8e80941Smrg#ifdef __cplusplus 457b8e80941Smrg} 458b8e80941Smrg#endif 459b8e80941Smrg 460b8e80941Smrg#endif /* U_DEBUG_H_ */ 461