]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - source/Commands/CommandObjectBugreport.cpp
Vendor import of lldb release_39 branch r276489:
[FreeBSD/FreeBSD.git] / source / Commands / CommandObjectBugreport.cpp
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 }