Index: lldb.xcodeproj/project.pbxproj =================================================================== --- lldb.xcodeproj/project.pbxproj +++ lldb.xcodeproj/project.pbxproj @@ -694,6 +694,7 @@ 6D55BAED1A8CD0A800A70529 /* PlatformAndroid.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D55BAE91A8CD08C00A70529 /* PlatformAndroid.cpp */; }; 6D55BAEE1A8CD0B200A70529 /* PlatformAndroidRemoteGDBServer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D55BAEB1A8CD08C00A70529 /* PlatformAndroidRemoteGDBServer.cpp */; }; 6D762BEE1B1605D2006C929D /* LLDBServerUtilities.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D762BEC1B1605CD006C929D /* LLDBServerUtilities.cpp */; }; + 6D86CEA01B440F8500A7FBFA /* CommandObjectBugreport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D86CE9E1B440F6B00A7FBFA /* CommandObjectBugreport.cpp */; }; 8C2D6A53197A1EAF006989C9 /* MemoryHistory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8C2D6A52197A1EAF006989C9 /* MemoryHistory.cpp */; }; 8C2D6A5E197A250F006989C9 /* MemoryHistoryASan.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8C2D6A5A197A1FDC006989C9 /* MemoryHistoryASan.cpp */; }; 8CCB017E19BA28A80009FD44 /* ThreadCollection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CCB017A19BA283D0009FD44 /* ThreadCollection.cpp */; }; @@ -2340,6 +2341,8 @@ 6D55BAEC1A8CD08C00A70529 /* PlatformAndroidRemoteGDBServer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PlatformAndroidRemoteGDBServer.h; sourceTree = ""; }; 6D762BEC1B1605CD006C929D /* LLDBServerUtilities.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = LLDBServerUtilities.cpp; path = "tools/lldb-server/LLDBServerUtilities.cpp"; sourceTree = ""; }; 6D762BED1B1605CD006C929D /* LLDBServerUtilities.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = LLDBServerUtilities.h; path = "tools/lldb-server/LLDBServerUtilities.h"; sourceTree = ""; }; + 6D86CE9E1B440F6B00A7FBFA /* CommandObjectBugreport.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectBugreport.cpp; path = source/Commands/CommandObjectBugreport.cpp; sourceTree = ""; }; + 6D86CE9F1B440F6B00A7FBFA /* CommandObjectBugreport.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CommandObjectBugreport.h; path = source/Commands/CommandObjectBugreport.h; sourceTree = ""; }; 8C2D6A52197A1EAF006989C9 /* MemoryHistory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MemoryHistory.cpp; path = source/Target/MemoryHistory.cpp; sourceTree = ""; }; 8C2D6A54197A1EBE006989C9 /* MemoryHistory.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = MemoryHistory.h; path = include/lldb/Target/MemoryHistory.h; sourceTree = ""; }; 8C2D6A5A197A1FDC006989C9 /* MemoryHistoryASan.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MemoryHistoryASan.cpp; sourceTree = ""; }; @@ -4232,6 +4235,8 @@ 26BC7E2D10F1B84700F91463 /* CommandObjectBreakpoint.cpp */, 9A42976111861A9F00FE05CD /* CommandObjectBreakpointCommand.h */, 9A42976211861AA600FE05CD /* CommandObjectBreakpointCommand.cpp */, + 6D86CE9F1B440F6B00A7FBFA /* CommandObjectBugreport.h */, + 6D86CE9E1B440F6B00A7FBFA /* CommandObjectBugreport.cpp */, 4C5DBBC711E3FEC60035160F /* CommandObjectCommands.h */, 4C5DBBC611E3FEC60035160F /* CommandObjectCommands.cpp */, 26BC7D1710F1B76300F91463 /* CommandObjectDisassemble.h */, @@ -6393,6 +6398,7 @@ 260CC64A15D0440D002BF2E0 /* OptionValueBoolean.cpp in Sources */, 260CC64B15D0440D002BF2E0 /* OptionValueProperties.cpp in Sources */, 3FDFED0C19B7C8E7009756A7 /* ThisThread.cpp in Sources */, + 6D86CEA01B440F8500A7FBFA /* CommandObjectBugreport.cpp in Sources */, 260CC64C15D0440D002BF2E0 /* OptionValueDictionary.cpp in Sources */, 49DCF6FE170E6B4A0092F75E /* IRMemoryMap.cpp in Sources */, 260CC64D15D0440D002BF2E0 /* OptionValueEnumeration.cpp in Sources */, Index: source/Commands/CMakeLists.txt =================================================================== --- source/Commands/CMakeLists.txt +++ source/Commands/CMakeLists.txt @@ -6,6 +6,7 @@ CommandObjectArgs.cpp CommandObjectBreakpoint.cpp CommandObjectBreakpointCommand.cpp + CommandObjectBugreport.cpp CommandObjectCommands.cpp CommandObjectDisassemble.cpp CommandObjectExpression.cpp Index: source/Commands/CommandObjectBugreport.h =================================================================== --- /dev/null +++ source/Commands/CommandObjectBugreport.h @@ -0,0 +1,36 @@ +//===-- CommandObjectBugreport.h --------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_CommandObjectBugreport_h_ +#define liblldb_CommandObjectBugreport_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Interpreter/CommandObjectMultiword.h" + +namespace lldb_private { + +//------------------------------------------------------------------------- +// CommandObjectMultiwordBugreport +//------------------------------------------------------------------------- + +class CommandObjectMultiwordBugreport : public CommandObjectMultiword +{ +public: + CommandObjectMultiwordBugreport(CommandInterpreter &interpreter); + + virtual + ~CommandObjectMultiwordBugreport(); +}; + +} // namespace lldb_private + +#endif // liblldb_CommandObjectBugreport_h_ Index: source/Commands/CommandObjectBugreport.cpp =================================================================== --- /dev/null +++ source/Commands/CommandObjectBugreport.cpp @@ -0,0 +1,139 @@ +//===-- CommandObjectBugreport.cpp ------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "CommandObjectBugreport.h" + +// C Includes +#include + +// C++ Includes +// Other libraries and framework includes + +// Project includes +#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(interpreter), + 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() + { + } + + 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) + { + 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(); + + char command_buffer[256]; + + 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) + { + char path[PATH_MAX]; + outfile_spec.GetPath (path, sizeof(path)); + + uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate; + const bool append = m_outfile_options.GetAppend().GetCurrentValue(); + if (append) + open_options |= File::eOpenOptionAppend; + + StreamFileSP outfile_stream = std::make_shared(); + if (outfile_stream->GetFile().Open(path, open_options).Success()) + { + result.SetImmediateOutputStream(outfile_stream); + } + else + { + result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write"); + result.SetStatus(eReturnStatusFailed); + return false; + } + } + + CommandInterpreterRunOptions options; + options.SetStopOnError(false); + options.SetEchoCommands(true); + options.SetPrintResults(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", + "Set of commands for creating domain specific bugreports.", + "bugreport []") +{ + + LoadSubCommand("unwind", CommandObjectSP(new CommandObjectBugreportUnwind(interpreter))); +} + +CommandObjectMultiwordBugreport::~CommandObjectMultiwordBugreport () +{ +} Index: source/Interpreter/CommandInterpreter.cpp =================================================================== --- source/Interpreter/CommandInterpreter.cpp +++ source/Interpreter/CommandInterpreter.cpp @@ -17,6 +17,7 @@ #include "../Commands/CommandObjectApropos.h" #include "../Commands/CommandObjectArgs.h" #include "../Commands/CommandObjectBreakpoint.h" +#include "../Commands/CommandObjectBugreport.h" #include "../Commands/CommandObjectDisassemble.h" #include "../Commands/CommandObjectExpression.h" #include "../Commands/CommandObjectFrame.h" @@ -421,6 +422,7 @@ m_command_dict["apropos"] = CommandObjectSP (new CommandObjectApropos (*this)); m_command_dict["breakpoint"]= CommandObjectSP (new CommandObjectMultiwordBreakpoint (*this)); + m_command_dict["bugreport"] = CommandObjectSP (new CommandObjectMultiwordBugreport (*this)); m_command_dict["command"] = CommandObjectSP (new CommandObjectMultiwordCommands (*this)); m_command_dict["disassemble"] = CommandObjectSP (new CommandObjectDisassemble (*this)); m_command_dict["expression"]= CommandObjectSP (new CommandObjectExpression (*this));