Add new bugreport command to lldb

The new command add functionality to print out domain specific
information for reporting a bug. Currently the only supported
domain is stack unwinding (with "bugreport unwind") but adding
new domains is fairly easy.

Differential revision: http://reviews.llvm.org/D10868

llvm-svn: 241252
This commit is contained in:
Tamas Berghammer 2015-07-02 10:03:37 +00:00
parent 1023668bc2
commit 3937bc650c
5 changed files with 190 additions and 0 deletions

View File

@ -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 = "<group>"; };
6D762BEC1B1605CD006C929D /* LLDBServerUtilities.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = LLDBServerUtilities.cpp; path = "tools/lldb-server/LLDBServerUtilities.cpp"; sourceTree = "<group>"; };
6D762BED1B1605CD006C929D /* LLDBServerUtilities.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = LLDBServerUtilities.h; path = "tools/lldb-server/LLDBServerUtilities.h"; sourceTree = "<group>"; };
6D86CE9E1B440F6B00A7FBFA /* CommandObjectBugreport.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectBugreport.cpp; path = source/Commands/CommandObjectBugreport.cpp; sourceTree = "<group>"; };
6D86CE9F1B440F6B00A7FBFA /* CommandObjectBugreport.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CommandObjectBugreport.h; path = source/Commands/CommandObjectBugreport.h; sourceTree = "<group>"; };
8C2D6A52197A1EAF006989C9 /* MemoryHistory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MemoryHistory.cpp; path = source/Target/MemoryHistory.cpp; sourceTree = "<group>"; };
8C2D6A54197A1EBE006989C9 /* MemoryHistory.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = MemoryHistory.h; path = include/lldb/Target/MemoryHistory.h; sourceTree = "<group>"; };
8C2D6A5A197A1FDC006989C9 /* MemoryHistoryASan.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MemoryHistoryASan.cpp; sourceTree = "<group>"; };
@ -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 */,

View File

@ -6,6 +6,7 @@ add_lldb_library(lldbCommands
CommandObjectArgs.cpp
CommandObjectBreakpoint.cpp
CommandObjectBreakpointCommand.cpp
CommandObjectBugreport.cpp
CommandObjectCommands.cpp
CommandObjectDisassemble.cpp
CommandObjectExpression.cpp

View File

@ -0,0 +1,145 @@
//===-- 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 <cstdio>
// 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)
{
char command_buffer[256];
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();
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 |
File::eOpenOptionAppend |
File::eOpenOptionCloseOnExec;
const bool append = m_outfile_options.GetAppend().GetCurrentValue();
if (!append)
open_options |= File::eOpenOptionTruncate;
StreamFileSP outfile_stream = std::make_shared<StreamFile>();
Error error = outfile_stream->GetFile().Open(path, open_options);
if (error.Fail())
{
result.AppendErrorWithFormat("Failed to open file '%s' for %s: %s\n",
path,
append ? "append" : "write",
error.AsCString());
result.SetStatus(eReturnStatusFailed);
return false;
}
result.SetImmediateOutputStream(outfile_stream);
}
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 <subcommand> [<subcommand-options>]")
{
LoadSubCommand("unwind", CommandObjectSP(new CommandObjectBugreportUnwind(interpreter)));
}
CommandObjectMultiwordBugreport::~CommandObjectMultiwordBugreport ()
{
}

View File

@ -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_

View File

@ -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 @@ CommandInterpreter::LoadCommandDictionary ()
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));