blob: 3d00cb817e3d840826512513ff142d8e0504f7cf [file] [log] [blame]
Tamas Berghammer3937bc62015-07-02 10:03:37 +00001//===-- 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
24using namespace lldb;
25using namespace lldb_private;
26
27//-------------------------------------------------------------------------
28// "bugreport unwind"
29//-------------------------------------------------------------------------
30
31class CommandObjectBugreportUnwind : public CommandObjectParsed
32{
33public:
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
Bruce Mitchener13d21e92015-10-07 16:56:17 +000046 ~CommandObjectBugreportUnwind() override
Tamas Berghammer3937bc62015-07-02 10:03:37 +000047 {
48 }
49
50 Options *
51 GetOptions() override
52 {
53 return &m_option_group;
54 }
55
56protected:
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
122private:
123 OptionGroupOptions m_option_group;
124 OptionGroupOutputFile m_outfile_options;
125};
126
127#pragma mark CommandObjectMultiwordBugreport
128
129//-------------------------------------------------------------------------
130// CommandObjectMultiwordBugreport
131//-------------------------------------------------------------------------
132
133CommandObjectMultiwordBugreport::CommandObjectMultiwordBugreport(CommandInterpreter &interpreter) :
134 CommandObjectMultiword(interpreter,
135 "bugreport",
136 "Set of commands for creating domain specific bugreports.",
137 "bugreport <subcommand> [<subcommand-options>]")
138{
139
140 LoadSubCommand("unwind", CommandObjectSP(new CommandObjectBugreportUnwind(interpreter)));
141}
142
143CommandObjectMultiwordBugreport::~CommandObjectMultiwordBugreport ()
144{
145}