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 public: 33 CommandObjectBugreportUnwind(CommandInterpreter &interpreter) 34 : CommandObjectParsed( 35 interpreter, "bugreport unwind", 36 "Create a bugreport for a bug in the stack unwinding code.", 37 nullptr), 38 m_option_group(), m_outfile_options() { 39 m_option_group.Append(&m_outfile_options, LLDB_OPT_SET_ALL, 40 LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3); 41 m_option_group.Finalize(); 42 } 43 44 ~CommandObjectBugreportUnwind() override {} 45 46 Options *GetOptions() override { return &m_option_group; } 47 48 protected: 49 bool DoExecute(Args &command, CommandReturnObject &result) override { 50 StringList commands; 51 commands.AppendString("thread backtrace"); 52 53 Thread *thread = m_exe_ctx.GetThreadPtr(); 54 if (thread) { 55 char command_buffer[256]; 56 57 uint32_t frame_count = thread->GetStackFrameCount(); 58 for (uint32_t i = 0; i < frame_count; ++i) { 59 StackFrameSP frame = thread->GetStackFrameAtIndex(i); 60 lldb::addr_t pc = frame->GetStackID().GetPC(); 61 62 snprintf(command_buffer, sizeof(command_buffer), 63 "disassemble --bytes --address 0x%" PRIx64, pc); 64 commands.AppendString(command_buffer); 65 66 snprintf(command_buffer, sizeof(command_buffer), 67 "image show-unwind --address 0x%" PRIx64, pc); 68 commands.AppendString(command_buffer); 69 } 70 } 71 72 const FileSpec &outfile_spec = 73 m_outfile_options.GetFile().GetCurrentValue(); 74 if (outfile_spec) { 75 char path[PATH_MAX]; 76 outfile_spec.GetPath(path, sizeof(path)); 77 78 uint32_t open_options = 79 File::eOpenOptionWrite | File::eOpenOptionCanCreate | 80 File::eOpenOptionAppend | File::eOpenOptionCloseOnExec; 81 82 const bool append = m_outfile_options.GetAppend().GetCurrentValue(); 83 if (!append) 84 open_options |= File::eOpenOptionTruncate; 85 86 StreamFileSP outfile_stream = std::make_shared<StreamFile>(); 87 Status error = outfile_stream->GetFile().Open(path, open_options); 88 if (error.Fail()) { 89 result.AppendErrorWithFormat("Failed to open file '%s' for %s: %s\n", 90 path, append ? "append" : "write", 91 error.AsCString()); 92 result.SetStatus(eReturnStatusFailed); 93 return false; 94 } 95 96 result.SetImmediateOutputStream(outfile_stream); 97 } 98 99 CommandInterpreterRunOptions options; 100 options.SetStopOnError(false); 101 options.SetEchoCommands(true); 102 options.SetPrintResults(true); 103 options.SetAddToHistory(false); 104 m_interpreter.HandleCommands(commands, &m_exe_ctx, options, result); 105 106 return result.Succeeded(); 107 } 108 109 private: 110 OptionGroupOptions m_option_group; 111 OptionGroupOutputFile m_outfile_options; 112 }; 113 114 #pragma mark CommandObjectMultiwordBugreport 115 116 //------------------------------------------------------------------------- 117 // CommandObjectMultiwordBugreport 118 //------------------------------------------------------------------------- 119 120 CommandObjectMultiwordBugreport::CommandObjectMultiwordBugreport( 121 CommandInterpreter &interpreter) 122 : CommandObjectMultiword( 123 interpreter, "bugreport", 124 "Commands for creating domain-specific bug reports.", 125 "bugreport <subcommand> [<subcommand-options>]") { 126 127 LoadSubCommand( 128 "unwind", CommandObjectSP(new CommandObjectBugreportUnwind(interpreter))); 129 } 130 131 CommandObjectMultiwordBugreport::~CommandObjectMultiwordBugreport() {} 132