18dffb485Schristos /* Declarations for debug printing functions. 28dffb485Schristos 3*5ba1f45fSchristos Copyright (C) 2014-2024 Free Software Foundation, Inc. 48dffb485Schristos 58dffb485Schristos This file is part of GDB. 68dffb485Schristos 78dffb485Schristos This program is free software; you can redistribute it and/or modify 88dffb485Schristos it under the terms of the GNU General Public License as published by 98dffb485Schristos the Free Software Foundation; either version 3 of the License, or 108dffb485Schristos (at your option) any later version. 118dffb485Schristos 128dffb485Schristos This program is distributed in the hope that it will be useful, 138dffb485Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of 148dffb485Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 158dffb485Schristos GNU General Public License for more details. 168dffb485Schristos 178dffb485Schristos You should have received a copy of the GNU General Public License 188dffb485Schristos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 198dffb485Schristos 208dffb485Schristos #ifndef COMMON_COMMON_DEBUG_H 218dffb485Schristos #define COMMON_COMMON_DEBUG_H 228dffb485Schristos 23*5ba1f45fSchristos #include <optional> 244b169a6bSchristos #include "gdbsupport/preprocessor.h" 254b169a6bSchristos 264b169a6bSchristos #include <stdarg.h> 274b169a6bSchristos 288dffb485Schristos /* Set to true to enable debugging of hardware breakpoint/ 298dffb485Schristos watchpoint support code. */ 308dffb485Schristos 318dffb485Schristos extern bool show_debug_regs; 328dffb485Schristos 338dffb485Schristos /* Print a formatted message to the appropriate channel for 348dffb485Schristos debugging output for the client. */ 358dffb485Schristos 368dffb485Schristos extern void debug_printf (const char *format, ...) 378dffb485Schristos ATTRIBUTE_PRINTF (1, 2); 388dffb485Schristos 398dffb485Schristos /* Print a formatted message to the appropriate channel for 408dffb485Schristos debugging output for the client. This function must be 418dffb485Schristos provided by the client. */ 428dffb485Schristos 438dffb485Schristos extern void debug_vprintf (const char *format, va_list ap) 448dffb485Schristos ATTRIBUTE_PRINTF (1, 0); 458dffb485Schristos 464b169a6bSchristos /* Print a debug statement prefixed with the module and function name, and 474b169a6bSchristos with a newline at the end. */ 484b169a6bSchristos 494b169a6bSchristos extern void ATTRIBUTE_PRINTF (3, 4) debug_prefixed_printf 504b169a6bSchristos (const char *module, const char *func, const char *format, ...); 514b169a6bSchristos 524b169a6bSchristos /* Print a debug statement prefixed with the module and function name, and 534b169a6bSchristos with a newline at the end. */ 544b169a6bSchristos 554b169a6bSchristos extern void ATTRIBUTE_PRINTF (3, 0) debug_prefixed_vprintf 564b169a6bSchristos (const char *module, const char *func, const char *format, va_list args); 574b169a6bSchristos 584b169a6bSchristos /* Helper to define "_debug_print" macros. 594b169a6bSchristos 604b169a6bSchristos DEBUG_ENABLED_COND is an expression that evaluates to true if the debugging 614b169a6bSchristos statement is enabled and should be printed. 624b169a6bSchristos 634b169a6bSchristos The other arguments, as well as the name of the current function, are 644b169a6bSchristos forwarded to debug_prefixed_printf. */ 654b169a6bSchristos 664b169a6bSchristos #define debug_prefixed_printf_cond(debug_enabled_cond, module, fmt, ...) \ 674b169a6bSchristos do \ 684b169a6bSchristos { \ 694b169a6bSchristos if (debug_enabled_cond) \ 704b169a6bSchristos debug_prefixed_printf (module, __func__, fmt, ##__VA_ARGS__); \ 714b169a6bSchristos } \ 724b169a6bSchristos while (0) 734b169a6bSchristos 744b169a6bSchristos #define debug_prefixed_printf_cond_nofunc(debug_enabled_cond, module, fmt, ...) \ 754b169a6bSchristos do \ 764b169a6bSchristos { \ 774b169a6bSchristos if (debug_enabled_cond) \ 784b169a6bSchristos debug_prefixed_printf (module, nullptr, fmt, ##__VA_ARGS__); \ 794b169a6bSchristos } \ 804b169a6bSchristos while (0) 814b169a6bSchristos 824b169a6bSchristos /* Nesting depth of scoped_debug_start_end objects. */ 834b169a6bSchristos 844b169a6bSchristos extern int debug_print_depth; 854b169a6bSchristos 864b169a6bSchristos /* Print a message on construction and destruction, to denote the start and end 874b169a6bSchristos of an operation. Increment DEBUG_PRINT_DEPTH on construction and decrement 884b169a6bSchristos it on destruction, such that nested debug statements will be printed with 894b169a6bSchristos an indent and appear "inside" this one. */ 904b169a6bSchristos 914b169a6bSchristos template<typename PT> 924b169a6bSchristos struct scoped_debug_start_end 934b169a6bSchristos { 944b169a6bSchristos /* DEBUG_ENABLED is a reference to a variable that indicates whether debugging 954b169a6bSchristos is enabled, so if the debug statements should be printed. Is is read 964b169a6bSchristos separately at construction and destruction, such that the start statement 974b169a6bSchristos could be printed but not the end statement, or vice-versa. 984b169a6bSchristos 994b169a6bSchristos DEBUG_ENABLED should either be of type 'bool &' or should be a type 1004b169a6bSchristos that can be invoked. 1014b169a6bSchristos 1024b169a6bSchristos MODULE and FUNC are forwarded to debug_prefixed_printf. 1034b169a6bSchristos 1044b169a6bSchristos START_PREFIX and END_PREFIX are the statements to print on construction and 1054b169a6bSchristos destruction, respectively. 1064b169a6bSchristos 1074b169a6bSchristos If the FMT format string is non-nullptr, then a `: ` is appended to the 1084b169a6bSchristos messages, followed by the rendering of that format string with ARGS. 1094b169a6bSchristos The format string is rendered during construction and is re-used as is 1104b169a6bSchristos for the message on exit. */ 1114b169a6bSchristos 1124b169a6bSchristos scoped_debug_start_end (PT &debug_enabled, const char *module, 1134b169a6bSchristos const char *func, const char *start_prefix, 1144b169a6bSchristos const char *end_prefix, const char *fmt, 1154b169a6bSchristos va_list args) 1164b169a6bSchristos ATTRIBUTE_NULL_PRINTF (7, 0) 1174b169a6bSchristos : m_debug_enabled (debug_enabled), 1184b169a6bSchristos m_module (module), 1194b169a6bSchristos m_func (func), 1204b169a6bSchristos m_end_prefix (end_prefix), 1214b169a6bSchristos m_with_format (fmt != nullptr) 1224b169a6bSchristos { 1234b169a6bSchristos if (is_debug_enabled ()) 1244b169a6bSchristos { 1254b169a6bSchristos if (fmt != nullptr) 1264b169a6bSchristos { 1274b169a6bSchristos m_msg = string_vprintf (fmt, args); 1284b169a6bSchristos debug_prefixed_printf (m_module, m_func, "%s: %s", 1294b169a6bSchristos start_prefix, m_msg->c_str ()); 1304b169a6bSchristos } 1314b169a6bSchristos else 1324b169a6bSchristos debug_prefixed_printf (m_module, m_func, "%s", start_prefix); 1334b169a6bSchristos 1344b169a6bSchristos ++debug_print_depth; 1354b169a6bSchristos m_must_decrement_print_depth = true; 1364b169a6bSchristos } 1374b169a6bSchristos } 1384b169a6bSchristos 1394b169a6bSchristos DISABLE_COPY_AND_ASSIGN (scoped_debug_start_end); 1404b169a6bSchristos 141*5ba1f45fSchristos scoped_debug_start_end (scoped_debug_start_end &&other) 142*5ba1f45fSchristos : m_debug_enabled (other.m_debug_enabled), 143*5ba1f45fSchristos m_module (other.m_module), 144*5ba1f45fSchristos m_func (other.m_func), 145*5ba1f45fSchristos m_end_prefix (other.m_end_prefix), 146*5ba1f45fSchristos m_msg (other.m_msg), 147*5ba1f45fSchristos m_with_format (other.m_with_format), 148*5ba1f45fSchristos m_must_decrement_print_depth (other.m_must_decrement_print_depth), 149*5ba1f45fSchristos m_disabled (other.m_disabled) 150*5ba1f45fSchristos { 151*5ba1f45fSchristos /* Avoid the moved-from object doing the side-effects in its destructor. */ 152*5ba1f45fSchristos other.m_disabled = true; 153*5ba1f45fSchristos } 1544b169a6bSchristos 1554b169a6bSchristos ~scoped_debug_start_end () 1564b169a6bSchristos { 157*5ba1f45fSchristos if (m_disabled) 158*5ba1f45fSchristos return; 159*5ba1f45fSchristos 1604b169a6bSchristos if (m_must_decrement_print_depth) 1614b169a6bSchristos { 1624b169a6bSchristos gdb_assert (debug_print_depth > 0); 1634b169a6bSchristos --debug_print_depth; 1644b169a6bSchristos } 1654b169a6bSchristos 1664b169a6bSchristos if (is_debug_enabled ()) 1674b169a6bSchristos { 1684b169a6bSchristos if (m_with_format) 1694b169a6bSchristos { 1704b169a6bSchristos if (m_msg.has_value ()) 1714b169a6bSchristos debug_prefixed_printf (m_module, m_func, "%s: %s", 1724b169a6bSchristos m_end_prefix, m_msg->c_str ()); 1734b169a6bSchristos else 1744b169a6bSchristos { 1754b169a6bSchristos /* A format string was passed to the constructor, but debug 1764b169a6bSchristos control variable wasn't set at the time, so we don't have the 1774b169a6bSchristos rendering of the format string. */ 1784b169a6bSchristos debug_prefixed_printf (m_module, m_func, "%s: <%s debugging was not enabled on entry>", 1794b169a6bSchristos m_end_prefix, m_module); 1804b169a6bSchristos } 1814b169a6bSchristos } 1824b169a6bSchristos else 1834b169a6bSchristos debug_prefixed_printf (m_module, m_func, "%s", m_end_prefix); 1844b169a6bSchristos } 1854b169a6bSchristos } 1864b169a6bSchristos 1874b169a6bSchristos private: 1884b169a6bSchristos 1894b169a6bSchristos /* This function is specialized based on the type PT. Returns true if 1904b169a6bSchristos M_DEBUG_ENABLED indicates this debug setting is enabled, otherwise, 1914b169a6bSchristos return false. */ 1924b169a6bSchristos bool is_debug_enabled () const; 1934b169a6bSchristos 1944b169a6bSchristos /* Reference to the debug setting, or a callback that can read the debug 1954b169a6bSchristos setting. Access the value of this by calling IS_DEBUG_ENABLED. */ 1964b169a6bSchristos PT &m_debug_enabled; 1974b169a6bSchristos 1984b169a6bSchristos const char *m_module; 1994b169a6bSchristos const char *m_func; 2004b169a6bSchristos const char *m_end_prefix; 2014b169a6bSchristos 2024b169a6bSchristos /* The result of formatting the format string in the constructor. */ 203*5ba1f45fSchristos std::optional<std::string> m_msg; 2044b169a6bSchristos 2054b169a6bSchristos /* True is a non-nullptr format was passed to the constructor. */ 2064b169a6bSchristos bool m_with_format; 2074b169a6bSchristos 2084b169a6bSchristos /* This is used to handle the case where debugging is enabled during 2094b169a6bSchristos construction but not during destruction, or vice-versa. We want to make 2104b169a6bSchristos sure there are as many increments are there are decrements. */ 2114b169a6bSchristos bool m_must_decrement_print_depth = false; 212*5ba1f45fSchristos 213*5ba1f45fSchristos /* True if this object was moved from, and the destructor behavior must be 214*5ba1f45fSchristos inhibited. */ 215*5ba1f45fSchristos bool m_disabled = false; 2164b169a6bSchristos }; 2174b169a6bSchristos 2184b169a6bSchristos /* Implementation of is_debug_enabled when PT is an invokable type. */ 2194b169a6bSchristos 2204b169a6bSchristos template<typename PT> 2214b169a6bSchristos inline bool 2224b169a6bSchristos scoped_debug_start_end<PT>::is_debug_enabled () const 2234b169a6bSchristos { 2244b169a6bSchristos return m_debug_enabled (); 2254b169a6bSchristos } 2264b169a6bSchristos 2274b169a6bSchristos /* Implementation of is_debug_enabled when PT is 'bool &'. */ 2284b169a6bSchristos 2294b169a6bSchristos template<> 2304b169a6bSchristos inline bool 2314b169a6bSchristos scoped_debug_start_end<bool &>::is_debug_enabled () const 2324b169a6bSchristos { 2334b169a6bSchristos return m_debug_enabled; 2344b169a6bSchristos } 2354b169a6bSchristos 2364b169a6bSchristos /* Wrapper around the scoped_debug_start_end constructor to allow the 2374b169a6bSchristos caller to create an object using 'auto' type, the actual type will be 2384b169a6bSchristos based on the type of the PRED argument. All arguments are forwarded to 2394b169a6bSchristos the scoped_debug_start_end constructor. */ 2404b169a6bSchristos 2414b169a6bSchristos template<typename PT> 2424b169a6bSchristos static inline scoped_debug_start_end<PT &> ATTRIBUTE_NULL_PRINTF (6, 7) 2434b169a6bSchristos make_scoped_debug_start_end (PT &&pred, const char *module, const char *func, 2444b169a6bSchristos const char *start_prefix, 2454b169a6bSchristos const char *end_prefix, const char *fmt, ...) 2464b169a6bSchristos { 2474b169a6bSchristos va_list args; 2484b169a6bSchristos va_start (args, fmt); 2494b169a6bSchristos auto res = scoped_debug_start_end<PT &> (pred, module, func, start_prefix, 2504b169a6bSchristos end_prefix, fmt, args); 2514b169a6bSchristos va_end (args); 2524b169a6bSchristos 2534b169a6bSchristos return res; 2544b169a6bSchristos } 2554b169a6bSchristos 2564b169a6bSchristos /* Helper to define a module-specific start/end debug macro. */ 2574b169a6bSchristos 2584b169a6bSchristos #define scoped_debug_start_end(debug_enabled, module, fmt, ...) \ 2594b169a6bSchristos auto CONCAT(scoped_debug_start_end, __LINE__) \ 2604b169a6bSchristos = make_scoped_debug_start_end (debug_enabled, module, \ 2614b169a6bSchristos __func__, "start", "end", \ 2624b169a6bSchristos fmt, ##__VA_ARGS__) 2634b169a6bSchristos 2644b169a6bSchristos /* Helper to define a module-specific enter/exit debug macro. This is a special 2654b169a6bSchristos case of `scoped_debug_start_end` where the start and end messages are "enter" 2664b169a6bSchristos and "exit", to denote entry and exit of a function. */ 2674b169a6bSchristos 2684b169a6bSchristos #define scoped_debug_enter_exit(debug_enabled, module) \ 2694b169a6bSchristos auto CONCAT(scoped_debug_start_end, __LINE__) \ 2704b169a6bSchristos = make_scoped_debug_start_end (debug_enabled, module, \ 2714b169a6bSchristos __func__, "enter", "exit", \ 2724b169a6bSchristos nullptr) 2734b169a6bSchristos 2748dffb485Schristos #endif /* COMMON_COMMON_DEBUG_H */ 275