1/* ide-debug.h.in 2 * 3 * Copyright (C) 2015 Christian Hergert <christian@hergert.me> 4 * 5 * This program is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation, either version 3 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19#ifndef IDE_DEBUG_H 20#define IDE_DEBUG_H 21 22#include <execinfo.h> 23#include <glib.h> 24 25#include "ide-version-macros.h" 26 27G_BEGIN_DECLS 28 29/** 30 * SECTION:ide-debug 31 * @title: Debug logging and tracing 32 * @short_description: tracing and debug facilities for Builder and plugins 33 * 34 * The debug macros such as %IDE_ENTRY, %IDE_EXIT, and %IDE_RETURN provide 35 * helpers for tracing Builder and plugins at runtime. 36 * 37 * These tracing macros will compile out when Builder is configured for a 38 * release build. Otherwise, running Builder with the "-vvvv" command line 39 * argument will show tracing output. 40 * 41 * Since: 3.18 42 */ 43 44/** 45 * IDE_ENTRY: (skip) 46 * 47 * Traces the entry into a function. Place this at the beginning of your 48 * function above pre-condition checks. 49 * 50 * Since: 3.18 51 */ 52 53/** 54 * IDE_EXIT: (skip) 55 * 56 * Traces the exit from a function. Use this instead of "return" to return 57 * and log the function exiting. 58 * 59 * Since: 3.18 60 */ 61 62/** 63 * IDE_RETURN: (skip) 64 * 65 * Similar to %IDE_EXIT but allows providing a return value. 66 * 67 * Since: 3.18 68 */ 69 70/** 71 * IDE_GOTO: (skip) 72 * @_l: the label to jump to 73 * 74 * Appends to the jump to label to the tracing log and then jumps 75 * to the label @_l. 76 * 77 * Since: 3.18 78 */ 79 80/** 81 * IDE_TODO: (skip) 82 * @_msg: the message to append to the trace log 83 * 84 * Appends to the tracing log that unsupported code has been 85 * reached. 86 * 87 * Since: 3.18 88 */ 89 90/** 91 * IDE_PROBE: (skip) 92 * 93 * Appends to the tracing log that a line of code was reached. 94 * 95 * Since: 3.18 96 */ 97 98/** 99 * IDE_TRACE_MSG: (skip) 100 * 101 * Similar to %IDE_PROBE but allows specifying a log message. 102 * 103 * Since: 3.18 104 */ 105 106#ifndef IDE_ENABLE_TRACE 107# define IDE_ENABLE_TRACE @ENABLE_TRACING@ 108#endif 109#if IDE_ENABLE_TRACE != 1 110# undef IDE_ENABLE_TRACE 111#endif 112 113/** 114 * IDE_LOG_LEVEL_TRACE: (skip) 115 */ 116#ifndef IDE_LOG_LEVEL_TRACE 117# define IDE_LOG_LEVEL_TRACE ((GLogLevelFlags)(1 << G_LOG_LEVEL_USER_SHIFT)) 118#endif 119 120#ifdef IDE_ENABLE_TRACE 121_IDE_EXTERN 122void ide_trace_function (const gchar *strfunc, 123 gint64 begin_time_usec, 124 gint64 end_time_usec); 125# define IDE_TRACE_MSG(fmt, ...) \ 126 g_log(G_LOG_DOMAIN, IDE_LOG_LEVEL_TRACE, " MSG: %s():%d: " fmt, \ 127 G_STRFUNC, __LINE__, ##__VA_ARGS__) 128# define IDE_PROBE \ 129 g_log(G_LOG_DOMAIN, IDE_LOG_LEVEL_TRACE, "PROBE: %s():%d", \ 130 G_STRFUNC, __LINE__) 131# define IDE_TODO(_msg) \ 132 g_log(G_LOG_DOMAIN, IDE_LOG_LEVEL_TRACE, " TODO: %s():%d: %s", \ 133 G_STRFUNC, __LINE__, _msg) 134# define IDE_ENTRY \ 135 gint64 __trace_begin_time = g_get_monotonic_time (); \ 136 g_log(G_LOG_DOMAIN, IDE_LOG_LEVEL_TRACE, "ENTRY: %s():%d", \ 137 G_STRFUNC, __LINE__) 138# define IDE_EXIT \ 139 G_STMT_START { \ 140 ide_trace_function (G_STRFUNC, \ 141 __trace_begin_time, \ 142 g_get_monotonic_time ()); \ 143 g_log(G_LOG_DOMAIN, IDE_LOG_LEVEL_TRACE, " EXIT: %s():%d", \ 144 G_STRFUNC, __LINE__); \ 145 return; \ 146 } G_STMT_END 147# define IDE_GOTO(_l) \ 148 G_STMT_START { \ 149 g_log(G_LOG_DOMAIN, IDE_LOG_LEVEL_TRACE, " GOTO: %s():%d ("#_l")", \ 150 G_STRFUNC, __LINE__); \ 151 goto _l; \ 152 } G_STMT_END 153# define IDE_RETURN(_r) \ 154 G_STMT_START { \ 155 ide_trace_function (G_STRFUNC, \ 156 __trace_begin_time, \ 157 g_get_monotonic_time ()); \ 158 g_log(G_LOG_DOMAIN, IDE_LOG_LEVEL_TRACE, " EXIT: %s():%d ", \ 159 G_STRFUNC, __LINE__); \ 160 return _r; \ 161 } G_STMT_END 162# define IDE_BACKTRACE \ 163 G_STMT_START { \ 164 gpointer btbuf[64]; \ 165 int btbuflen = backtrace (btbuf, G_N_ELEMENTS (btbuf)); \ 166 char **symnames = backtrace_symbols (btbuf, btbuflen); \ 167 for (guint _i = 0; _i < btbuflen; _i++) { \ 168 g_log(G_LOG_DOMAIN, IDE_LOG_LEVEL_TRACE, "TRACE: [%-2d]: %s", \ 169 _i, symnames[_i]); \ 170 } \ 171 free (symnames); \ 172 } G_STMT_END 173#else 174# define IDE_TODO(_msg) G_STMT_START { } G_STMT_END 175# define IDE_PROBE G_STMT_START { } G_STMT_END 176# define IDE_TRACE_MSG(fmt, ...) G_STMT_START { } G_STMT_END 177# define IDE_ENTRY G_STMT_START { } G_STMT_END 178# define IDE_GOTO(_l) G_STMT_START { goto _l; } G_STMT_END 179# define IDE_EXIT G_STMT_START { return; } G_STMT_END 180# define IDE_RETURN(_r) G_STMT_START { return _r; } G_STMT_END 181# define IDE_BACKTRACE G_STMT_START { } G_STMT_END 182#endif 183 184#define _IDE_BUG(Component, Description, File, Line, Func, ...) \ 185 G_STMT_START { \ 186 g_printerr ("-----------------------------------------------------------------\n"); \ 187 g_printerr ("You've found a bug in Builder or one of its dependent libraries.\n"); \ 188 g_printerr ("Please help us help you by filing a bug report at:\n"); \ 189 g_printerr ("\n"); \ 190 g_printerr ("@BUGREPORT_URL@&component=%s\n", Component); \ 191 g_printerr ("\n"); \ 192 g_printerr ("%s:%d in function %s()\n", File, Line, Func); \ 193 g_printerr ("\n"); \ 194 g_printerr (Description"\n", ##__VA_ARGS__); \ 195 g_printerr ("-----------------------------------------------------------------\n"); \ 196 } G_STMT_END 197#define IDE_BUG(Component, Description, ...) \ 198 _IDE_BUG(Component, Description, __FILE__, __LINE__, G_STRFUNC, ##__VA_ARGS__) 199 200G_END_DECLS 201 202#endif /* IDE_DEBUG_H */ 203