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