]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/lldb/source/Commands/CommandObjectBugreport.cpp
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm-project / lldb / source / Commands / CommandObjectBugreport.cpp
1 //===-- CommandObjectBugreport.cpp ------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "CommandObjectBugreport.h"
10
11 #include <cstdio>
12
13
14 #include "lldb/Interpreter/CommandInterpreter.h"
15 #include "lldb/Interpreter/CommandReturnObject.h"
16 #include "lldb/Interpreter/OptionGroupOutputFile.h"
17 #include "lldb/Target/Thread.h"
18
19 using namespace lldb;
20 using namespace lldb_private;
21
22 // "bugreport unwind"
23
24 class CommandObjectBugreportUnwind : public CommandObjectParsed {
25 public:
26   CommandObjectBugreportUnwind(CommandInterpreter &interpreter)
27       : CommandObjectParsed(
28             interpreter, "bugreport unwind",
29             "Create a bugreport for a bug in the stack unwinding code.",
30             nullptr),
31         m_option_group(), m_outfile_options() {
32     m_option_group.Append(&m_outfile_options, LLDB_OPT_SET_ALL,
33                           LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3);
34     m_option_group.Finalize();
35   }
36
37   ~CommandObjectBugreportUnwind() override {}
38
39   Options *GetOptions() override { return &m_option_group; }
40
41 protected:
42   bool DoExecute(Args &command, CommandReturnObject &result) override {
43     StringList commands;
44     commands.AppendString("thread backtrace");
45
46     Thread *thread = m_exe_ctx.GetThreadPtr();
47     if (thread) {
48       char command_buffer[256];
49
50       uint32_t frame_count = thread->GetStackFrameCount();
51       for (uint32_t i = 0; i < frame_count; ++i) {
52         StackFrameSP frame = thread->GetStackFrameAtIndex(i);
53         lldb::addr_t pc = frame->GetStackID().GetPC();
54
55         snprintf(command_buffer, sizeof(command_buffer),
56                  "disassemble --bytes --address 0x%" PRIx64, pc);
57         commands.AppendString(command_buffer);
58
59         snprintf(command_buffer, sizeof(command_buffer),
60                  "image show-unwind --address 0x%" PRIx64, pc);
61         commands.AppendString(command_buffer);
62       }
63     }
64
65     const FileSpec &outfile_spec =
66         m_outfile_options.GetFile().GetCurrentValue();
67     if (outfile_spec) {
68
69       uint32_t open_options =
70           File::eOpenOptionWrite | File::eOpenOptionCanCreate |
71           File::eOpenOptionAppend | File::eOpenOptionCloseOnExec;
72
73       const bool append = m_outfile_options.GetAppend().GetCurrentValue();
74       if (!append)
75         open_options |= File::eOpenOptionTruncate;
76
77       StreamFileSP outfile_stream = std::make_shared<StreamFile>();
78       File &file = outfile_stream->GetFile();
79       Status error =
80           FileSystem::Instance().Open(file, outfile_spec, open_options);
81       if (error.Fail()) {
82         auto path = outfile_spec.GetPath();
83         result.AppendErrorWithFormat("Failed to open file '%s' for %s: %s\n",
84                                      path.c_str(), append ? "append" : "write",
85                                      error.AsCString());
86         result.SetStatus(eReturnStatusFailed);
87         return false;
88       }
89
90       result.SetImmediateOutputStream(outfile_stream);
91     }
92
93     CommandInterpreterRunOptions options;
94     options.SetStopOnError(false);
95     options.SetEchoCommands(true);
96     options.SetPrintResults(true);
97     options.SetPrintErrors(true);
98     options.SetAddToHistory(false);
99     m_interpreter.HandleCommands(commands, &m_exe_ctx, options, result);
100
101     return result.Succeeded();
102   }
103
104 private:
105   OptionGroupOptions m_option_group;
106   OptionGroupOutputFile m_outfile_options;
107 };
108
109 #pragma mark CommandObjectMultiwordBugreport
110
111 // CommandObjectMultiwordBugreport
112
113 CommandObjectMultiwordBugreport::CommandObjectMultiwordBugreport(
114     CommandInterpreter &interpreter)
115     : CommandObjectMultiword(
116           interpreter, "bugreport",
117           "Commands for creating domain-specific bug reports.",
118           "bugreport <subcommand> [<subcommand-options>]") {
119
120   LoadSubCommand(
121       "unwind", CommandObjectSP(new CommandObjectBugreportUnwind(interpreter)));
122 }
123
124 CommandObjectMultiwordBugreport::~CommandObjectMultiwordBugreport() {}