1 //===-- CommandObjectBugreport.cpp ------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "CommandObjectBugreport.h" 11 12 // C Includes 13 #include <cstdio> 14 15 // C++ Includes 16 // Other libraries and framework includes 17 18 // Project includes 19 #include "lldb/Interpreter/CommandInterpreter.h" 20 #include "lldb/Interpreter/CommandReturnObject.h" 21 #include "lldb/Interpreter/OptionGroupOutputFile.h" 22 #include "lldb/Target/Thread.h" 23 24 using namespace lldb; 25 using namespace lldb_private; 26 27 //------------------------------------------------------------------------- 28 // "bugreport unwind" 29 //------------------------------------------------------------------------- 30 31 class CommandObjectBugreportUnwind : public CommandObjectParsed 32 { 33 public: 34 CommandObjectBugreportUnwind(CommandInterpreter &interpreter) : 35 CommandObjectParsed(interpreter, 36 "bugreport unwind", 37 "Create a bugreport for a bug in the stack unwinding code.", 38 nullptr), 39 m_option_group(interpreter), 40 m_outfile_options() 41 { 42 m_option_group.Append (&m_outfile_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3); 43 m_option_group.Finalize(); 44 } 45 46 ~CommandObjectBugreportUnwind() override 47 { 48 } 49 50 Options * 51 GetOptions() override 52 { 53 return &m_option_group; 54 } 55 56 protected: 57 bool 58 DoExecute(Args& command, CommandReturnObject &result) override 59 { 60 StringList commands; 61 commands.AppendString("thread backtrace"); 62 63 Thread *thread = m_exe_ctx.GetThreadPtr(); 64 if (thread) 65 { 66 char command_buffer[256]; 67 68 uint32_t frame_count = thread->GetStackFrameCount(); 69 for (uint32_t i = 0; i < frame_count; ++i) 70 { 71 StackFrameSP frame = thread->GetStackFrameAtIndex(i); 72 lldb::addr_t pc = frame->GetStackID().GetPC(); 73 74 snprintf(command_buffer, sizeof(command_buffer), "disassemble --bytes --address 0x%" PRIx64, pc); 75 commands.AppendString(command_buffer); 76 77 snprintf(command_buffer, sizeof(command_buffer), "image show-unwind --address 0x%" PRIx64, pc); 78 commands.AppendString(command_buffer); 79 } 80 } 81 82 const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue(); 83 if (outfile_spec) 84 { 85 char path[PATH_MAX]; 86 outfile_spec.GetPath (path, sizeof(path)); 87 88 uint32_t open_options = File::eOpenOptionWrite | 89 File::eOpenOptionCanCreate | 90 File::eOpenOptionAppend | 91 File::eOpenOptionCloseOnExec; 92 93 const bool append = m_outfile_options.GetAppend().GetCurrentValue(); 94 if (!append) 95 open_options |= File::eOpenOptionTruncate; 96 97 StreamFileSP outfile_stream = std::make_shared<StreamFile>(); 98 Error error = outfile_stream->GetFile().Open(path, open_options); 99 if (error.Fail()) 100 { 101 result.AppendErrorWithFormat("Failed to open file '%s' for %s: %s\n", 102 path, 103 append ? "append" : "write", 104 error.AsCString()); 105 result.SetStatus(eReturnStatusFailed); 106 return false; 107 } 108 109 result.SetImmediateOutputStream(outfile_stream); 110 } 111 112 CommandInterpreterRunOptions options; 113 options.SetStopOnError(false); 114 options.SetEchoCommands(true); 115 options.SetPrintResults(true); 116 options.SetAddToHistory(false); 117 m_interpreter.HandleCommands(commands, &m_exe_ctx, options, result); 118 119 return result.Succeeded(); 120 } 121 122 private: 123 OptionGroupOptions m_option_group; 124 OptionGroupOutputFile m_outfile_options; 125 }; 126 127 #pragma mark CommandObjectMultiwordBugreport 128 129 //------------------------------------------------------------------------- 130 // CommandObjectMultiwordBugreport 131 //------------------------------------------------------------------------- 132 133 CommandObjectMultiwordBugreport::CommandObjectMultiwordBugreport(CommandInterpreter &interpreter) 134 : CommandObjectMultiword(interpreter, "bugreport", "Commands for creating domain-specific bug reports.", 135 "bugreport <subcommand> [<subcommand-options>]") 136 { 137 138 LoadSubCommand("unwind", CommandObjectSP(new CommandObjectBugreportUnwind(interpreter))); 139 } 140 141 CommandObjectMultiwordBugreport::~CommandObjectMultiwordBugreport () 142 { 143 } 144