1 //===-- CommandObjectBugreport.cpp ------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "CommandObjectBugreport.h"
15 #include "lldb/Interpreter/CommandInterpreter.h"
16 #include "lldb/Interpreter/CommandReturnObject.h"
17 #include "lldb/Interpreter/OptionGroupOutputFile.h"
18 #include "lldb/Target/Thread.h"
21 using namespace lldb_private;
23 //-------------------------------------------------------------------------
25 //-------------------------------------------------------------------------
27 class CommandObjectBugreportUnwind : public CommandObjectParsed {
29 CommandObjectBugreportUnwind(CommandInterpreter &interpreter)
30 : CommandObjectParsed(
31 interpreter, "bugreport unwind",
32 "Create a bugreport for a bug in the stack unwinding code.",
34 m_option_group(), m_outfile_options() {
35 m_option_group.Append(&m_outfile_options, LLDB_OPT_SET_ALL,
36 LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3);
37 m_option_group.Finalize();
40 ~CommandObjectBugreportUnwind() override {}
42 Options *GetOptions() override { return &m_option_group; }
45 bool DoExecute(Args &command, CommandReturnObject &result) override {
47 commands.AppendString("thread backtrace");
49 Thread *thread = m_exe_ctx.GetThreadPtr();
51 char command_buffer[256];
53 uint32_t frame_count = thread->GetStackFrameCount();
54 for (uint32_t i = 0; i < frame_count; ++i) {
55 StackFrameSP frame = thread->GetStackFrameAtIndex(i);
56 lldb::addr_t pc = frame->GetStackID().GetPC();
58 snprintf(command_buffer, sizeof(command_buffer),
59 "disassemble --bytes --address 0x%" PRIx64, pc);
60 commands.AppendString(command_buffer);
62 snprintf(command_buffer, sizeof(command_buffer),
63 "image show-unwind --address 0x%" PRIx64, pc);
64 commands.AppendString(command_buffer);
68 const FileSpec &outfile_spec =
69 m_outfile_options.GetFile().GetCurrentValue();
72 uint32_t open_options =
73 File::eOpenOptionWrite | File::eOpenOptionCanCreate |
74 File::eOpenOptionAppend | File::eOpenOptionCloseOnExec;
76 const bool append = m_outfile_options.GetAppend().GetCurrentValue();
78 open_options |= File::eOpenOptionTruncate;
80 StreamFileSP outfile_stream = std::make_shared<StreamFile>();
81 File &file = outfile_stream->GetFile();
83 FileSystem::Instance().Open(file, outfile_spec, open_options);
85 auto path = outfile_spec.GetPath();
86 result.AppendErrorWithFormat("Failed to open file '%s' for %s: %s\n",
87 path.c_str(), append ? "append" : "write",
89 result.SetStatus(eReturnStatusFailed);
93 result.SetImmediateOutputStream(outfile_stream);
96 CommandInterpreterRunOptions options;
97 options.SetStopOnError(false);
98 options.SetEchoCommands(true);
99 options.SetPrintResults(true);
100 options.SetAddToHistory(false);
101 m_interpreter.HandleCommands(commands, &m_exe_ctx, options, result);
103 return result.Succeeded();
107 OptionGroupOptions m_option_group;
108 OptionGroupOutputFile m_outfile_options;
111 #pragma mark CommandObjectMultiwordBugreport
113 //-------------------------------------------------------------------------
114 // CommandObjectMultiwordBugreport
115 //-------------------------------------------------------------------------
117 CommandObjectMultiwordBugreport::CommandObjectMultiwordBugreport(
118 CommandInterpreter &interpreter)
119 : CommandObjectMultiword(
120 interpreter, "bugreport",
121 "Commands for creating domain-specific bug reports.",
122 "bugreport <subcommand> [<subcommand-options>]") {
125 "unwind", CommandObjectSP(new CommandObjectBugreportUnwind(interpreter)));
128 CommandObjectMultiwordBugreport::~CommandObjectMultiwordBugreport() {}