aboutsummaryrefslogtreecommitdiff
path: root/lldb/source
diff options
context:
space:
mode:
authorJonas Devlieghere <jonas@devlieghere.com>2022-06-24 12:53:10 -0700
committerJonas Devlieghere <jonas@devlieghere.com>2022-06-24 18:24:00 -0700
commitbe265d25ca5e300a3af45a5f85fc6e4b107148e5 (patch)
treec8205472b1a3a4ef4ea6f41601322adb499b08ee /lldb/source
parent7ae92a69c2f3ddd3d41cbc5c808d240184b394d0 (diff)
downloadllvm-be265d25ca5e300a3af45a5f85fc6e4b107148e5.zip
llvm-be265d25ca5e300a3af45a5f85fc6e4b107148e5.tar.gz
llvm-be265d25ca5e300a3af45a5f85fc6e4b107148e5.tar.bz2
[lldb] Add support for specifying a log handler
This patch adds a new flag to `log enable`, allowing the user to specify a custom log handler. In addition to the default (stream) handler, this allows using the circular log handler (which logs to a fixed size, in-memory circular buffer) as well as the system log handler (which logs to the operating system log). Differential revision: https://reviews.llvm.org/D128323
Diffstat (limited to 'lldb/source')
-rw-r--r--lldb/source/API/SBDebugger.cpp3
-rw-r--r--lldb/source/Commands/CommandObjectLog.cpp51
-rw-r--r--lldb/source/Commands/Options.td4
-rw-r--r--lldb/source/Core/Debugger.cpp30
-rw-r--r--lldb/source/Interpreter/CommandObject.cpp3
5 files changed, 81 insertions, 10 deletions
diff --git a/lldb/source/API/SBDebugger.cpp b/lldb/source/API/SBDebugger.cpp
index 8aa2c74..0de934b 100644
--- a/lldb/source/API/SBDebugger.cpp
+++ b/lldb/source/API/SBDebugger.cpp
@@ -1621,7 +1621,8 @@ bool SBDebugger::EnableLog(const char *channel, const char **categories) {
std::string error;
llvm::raw_string_ostream error_stream(error);
return m_opaque_sp->EnableLog(channel, GetCategoryArray(categories), "",
- log_options, /*buffer_size=*/0, error_stream);
+ log_options, /*buffer_size=*/0,
+ eLogHandlerStream, error_stream);
} else
return false;
}
diff --git a/lldb/source/Commands/CommandObjectLog.cpp b/lldb/source/Commands/CommandObjectLog.cpp
index 91277e3..349af26 100644
--- a/lldb/source/Commands/CommandObjectLog.cpp
+++ b/lldb/source/Commands/CommandObjectLog.cpp
@@ -11,6 +11,7 @@
#include "lldb/Host/OptionParser.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionArgParser.h"
+#include "lldb/Interpreter/OptionValueEnumeration.h"
#include "lldb/Interpreter/OptionValueUInt64.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Utility/Args.h"
@@ -22,6 +23,36 @@
using namespace lldb;
using namespace lldb_private;
+static constexpr OptionEnumValueElement g_log_handler_type[] = {
+ {
+ eLogHandlerDefault,
+ "default",
+ "Use the default (stream) log handler",
+ },
+ {
+ eLogHandlerStream,
+ "stream",
+ "Write log messages to the debugger output stream or to a file if one "
+ "is specified. A buffer size (in bytes) can be specified with -b. If "
+ "no buffer size is specified the output is unbuffered.",
+ },
+ {
+ eLogHandlerCircular,
+ "circular",
+ "Write log messages to a fixed size circular buffer. A buffer size "
+ "(number of messages) must be specified with -b.",
+ },
+ {
+ eLogHandlerSystem,
+ "os",
+ "Write log messages to the operating system log.",
+ },
+};
+
+static constexpr OptionEnumValues LogHandlerType() {
+ return OptionEnumValues(g_log_handler_type);
+}
+
#define LLDB_OPTIONS_log_enable
#include "CommandOptions.inc"
@@ -90,6 +121,14 @@ public:
log_file.SetFile(option_arg, FileSpec::Style::native);
FileSystem::Instance().Resolve(log_file);
break;
+ case 'h':
+ handler = (LogHandlerKind)OptionArgParser::ToOptionEnum(
+ option_arg, GetDefinitions()[option_idx].enum_values, 0, error);
+ if (!error.Success())
+ error.SetErrorStringWithFormat(
+ "unrecognized value for log handler '%s'",
+ option_arg.str().c_str());
+ break;
case 'b':
error =
buffer_size.SetValueFromString(option_arg, eVarSetOperationAssign);
@@ -128,6 +167,7 @@ public:
void OptionParsingStarting(ExecutionContext *execution_context) override {
log_file.Clear();
buffer_size.Clear();
+ handler = eLogHandlerStream;
log_options = 0;
}
@@ -137,6 +177,7 @@ public:
FileSpec log_file;
OptionValueUInt64 buffer_size;
+ LogHandlerKind handler = eLogHandlerStream;
uint32_t log_options = 0;
};
@@ -155,6 +196,13 @@ protected:
return false;
}
+ if (m_options.handler == eLogHandlerCircular &&
+ m_options.buffer_size.GetCurrentValue() == 0) {
+ result.AppendError(
+ "the circular buffer handler requires a non-zero buffer size.\n");
+ return false;
+ }
+
// Store into a std::string since we're about to shift the channel off.
const std::string channel = std::string(args[0].ref());
args.Shift(); // Shift off the channel
@@ -168,7 +216,8 @@ protected:
llvm::raw_string_ostream error_stream(error);
bool success = GetDebugger().EnableLog(
channel, args.GetArgumentArrayRef(), log_file, m_options.log_options,
- m_options.buffer_size.GetCurrentValue(), error_stream);
+ m_options.buffer_size.GetCurrentValue(), m_options.handler,
+ error_stream);
result.GetErrorStream() << error_stream.str();
if (success)
diff --git a/lldb/source/Commands/Options.td b/lldb/source/Commands/Options.td
index b95fc6b..53e09cf 100644
--- a/lldb/source/Commands/Options.td
+++ b/lldb/source/Commands/Options.td
@@ -431,8 +431,10 @@ let Command = "history" in {
let Command = "log enable" in {
def log_file : Option<"file", "f">, Group<1>, Arg<"Filename">,
Desc<"Set the destination file to log to.">;
+ def log_handler : Option<"log-handler", "h">, Group<1>,
+ EnumArg<"LogHandler", "LogHandlerType()">, Desc<"Specify a log handler which determines where log messages are written.">;
def log_buffer_size : Option<"buffer", "b">, Group<1>, Arg<"UnsignedInteger">,
- Desc<"Set the log to be buffered, using the specified buffer size.">;
+ Desc<"Set the log to be buffered, using the specified buffer size, if supported by the log handler.">;
def log_verbose : Option<"verbose", "v">, Group<1>,
Desc<"Enable verbose logging.">;
def log_sequence : Option<"sequence", "s">, Group<1>,
diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp
index fd9679c..f17cd88 100644
--- a/lldb/source/Core/Debugger.cpp
+++ b/lldb/source/Core/Debugger.cpp
@@ -1406,11 +1406,27 @@ void Debugger::ReportError(std::string message,
debugger_id, once);
}
+static std::shared_ptr<LogHandler>
+CreateLogHandler(LogHandlerKind log_handler_kind, int fd, bool should_close,
+ size_t buffer_size) {
+ switch (log_handler_kind) {
+ case eLogHandlerStream:
+ return std::make_shared<StreamLogHandler>(fd, should_close, buffer_size);
+ case eLogHandlerCircular:
+ return std::make_shared<RotatingLogHandler>(buffer_size);
+ case eLogHandlerSystem:
+ return std::make_shared<SystemLogHandler>();
+ case eLogHandlerCallback:
+ return {};
+ }
+ return {};
+}
+
bool Debugger::EnableLog(llvm::StringRef channel,
llvm::ArrayRef<const char *> categories,
llvm::StringRef log_file, uint32_t log_options,
- size_t buffer_size, llvm::raw_ostream &error_stream) {
- const bool should_close = true;
+ size_t buffer_size, LogHandlerKind log_handler_kind,
+ llvm::raw_ostream &error_stream) {
std::shared_ptr<LogHandler> log_handler_sp;
if (m_callback_handler_sp) {
@@ -1419,8 +1435,9 @@ bool Debugger::EnableLog(llvm::StringRef channel,
log_options |=
LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_THREAD_NAME;
} else if (log_file.empty()) {
- log_handler_sp = std::make_shared<StreamLogHandler>(
- GetOutputFile().GetDescriptor(), !should_close, buffer_size);
+ log_handler_sp =
+ CreateLogHandler(log_handler_kind, GetOutputFile().GetDescriptor(),
+ /*should_close=*/false, buffer_size);
} else {
auto pos = m_stream_handlers.find(log_file);
if (pos != m_stream_handlers.end())
@@ -1440,8 +1457,9 @@ bool Debugger::EnableLog(llvm::StringRef channel,
return false;
}
- log_handler_sp = std::make_shared<StreamLogHandler>(
- (*file)->GetDescriptor(), should_close, buffer_size);
+ log_handler_sp =
+ CreateLogHandler(log_handler_kind, (*file)->GetDescriptor(),
+ /*should_close=*/true, buffer_size);
m_stream_handlers[log_file] = log_handler_sp;
}
}
diff --git a/lldb/source/Interpreter/CommandObject.cpp b/lldb/source/Interpreter/CommandObject.cpp
index b38bf86..824c34c 100644
--- a/lldb/source/Interpreter/CommandObject.cpp
+++ b/lldb/source/Interpreter/CommandObject.cpp
@@ -1126,7 +1126,8 @@ CommandObject::ArgumentTableEntry CommandObject::g_arguments_data[] = {
{ eArgTypeCommand, "command", CommandCompletions::eNoCompletion, { nullptr, false }, "An LLDB Command line command element." },
{ eArgTypeColumnNum, "column", CommandCompletions::eNoCompletion, { nullptr, false }, "Column number in a source file." },
{ eArgTypeModuleUUID, "module-uuid", CommandCompletions::eModuleUUIDCompletion, { nullptr, false }, "A module UUID value." },
- { eArgTypeSaveCoreStyle, "corefile-style", CommandCompletions::eNoCompletion, { nullptr, false }, "The type of corefile that lldb will try to create, dependant on this target's capabilities." }
+ { eArgTypeSaveCoreStyle, "corefile-style", CommandCompletions::eNoCompletion, { nullptr, false }, "The type of corefile that lldb will try to create, dependant on this target's capabilities." },
+ { eArgTypeLogHandler, "log-handler", CommandCompletions::eNoCompletion, { nullptr, false }, "The log handle that will be used to write out log messages." },
// clang-format on
};