123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201 |
- /* Declarations for debug printing functions.
- Copyright (C) 2014-2022 Free Software Foundation, Inc.
- This file is part of GDB.
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
- #ifndef COMMON_COMMON_DEBUG_H
- #define COMMON_COMMON_DEBUG_H
- #include "gdbsupport/gdb_optional.h"
- #include "gdbsupport/preprocessor.h"
- #include <stdarg.h>
- /* Set to true to enable debugging of hardware breakpoint/
- watchpoint support code. */
- extern bool show_debug_regs;
- /* Print a formatted message to the appropriate channel for
- debugging output for the client. */
- extern void debug_printf (const char *format, ...)
- ATTRIBUTE_PRINTF (1, 2);
- /* Print a formatted message to the appropriate channel for
- debugging output for the client. This function must be
- provided by the client. */
- extern void debug_vprintf (const char *format, va_list ap)
- ATTRIBUTE_PRINTF (1, 0);
- /* Print a debug statement prefixed with the module and function name, and
- with a newline at the end. */
- extern void ATTRIBUTE_PRINTF (3, 4) debug_prefixed_printf
- (const char *module, const char *func, const char *format, ...);
- /* Print a debug statement prefixed with the module and function name, and
- with a newline at the end. */
- extern void ATTRIBUTE_PRINTF (3, 0) debug_prefixed_vprintf
- (const char *module, const char *func, const char *format, va_list args);
- /* Helper to define "_debug_print" macros.
- DEBUG_ENABLED_COND is an expression that evaluates to true if the debugging
- statement is enabled and should be printed.
- The other arguments, as well as the name of the current function, are
- forwarded to debug_prefixed_printf. */
- #define debug_prefixed_printf_cond(debug_enabled_cond, module, fmt, ...) \
- do \
- { \
- if (debug_enabled_cond) \
- debug_prefixed_printf (module, __func__, fmt, ##__VA_ARGS__); \
- } \
- while (0)
- #define debug_prefixed_printf_cond_nofunc(debug_enabled_cond, module, fmt, ...) \
- do \
- { \
- if (debug_enabled_cond) \
- debug_prefixed_printf (module, nullptr, fmt, ##__VA_ARGS__); \
- } \
- while (0)
- /* Nesting depth of scoped_debug_start_end objects. */
- extern int debug_print_depth;
- /* Print a message on construction and destruction, to denote the start and end
- of an operation. Increment DEBUG_PRINT_DEPTH on construction and decrement
- it on destruction, such that nested debug statements will be printed with
- an indent and appear "inside" this one. */
- struct scoped_debug_start_end
- {
- /* DEBUG_ENABLED is a reference to a variable that indicates whether debugging
- is enabled, so if the debug statements should be printed. Is is read
- separately at construction and destruction, such that the start statement
- could be printed but not the end statement, or vice-versa.
- MODULE and FUNC are forwarded to debug_prefixed_printf.
- START_PREFIX and END_PREFIX are the statements to print on construction and
- destruction, respectively.
- If the FMT format string is non-nullptr, then a `: ` is appended to the
- messages, followed by the rendering of that format string. The format
- string is rendered during construction and is re-used as is for the
- message on exit. */
- scoped_debug_start_end (bool &debug_enabled, const char *module,
- const char *func, const char *start_prefix,
- const char *end_prefix, const char *fmt, ...)
- ATTRIBUTE_NULL_PRINTF (7, 8)
- : m_debug_enabled (debug_enabled),
- m_module (module),
- m_func (func),
- m_end_prefix (end_prefix),
- m_with_format (fmt != nullptr)
- {
- if (m_debug_enabled)
- {
- if (fmt != nullptr)
- {
- va_list args;
- va_start (args, fmt);
- m_msg = string_vprintf (fmt, args);
- va_end (args);
- debug_prefixed_printf (m_module, m_func, "%s: %s",
- start_prefix, m_msg->c_str ());
- }
- else
- debug_prefixed_printf (m_module, m_func, "%s", start_prefix);
- ++debug_print_depth;
- m_must_decrement_print_depth = true;
- }
- }
- DISABLE_COPY_AND_ASSIGN (scoped_debug_start_end);
- ~scoped_debug_start_end ()
- {
- if (m_must_decrement_print_depth)
- {
- gdb_assert (debug_print_depth > 0);
- --debug_print_depth;
- }
- if (m_debug_enabled)
- {
- if (m_with_format)
- {
- if (m_msg.has_value ())
- debug_prefixed_printf (m_module, m_func, "%s: %s",
- m_end_prefix, m_msg->c_str ());
- else
- {
- /* A format string was passed to the constructor, but debug
- control variable wasn't set at the time, so we don't have the
- rendering of the format string. */
- debug_prefixed_printf (m_module, m_func, "%s: <%s debugging was not enabled on entry>",
- m_end_prefix, m_module);
- }
- }
- else
- debug_prefixed_printf (m_module, m_func, "%s", m_end_prefix);
- }
- }
- private:
- bool &m_debug_enabled;
- const char *m_module;
- const char *m_func;
- const char *m_end_prefix;
- /* The result of formatting the format string in the constructor. */
- gdb::optional<std::string> m_msg;
- /* True is a non-nullptr format was passed to the constructor. */
- bool m_with_format;
- /* This is used to handle the case where debugging is enabled during
- construction but not during destruction, or vice-versa. We want to make
- sure there are as many increments are there are decrements. */
- bool m_must_decrement_print_depth = false;
- };
- /* Helper to define a module-specific start/end debug macro. */
- #define scoped_debug_start_end(debug_enabled, module, fmt, ...) \
- scoped_debug_start_end CONCAT(scoped_debug_start_end, __LINE__) \
- (debug_enabled, module, __func__, "start", "end", fmt, ##__VA_ARGS__)
- /* Helper to define a module-specific enter/exit debug macro. This is a special
- case of `scoped_debug_start_end` where the start and end messages are "enter"
- and "exit", to denote entry and exit of a function. */
- #define scoped_debug_enter_exit(debug_enabled, module) \
- scoped_debug_start_end CONCAT(scoped_debug_start_end, __LINE__) \
- (debug_enabled, module, __func__, "enter", "exit", nullptr)
- #endif /* COMMON_COMMON_DEBUG_H */
|