xref: /netbsd-src/external/gpl3/gdb.old/dist/gdbsupport/common-debug.h (revision 6881a4007f077b54e5f51159c52b9b25f57deb0d)
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