diff options
Diffstat (limited to 'contrib/llvm-project/lldb/source/Commands/CommandObjectBugreport.cpp')
-rw-r--r-- | contrib/llvm-project/lldb/source/Commands/CommandObjectBugreport.cpp | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectBugreport.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectBugreport.cpp new file mode 100644 index 000000000000..515cc9a113b1 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectBugreport.cpp @@ -0,0 +1,124 @@ +//===-- CommandObjectBugreport.cpp ------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "CommandObjectBugreport.h" + +#include <cstdio> + + +#include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Interpreter/CommandReturnObject.h" +#include "lldb/Interpreter/OptionGroupOutputFile.h" +#include "lldb/Target/Thread.h" + +using namespace lldb; +using namespace lldb_private; + +// "bugreport unwind" + +class CommandObjectBugreportUnwind : public CommandObjectParsed { +public: + CommandObjectBugreportUnwind(CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "bugreport unwind", + "Create a bugreport for a bug in the stack unwinding code.", + nullptr), + m_option_group(), m_outfile_options() { + m_option_group.Append(&m_outfile_options, LLDB_OPT_SET_ALL, + LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3); + m_option_group.Finalize(); + } + + ~CommandObjectBugreportUnwind() override {} + + Options *GetOptions() override { return &m_option_group; } + +protected: + bool DoExecute(Args &command, CommandReturnObject &result) override { + StringList commands; + commands.AppendString("thread backtrace"); + + Thread *thread = m_exe_ctx.GetThreadPtr(); + if (thread) { + char command_buffer[256]; + + uint32_t frame_count = thread->GetStackFrameCount(); + for (uint32_t i = 0; i < frame_count; ++i) { + StackFrameSP frame = thread->GetStackFrameAtIndex(i); + lldb::addr_t pc = frame->GetStackID().GetPC(); + + snprintf(command_buffer, sizeof(command_buffer), + "disassemble --bytes --address 0x%" PRIx64, pc); + commands.AppendString(command_buffer); + + snprintf(command_buffer, sizeof(command_buffer), + "image show-unwind --address 0x%" PRIx64, pc); + commands.AppendString(command_buffer); + } + } + + const FileSpec &outfile_spec = + m_outfile_options.GetFile().GetCurrentValue(); + if (outfile_spec) { + + uint32_t open_options = + File::eOpenOptionWrite | File::eOpenOptionCanCreate | + File::eOpenOptionAppend | File::eOpenOptionCloseOnExec; + + const bool append = m_outfile_options.GetAppend().GetCurrentValue(); + if (!append) + open_options |= File::eOpenOptionTruncate; + + StreamFileSP outfile_stream = std::make_shared<StreamFile>(); + File &file = outfile_stream->GetFile(); + Status error = + FileSystem::Instance().Open(file, outfile_spec, open_options); + if (error.Fail()) { + auto path = outfile_spec.GetPath(); + result.AppendErrorWithFormat("Failed to open file '%s' for %s: %s\n", + path.c_str(), append ? "append" : "write", + error.AsCString()); + result.SetStatus(eReturnStatusFailed); + return false; + } + + result.SetImmediateOutputStream(outfile_stream); + } + + CommandInterpreterRunOptions options; + options.SetStopOnError(false); + options.SetEchoCommands(true); + options.SetPrintResults(true); + options.SetPrintErrors(true); + options.SetAddToHistory(false); + m_interpreter.HandleCommands(commands, &m_exe_ctx, options, result); + + return result.Succeeded(); + } + +private: + OptionGroupOptions m_option_group; + OptionGroupOutputFile m_outfile_options; +}; + +#pragma mark CommandObjectMultiwordBugreport + +// CommandObjectMultiwordBugreport + +CommandObjectMultiwordBugreport::CommandObjectMultiwordBugreport( + CommandInterpreter &interpreter) + : CommandObjectMultiword( + interpreter, "bugreport", + "Commands for creating domain-specific bug reports.", + "bugreport <subcommand> [<subcommand-options>]") { + + LoadSubCommand( + "unwind", CommandObjectSP(new CommandObjectBugreportUnwind(interpreter))); +} + +CommandObjectMultiwordBugreport::~CommandObjectMultiwordBugreport() {} |