1 //===-- CommandObjectBugreport.cpp ------------------------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "CommandObjectBugreport.h"
14 #include "lldb/Interpreter/CommandInterpreter.h"
15 #include "lldb/Interpreter/CommandReturnObject.h"
16 #include "lldb/Interpreter/OptionGroupOutputFile.h"
17 #include "lldb/Target/Thread.h"
20 using namespace lldb_private;
24 class CommandObjectBugreportUnwind : public CommandObjectParsed {
26 CommandObjectBugreportUnwind(CommandInterpreter &interpreter)
27 : CommandObjectParsed(
28 interpreter, "bugreport unwind",
29 "Create a bugreport for a bug in the stack unwinding code.",
31 m_option_group(), m_outfile_options() {
32 m_option_group.Append(&m_outfile_options, LLDB_OPT_SET_ALL,
33 LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3);
34 m_option_group.Finalize();
37 ~CommandObjectBugreportUnwind() override {}
39 Options *GetOptions() override { return &m_option_group; }
42 bool DoExecute(Args &command, CommandReturnObject &result) override {
44 commands.AppendString("thread backtrace");
46 Thread *thread = m_exe_ctx.GetThreadPtr();
48 char command_buffer[256];
50 uint32_t frame_count = thread->GetStackFrameCount();
51 for (uint32_t i = 0; i < frame_count; ++i) {
52 StackFrameSP frame = thread->GetStackFrameAtIndex(i);
53 lldb::addr_t pc = frame->GetStackID().GetPC();
55 snprintf(command_buffer, sizeof(command_buffer),
56 "disassemble --bytes --address 0x%" PRIx64, pc);
57 commands.AppendString(command_buffer);
59 snprintf(command_buffer, sizeof(command_buffer),
60 "image show-unwind --address 0x%" PRIx64, pc);
61 commands.AppendString(command_buffer);
65 const FileSpec &outfile_spec =
66 m_outfile_options.GetFile().GetCurrentValue();
69 uint32_t open_options =
70 File::eOpenOptionWrite | File::eOpenOptionCanCreate |
71 File::eOpenOptionAppend | File::eOpenOptionCloseOnExec;
73 const bool append = m_outfile_options.GetAppend().GetCurrentValue();
75 open_options |= File::eOpenOptionTruncate;
77 StreamFileSP outfile_stream = std::make_shared<StreamFile>();
78 File &file = outfile_stream->GetFile();
80 FileSystem::Instance().Open(file, outfile_spec, open_options);
82 auto path = outfile_spec.GetPath();
83 result.AppendErrorWithFormat("Failed to open file '%s' for %s: %s\n",
84 path.c_str(), append ? "append" : "write",
86 result.SetStatus(eReturnStatusFailed);
90 result.SetImmediateOutputStream(outfile_stream);
93 CommandInterpreterRunOptions options;
94 options.SetStopOnError(false);
95 options.SetEchoCommands(true);
96 options.SetPrintResults(true);
97 options.SetPrintErrors(true);
98 options.SetAddToHistory(false);
99 m_interpreter.HandleCommands(commands, &m_exe_ctx, options, result);
101 return result.Succeeded();
105 OptionGroupOptions m_option_group;
106 OptionGroupOutputFile m_outfile_options;
109 #pragma mark CommandObjectMultiwordBugreport
111 // CommandObjectMultiwordBugreport
113 CommandObjectMultiwordBugreport::CommandObjectMultiwordBugreport(
114 CommandInterpreter &interpreter)
115 : CommandObjectMultiword(
116 interpreter, "bugreport",
117 "Commands for creating domain-specific bug reports.",
118 "bugreport <subcommand> [<subcommand-options>]") {
121 "unwind", CommandObjectSP(new CommandObjectBugreportUnwind(interpreter)));
124 CommandObjectMultiwordBugreport::~CommandObjectMultiwordBugreport() {}