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