hawkinsw created this revision. hawkinsw added reviewers: teemperor, JDevlieghere, labath. Herald added a project: All. hawkinsw requested review of this revision. Herald added a project: LLDB. Herald added a subscriber: lldb-commits.
When logging for the lldb channel is enabled for any category and the channel output is being directed to a file, inject a copy of every command entered. This change will make it easier to contextualize the debugging output with any commands that the user entered. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D124922 Files: lldb/include/lldb/Utility/Log.h lldb/source/Commands/CommandObjectLog.cpp lldb/source/Interpreter/CommandInterpreter.cpp Index: lldb/source/Interpreter/CommandInterpreter.cpp =================================================================== --- lldb/source/Interpreter/CommandInterpreter.cpp +++ lldb/source/Interpreter/CommandInterpreter.cpp @@ -1838,11 +1838,17 @@ std::string original_command_string(command_line); Log *log = GetLog(LLDBLog::Commands); + Log *lldb_log = GetChannelLogWhenAnyCategoryEnabled<LLDBLog>(); llvm::PrettyStackTraceFormat stack_trace("HandleCommand(command = \"%s\")", command_line); LLDB_LOGF(log, "Processing command: %s", command_line); LLDB_SCOPED_TIMERF("Processing command: %s.", command_line); + // If there is logging enabled for any category in the lldb channel that + // is being directed to a file, log every command. This functionality will + // make it easier for the user reading a log file after the fact to correlate + // the debugging output with the commands that may have caused it. + LLDB_LOGF_FILE_ONLY(lldb_log, "(lldb) %s\n", command_line); if (WasInterrupted()) { result.AppendError("interrupted"); Index: lldb/source/Commands/CommandObjectLog.cpp =================================================================== --- lldb/source/Commands/CommandObjectLog.cpp +++ lldb/source/Commands/CommandObjectLog.cpp @@ -88,6 +88,7 @@ case 'f': log_file.SetFile(option_arg, FileSpec::Style::native); FileSystem::Instance().Resolve(log_file); + log_options |= LLDB_LOG_OPTION_LOG_TO_FILE; break; case 't': log_options |= LLDB_LOG_OPTION_THREADSAFE; Index: lldb/include/lldb/Utility/Log.h =================================================================== --- lldb/include/lldb/Utility/Log.h +++ lldb/include/lldb/Utility/Log.h @@ -24,6 +24,7 @@ #include <atomic> #include <cstdarg> #include <cstdint> +#include <limits> #include <memory> #include <string> #include <type_traits> @@ -41,6 +42,7 @@ #define LLDB_LOG_OPTION_BACKTRACE (1U << 7) #define LLDB_LOG_OPTION_APPEND (1U << 8) #define LLDB_LOG_OPTION_PREPEND_FILE_FUNCTION (1U << 9) +#define LLDB_LOG_OPTION_LOG_TO_FILE (1U << 10) // Logging Functions namespace lldb_private { @@ -238,6 +240,18 @@ return LogChannelFor<Cat>().GetLog(Log::MaskType(mask)); } +/// Retrieve the Log object for a channel when any of its categories are +/// enabled. +/// +/// Returns a valid Log object if any of the categories for a channel are +/// enabled. Otherwise, returns nullptr. +template <typename Channel> Log *GetChannelLogWhenAnyCategoryEnabled() { + static_assert( + std::is_same<Log::MaskType, std::underlying_type_t<Channel>>::value, ""); + Log::MaskType any_category_flag = std::numeric_limits<Log::MaskType>::max(); + return LogChannelFor<Channel>().GetLog(any_category_flag); +} + } // namespace lldb_private /// The LLDB_LOG* macros defined below are the way to emit log messages. @@ -274,6 +288,15 @@ log_private->Printf(__VA_ARGS__); \ } while (0) +// Write a message to the log only if that log is sending its output to a file. +#define LLDB_LOGF_FILE_ONLY(log, ...) \ + do { \ + ::lldb_private::Log *log_private = (log); \ + if (log_private && \ + log_private->GetOptions().Test(LLDB_LOG_OPTION_LOG_TO_FILE)) \ + log_private->Printf(__VA_ARGS__); \ + } while (0) + #define LLDB_LOGV(log, ...) \ do { \ ::lldb_private::Log *log_private = (log); \
Index: lldb/source/Interpreter/CommandInterpreter.cpp =================================================================== --- lldb/source/Interpreter/CommandInterpreter.cpp +++ lldb/source/Interpreter/CommandInterpreter.cpp @@ -1838,11 +1838,17 @@ std::string original_command_string(command_line); Log *log = GetLog(LLDBLog::Commands); + Log *lldb_log = GetChannelLogWhenAnyCategoryEnabled<LLDBLog>(); llvm::PrettyStackTraceFormat stack_trace("HandleCommand(command = \"%s\")", command_line); LLDB_LOGF(log, "Processing command: %s", command_line); LLDB_SCOPED_TIMERF("Processing command: %s.", command_line); + // If there is logging enabled for any category in the lldb channel that + // is being directed to a file, log every command. This functionality will + // make it easier for the user reading a log file after the fact to correlate + // the debugging output with the commands that may have caused it. + LLDB_LOGF_FILE_ONLY(lldb_log, "(lldb) %s\n", command_line); if (WasInterrupted()) { result.AppendError("interrupted"); Index: lldb/source/Commands/CommandObjectLog.cpp =================================================================== --- lldb/source/Commands/CommandObjectLog.cpp +++ lldb/source/Commands/CommandObjectLog.cpp @@ -88,6 +88,7 @@ case 'f': log_file.SetFile(option_arg, FileSpec::Style::native); FileSystem::Instance().Resolve(log_file); + log_options |= LLDB_LOG_OPTION_LOG_TO_FILE; break; case 't': log_options |= LLDB_LOG_OPTION_THREADSAFE; Index: lldb/include/lldb/Utility/Log.h =================================================================== --- lldb/include/lldb/Utility/Log.h +++ lldb/include/lldb/Utility/Log.h @@ -24,6 +24,7 @@ #include <atomic> #include <cstdarg> #include <cstdint> +#include <limits> #include <memory> #include <string> #include <type_traits> @@ -41,6 +42,7 @@ #define LLDB_LOG_OPTION_BACKTRACE (1U << 7) #define LLDB_LOG_OPTION_APPEND (1U << 8) #define LLDB_LOG_OPTION_PREPEND_FILE_FUNCTION (1U << 9) +#define LLDB_LOG_OPTION_LOG_TO_FILE (1U << 10) // Logging Functions namespace lldb_private { @@ -238,6 +240,18 @@ return LogChannelFor<Cat>().GetLog(Log::MaskType(mask)); } +/// Retrieve the Log object for a channel when any of its categories are +/// enabled. +/// +/// Returns a valid Log object if any of the categories for a channel are +/// enabled. Otherwise, returns nullptr. +template <typename Channel> Log *GetChannelLogWhenAnyCategoryEnabled() { + static_assert( + std::is_same<Log::MaskType, std::underlying_type_t<Channel>>::value, ""); + Log::MaskType any_category_flag = std::numeric_limits<Log::MaskType>::max(); + return LogChannelFor<Channel>().GetLog(any_category_flag); +} + } // namespace lldb_private /// The LLDB_LOG* macros defined below are the way to emit log messages. @@ -274,6 +288,15 @@ log_private->Printf(__VA_ARGS__); \ } while (0) +// Write a message to the log only if that log is sending its output to a file. +#define LLDB_LOGF_FILE_ONLY(log, ...) \ + do { \ + ::lldb_private::Log *log_private = (log); \ + if (log_private && \ + log_private->GetOptions().Test(LLDB_LOG_OPTION_LOG_TO_FILE)) \ + log_private->Printf(__VA_ARGS__); \ + } while (0) + #define LLDB_LOGV(log, ...) \ do { \ ::lldb_private::Log *log_private = (log); \
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits