17d62b00eSchristos /* Declarations for debug printing functions. 27d62b00eSchristos 3*6881a400Schristos Copyright (C) 2014-2023 Free Software Foundation, Inc. 47d62b00eSchristos 57d62b00eSchristos This file is part of GDB. 67d62b00eSchristos 77d62b00eSchristos This program is free software; you can redistribute it and/or modify 87d62b00eSchristos it under the terms of the GNU General Public License as published by 97d62b00eSchristos the Free Software Foundation; either version 3 of the License, or 107d62b00eSchristos (at your option) any later version. 117d62b00eSchristos 127d62b00eSchristos This program is distributed in the hope that it will be useful, 137d62b00eSchristos but WITHOUT ANY WARRANTY; without even the implied warranty of 147d62b00eSchristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 157d62b00eSchristos GNU General Public License for more details. 167d62b00eSchristos 177d62b00eSchristos You should have received a copy of the GNU General Public License 187d62b00eSchristos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 197d62b00eSchristos 207d62b00eSchristos #ifndef COMMON_COMMON_DEBUG_H 217d62b00eSchristos #define COMMON_COMMON_DEBUG_H 227d62b00eSchristos 23*6881a400Schristos #include "gdbsupport/gdb_optional.h" 24*6881a400Schristos #include "gdbsupport/preprocessor.h" 25*6881a400Schristos 26*6881a400Schristos #include <stdarg.h> 27*6881a400Schristos 287d62b00eSchristos /* Set to true to enable debugging of hardware breakpoint/ 297d62b00eSchristos watchpoint support code. */ 307d62b00eSchristos 317d62b00eSchristos extern bool show_debug_regs; 327d62b00eSchristos 337d62b00eSchristos /* Print a formatted message to the appropriate channel for 347d62b00eSchristos debugging output for the client. */ 357d62b00eSchristos 367d62b00eSchristos extern void debug_printf (const char *format, ...) 377d62b00eSchristos ATTRIBUTE_PRINTF (1, 2); 387d62b00eSchristos 397d62b00eSchristos /* Print a formatted message to the appropriate channel for 407d62b00eSchristos debugging output for the client. This function must be 417d62b00eSchristos provided by the client. */ 427d62b00eSchristos 437d62b00eSchristos extern void debug_vprintf (const char *format, va_list ap) 447d62b00eSchristos ATTRIBUTE_PRINTF (1, 0); 457d62b00eSchristos 46*6881a400Schristos /* Print a debug statement prefixed with the module and function name, and 47*6881a400Schristos with a newline at the end. */ 48*6881a400Schristos 49*6881a400Schristos extern void ATTRIBUTE_PRINTF (3, 4) debug_prefixed_printf 50*6881a400Schristos (const char *module, const char *func, const char *format, ...); 51*6881a400Schristos 52*6881a400Schristos /* Print a debug statement prefixed with the module and function name, and 53*6881a400Schristos with a newline at the end. */ 54*6881a400Schristos 55*6881a400Schristos extern void ATTRIBUTE_PRINTF (3, 0) debug_prefixed_vprintf 56*6881a400Schristos (const char *module, const char *func, const char *format, va_list args); 57*6881a400Schristos 58*6881a400Schristos /* Helper to define "_debug_print" macros. 59*6881a400Schristos 60*6881a400Schristos DEBUG_ENABLED_COND is an expression that evaluates to true if the debugging 61*6881a400Schristos statement is enabled and should be printed. 62*6881a400Schristos 63*6881a400Schristos The other arguments, as well as the name of the current function, are 64*6881a400Schristos forwarded to debug_prefixed_printf. */ 65*6881a400Schristos 66*6881a400Schristos #define debug_prefixed_printf_cond(debug_enabled_cond, module, fmt, ...) \ 67*6881a400Schristos do \ 68*6881a400Schristos { \ 69*6881a400Schristos if (debug_enabled_cond) \ 70*6881a400Schristos debug_prefixed_printf (module, __func__, fmt, ##__VA_ARGS__); \ 71*6881a400Schristos } \ 72*6881a400Schristos while (0) 73*6881a400Schristos 74*6881a400Schristos #define debug_prefixed_printf_cond_nofunc(debug_enabled_cond, module, fmt, ...) \ 75*6881a400Schristos do \ 76*6881a400Schristos { \ 77*6881a400Schristos if (debug_enabled_cond) \ 78*6881a400Schristos debug_prefixed_printf (module, nullptr, fmt, ##__VA_ARGS__); \ 79*6881a400Schristos } \ 80*6881a400Schristos while (0) 81*6881a400Schristos 82*6881a400Schristos /* Nesting depth of scoped_debug_start_end objects. */ 83*6881a400Schristos 84*6881a400Schristos extern int debug_print_depth; 85*6881a400Schristos 86*6881a400Schristos /* Print a message on construction and destruction, to denote the start and end 87*6881a400Schristos of an operation. Increment DEBUG_PRINT_DEPTH on construction and decrement 88*6881a400Schristos it on destruction, such that nested debug statements will be printed with 89*6881a400Schristos an indent and appear "inside" this one. */ 90*6881a400Schristos 91*6881a400Schristos template<typename PT> 92*6881a400Schristos struct scoped_debug_start_end 93*6881a400Schristos { 94*6881a400Schristos /* DEBUG_ENABLED is a reference to a variable that indicates whether debugging 95*6881a400Schristos is enabled, so if the debug statements should be printed. Is is read 96*6881a400Schristos separately at construction and destruction, such that the start statement 97*6881a400Schristos could be printed but not the end statement, or vice-versa. 98*6881a400Schristos 99*6881a400Schristos DEBUG_ENABLED should either be of type 'bool &' or should be a type 100*6881a400Schristos that can be invoked. 101*6881a400Schristos 102*6881a400Schristos MODULE and FUNC are forwarded to debug_prefixed_printf. 103*6881a400Schristos 104*6881a400Schristos START_PREFIX and END_PREFIX are the statements to print on construction and 105*6881a400Schristos destruction, respectively. 106*6881a400Schristos 107*6881a400Schristos If the FMT format string is non-nullptr, then a `: ` is appended to the 108*6881a400Schristos messages, followed by the rendering of that format string with ARGS. 109*6881a400Schristos The format string is rendered during construction and is re-used as is 110*6881a400Schristos for the message on exit. */ 111*6881a400Schristos 112*6881a400Schristos scoped_debug_start_end (PT &debug_enabled, const char *module, 113*6881a400Schristos const char *func, const char *start_prefix, 114*6881a400Schristos const char *end_prefix, const char *fmt, 115*6881a400Schristos va_list args) 116*6881a400Schristos ATTRIBUTE_NULL_PRINTF (7, 0) 117*6881a400Schristos : m_debug_enabled (debug_enabled), 118*6881a400Schristos m_module (module), 119*6881a400Schristos m_func (func), 120*6881a400Schristos m_end_prefix (end_prefix), 121*6881a400Schristos m_with_format (fmt != nullptr) 122*6881a400Schristos { 123*6881a400Schristos if (is_debug_enabled ()) 124*6881a400Schristos { 125*6881a400Schristos if (fmt != nullptr) 126*6881a400Schristos { 127*6881a400Schristos m_msg = string_vprintf (fmt, args); 128*6881a400Schristos debug_prefixed_printf (m_module, m_func, "%s: %s", 129*6881a400Schristos start_prefix, m_msg->c_str ()); 130*6881a400Schristos } 131*6881a400Schristos else 132*6881a400Schristos debug_prefixed_printf (m_module, m_func, "%s", start_prefix); 133*6881a400Schristos 134*6881a400Schristos ++debug_print_depth; 135*6881a400Schristos m_must_decrement_print_depth = true; 136*6881a400Schristos } 137*6881a400Schristos } 138*6881a400Schristos 139*6881a400Schristos DISABLE_COPY_AND_ASSIGN (scoped_debug_start_end); 140*6881a400Schristos 141*6881a400Schristos scoped_debug_start_end (scoped_debug_start_end &&other) = default; 142*6881a400Schristos 143*6881a400Schristos ~scoped_debug_start_end () 144*6881a400Schristos { 145*6881a400Schristos if (m_must_decrement_print_depth) 146*6881a400Schristos { 147*6881a400Schristos gdb_assert (debug_print_depth > 0); 148*6881a400Schristos --debug_print_depth; 149*6881a400Schristos } 150*6881a400Schristos 151*6881a400Schristos if (is_debug_enabled ()) 152*6881a400Schristos { 153*6881a400Schristos if (m_with_format) 154*6881a400Schristos { 155*6881a400Schristos if (m_msg.has_value ()) 156*6881a400Schristos debug_prefixed_printf (m_module, m_func, "%s: %s", 157*6881a400Schristos m_end_prefix, m_msg->c_str ()); 158*6881a400Schristos else 159*6881a400Schristos { 160*6881a400Schristos /* A format string was passed to the constructor, but debug 161*6881a400Schristos control variable wasn't set at the time, so we don't have the 162*6881a400Schristos rendering of the format string. */ 163*6881a400Schristos debug_prefixed_printf (m_module, m_func, "%s: <%s debugging was not enabled on entry>", 164*6881a400Schristos m_end_prefix, m_module); 165*6881a400Schristos } 166*6881a400Schristos } 167*6881a400Schristos else 168*6881a400Schristos debug_prefixed_printf (m_module, m_func, "%s", m_end_prefix); 169*6881a400Schristos } 170*6881a400Schristos } 171*6881a400Schristos 172*6881a400Schristos private: 173*6881a400Schristos 174*6881a400Schristos /* This function is specialized based on the type PT. Returns true if 175*6881a400Schristos M_DEBUG_ENABLED indicates this debug setting is enabled, otherwise, 176*6881a400Schristos return false. */ 177*6881a400Schristos bool is_debug_enabled () const; 178*6881a400Schristos 179*6881a400Schristos /* Reference to the debug setting, or a callback that can read the debug 180*6881a400Schristos setting. Access the value of this by calling IS_DEBUG_ENABLED. */ 181*6881a400Schristos PT &m_debug_enabled; 182*6881a400Schristos 183*6881a400Schristos const char *m_module; 184*6881a400Schristos const char *m_func; 185*6881a400Schristos const char *m_end_prefix; 186*6881a400Schristos 187*6881a400Schristos /* The result of formatting the format string in the constructor. */ 188*6881a400Schristos gdb::optional<std::string> m_msg; 189*6881a400Schristos 190*6881a400Schristos /* True is a non-nullptr format was passed to the constructor. */ 191*6881a400Schristos bool m_with_format; 192*6881a400Schristos 193*6881a400Schristos /* This is used to handle the case where debugging is enabled during 194*6881a400Schristos construction but not during destruction, or vice-versa. We want to make 195*6881a400Schristos sure there are as many increments are there are decrements. */ 196*6881a400Schristos bool m_must_decrement_print_depth = false; 197*6881a400Schristos }; 198*6881a400Schristos 199*6881a400Schristos /* Implementation of is_debug_enabled when PT is an invokable type. */ 200*6881a400Schristos 201*6881a400Schristos template<typename PT> 202*6881a400Schristos inline bool 203*6881a400Schristos scoped_debug_start_end<PT>::is_debug_enabled () const 204*6881a400Schristos { 205*6881a400Schristos return m_debug_enabled (); 206*6881a400Schristos } 207*6881a400Schristos 208*6881a400Schristos /* Implementation of is_debug_enabled when PT is 'bool &'. */ 209*6881a400Schristos 210*6881a400Schristos template<> 211*6881a400Schristos inline bool 212*6881a400Schristos scoped_debug_start_end<bool &>::is_debug_enabled () const 213*6881a400Schristos { 214*6881a400Schristos return m_debug_enabled; 215*6881a400Schristos } 216*6881a400Schristos 217*6881a400Schristos /* Wrapper around the scoped_debug_start_end constructor to allow the 218*6881a400Schristos caller to create an object using 'auto' type, the actual type will be 219*6881a400Schristos based on the type of the PRED argument. All arguments are forwarded to 220*6881a400Schristos the scoped_debug_start_end constructor. */ 221*6881a400Schristos 222*6881a400Schristos template<typename PT> 223*6881a400Schristos static inline scoped_debug_start_end<PT &> ATTRIBUTE_NULL_PRINTF (6, 7) 224*6881a400Schristos make_scoped_debug_start_end (PT &&pred, const char *module, const char *func, 225*6881a400Schristos const char *start_prefix, 226*6881a400Schristos const char *end_prefix, const char *fmt, ...) 227*6881a400Schristos { 228*6881a400Schristos va_list args; 229*6881a400Schristos va_start (args, fmt); 230*6881a400Schristos auto res = scoped_debug_start_end<PT &> (pred, module, func, start_prefix, 231*6881a400Schristos end_prefix, fmt, args); 232*6881a400Schristos va_end (args); 233*6881a400Schristos 234*6881a400Schristos return res; 235*6881a400Schristos } 236*6881a400Schristos 237*6881a400Schristos /* Helper to define a module-specific start/end debug macro. */ 238*6881a400Schristos 239*6881a400Schristos #define scoped_debug_start_end(debug_enabled, module, fmt, ...) \ 240*6881a400Schristos auto CONCAT(scoped_debug_start_end, __LINE__) \ 241*6881a400Schristos = make_scoped_debug_start_end (debug_enabled, module, \ 242*6881a400Schristos __func__, "start", "end", \ 243*6881a400Schristos fmt, ##__VA_ARGS__) 244*6881a400Schristos 245*6881a400Schristos /* Helper to define a module-specific enter/exit debug macro. This is a special 246*6881a400Schristos case of `scoped_debug_start_end` where the start and end messages are "enter" 247*6881a400Schristos and "exit", to denote entry and exit of a function. */ 248*6881a400Schristos 249*6881a400Schristos #define scoped_debug_enter_exit(debug_enabled, module) \ 250*6881a400Schristos auto CONCAT(scoped_debug_start_end, __LINE__) \ 251*6881a400Schristos = make_scoped_debug_start_end (debug_enabled, module, \ 252*6881a400Schristos __func__, "enter", "exit", \ 253*6881a400Schristos nullptr) 254*6881a400Schristos 2557d62b00eSchristos #endif /* COMMON_COMMON_DEBUG_H */ 256