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