xref: /openbsd-src/gnu/llvm/lldb/source/Core/Debugger.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1dda28197Spatrick //===-- Debugger.cpp ------------------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick 
9061da546Spatrick #include "lldb/Core/Debugger.h"
10061da546Spatrick 
11061da546Spatrick #include "lldb/Breakpoint/Breakpoint.h"
12*f6aab3d8Srobert #include "lldb/Core/DebuggerEvents.h"
13061da546Spatrick #include "lldb/Core/FormatEntity.h"
14061da546Spatrick #include "lldb/Core/Mangled.h"
15061da546Spatrick #include "lldb/Core/ModuleList.h"
16*f6aab3d8Srobert #include "lldb/Core/ModuleSpec.h"
17061da546Spatrick #include "lldb/Core/PluginManager.h"
18061da546Spatrick #include "lldb/Core/StreamAsynchronousIO.h"
19061da546Spatrick #include "lldb/Core/StreamFile.h"
20061da546Spatrick #include "lldb/DataFormatters/DataVisualization.h"
21061da546Spatrick #include "lldb/Expression/REPL.h"
22061da546Spatrick #include "lldb/Host/File.h"
23061da546Spatrick #include "lldb/Host/FileSystem.h"
24061da546Spatrick #include "lldb/Host/HostInfo.h"
25061da546Spatrick #include "lldb/Host/Terminal.h"
26061da546Spatrick #include "lldb/Host/ThreadLauncher.h"
27061da546Spatrick #include "lldb/Interpreter/CommandInterpreter.h"
28be691f3bSpatrick #include "lldb/Interpreter/CommandReturnObject.h"
29061da546Spatrick #include "lldb/Interpreter/OptionValue.h"
30*f6aab3d8Srobert #include "lldb/Interpreter/OptionValueLanguage.h"
31061da546Spatrick #include "lldb/Interpreter/OptionValueProperties.h"
32061da546Spatrick #include "lldb/Interpreter/OptionValueSInt64.h"
33061da546Spatrick #include "lldb/Interpreter/OptionValueString.h"
34061da546Spatrick #include "lldb/Interpreter/Property.h"
35061da546Spatrick #include "lldb/Interpreter/ScriptInterpreter.h"
36061da546Spatrick #include "lldb/Symbol/Function.h"
37061da546Spatrick #include "lldb/Symbol/Symbol.h"
38061da546Spatrick #include "lldb/Symbol/SymbolContext.h"
39061da546Spatrick #include "lldb/Target/Language.h"
40061da546Spatrick #include "lldb/Target/Process.h"
41061da546Spatrick #include "lldb/Target/StructuredDataPlugin.h"
42061da546Spatrick #include "lldb/Target/Target.h"
43061da546Spatrick #include "lldb/Target/TargetList.h"
44061da546Spatrick #include "lldb/Target/Thread.h"
45061da546Spatrick #include "lldb/Target/ThreadList.h"
46061da546Spatrick #include "lldb/Utility/AnsiTerminal.h"
47*f6aab3d8Srobert #include "lldb/Utility/Diagnostics.h"
48061da546Spatrick #include "lldb/Utility/Event.h"
49*f6aab3d8Srobert #include "lldb/Utility/LLDBLog.h"
50061da546Spatrick #include "lldb/Utility/Listener.h"
51061da546Spatrick #include "lldb/Utility/Log.h"
52061da546Spatrick #include "lldb/Utility/State.h"
53061da546Spatrick #include "lldb/Utility/Stream.h"
54061da546Spatrick #include "lldb/Utility/StreamString.h"
55*f6aab3d8Srobert #include "lldb/lldb-enumerations.h"
56061da546Spatrick 
57061da546Spatrick #if defined(_WIN32)
58061da546Spatrick #include "lldb/Host/windows/PosixApi.h"
59061da546Spatrick #include "lldb/Host/windows/windows.h"
60061da546Spatrick #endif
61061da546Spatrick 
62061da546Spatrick #include "llvm/ADT/STLExtras.h"
63061da546Spatrick #include "llvm/ADT/StringRef.h"
64061da546Spatrick #include "llvm/ADT/iterator.h"
65061da546Spatrick #include "llvm/Support/DynamicLibrary.h"
66061da546Spatrick #include "llvm/Support/FileSystem.h"
67061da546Spatrick #include "llvm/Support/Process.h"
68*f6aab3d8Srobert #include "llvm/Support/ThreadPool.h"
69061da546Spatrick #include "llvm/Support/Threading.h"
70061da546Spatrick #include "llvm/Support/raw_ostream.h"
71061da546Spatrick 
72be691f3bSpatrick #include <cstdio>
73be691f3bSpatrick #include <cstdlib>
74be691f3bSpatrick #include <cstring>
75061da546Spatrick #include <list>
76061da546Spatrick #include <memory>
77061da546Spatrick #include <mutex>
78*f6aab3d8Srobert #include <optional>
79061da546Spatrick #include <set>
80061da546Spatrick #include <string>
81061da546Spatrick #include <system_error>
82061da546Spatrick 
83*f6aab3d8Srobert // Includes for pipe()
84*f6aab3d8Srobert #if defined(_WIN32)
85*f6aab3d8Srobert #include <fcntl.h>
86*f6aab3d8Srobert #include <io.h>
87*f6aab3d8Srobert #else
88*f6aab3d8Srobert #include <unistd.h>
89*f6aab3d8Srobert #endif
90*f6aab3d8Srobert 
91061da546Spatrick namespace lldb_private {
92061da546Spatrick class Address;
93061da546Spatrick }
94061da546Spatrick 
95061da546Spatrick using namespace lldb;
96061da546Spatrick using namespace lldb_private;
97061da546Spatrick 
98061da546Spatrick static lldb::user_id_t g_unique_id = 1;
99061da546Spatrick static size_t g_debugger_event_thread_stack_bytes = 8 * 1024 * 1024;
100061da546Spatrick 
101061da546Spatrick #pragma mark Static Functions
102061da546Spatrick 
103061da546Spatrick typedef std::vector<DebuggerSP> DebuggerList;
104061da546Spatrick static std::recursive_mutex *g_debugger_list_mutex_ptr =
105061da546Spatrick     nullptr; // NOTE: intentional leak to avoid issues with C++ destructor chain
106061da546Spatrick static DebuggerList *g_debugger_list_ptr =
107061da546Spatrick     nullptr; // NOTE: intentional leak to avoid issues with C++ destructor chain
108*f6aab3d8Srobert static llvm::ThreadPool *g_thread_pool = nullptr;
109061da546Spatrick 
110061da546Spatrick static constexpr OptionEnumValueElement g_show_disassembly_enum_values[] = {
111061da546Spatrick     {
112061da546Spatrick         Debugger::eStopDisassemblyTypeNever,
113061da546Spatrick         "never",
114061da546Spatrick         "Never show disassembly when displaying a stop context.",
115061da546Spatrick     },
116061da546Spatrick     {
117061da546Spatrick         Debugger::eStopDisassemblyTypeNoDebugInfo,
118061da546Spatrick         "no-debuginfo",
119061da546Spatrick         "Show disassembly when there is no debug information.",
120061da546Spatrick     },
121061da546Spatrick     {
122061da546Spatrick         Debugger::eStopDisassemblyTypeNoSource,
123061da546Spatrick         "no-source",
124061da546Spatrick         "Show disassembly when there is no source information, or the source "
125061da546Spatrick         "file "
126061da546Spatrick         "is missing when displaying a stop context.",
127061da546Spatrick     },
128061da546Spatrick     {
129061da546Spatrick         Debugger::eStopDisassemblyTypeAlways,
130061da546Spatrick         "always",
131061da546Spatrick         "Always show disassembly when displaying a stop context.",
132061da546Spatrick     },
133061da546Spatrick };
134061da546Spatrick 
135061da546Spatrick static constexpr OptionEnumValueElement g_language_enumerators[] = {
136061da546Spatrick     {
137061da546Spatrick         eScriptLanguageNone,
138061da546Spatrick         "none",
139061da546Spatrick         "Disable scripting languages.",
140061da546Spatrick     },
141061da546Spatrick     {
142061da546Spatrick         eScriptLanguagePython,
143061da546Spatrick         "python",
144061da546Spatrick         "Select python as the default scripting language.",
145061da546Spatrick     },
146061da546Spatrick     {
147061da546Spatrick         eScriptLanguageDefault,
148061da546Spatrick         "default",
149061da546Spatrick         "Select the lldb default as the default scripting language.",
150061da546Spatrick     },
151061da546Spatrick };
152061da546Spatrick 
153*f6aab3d8Srobert static constexpr OptionEnumValueElement g_dwim_print_verbosities[] = {
154*f6aab3d8Srobert     {eDWIMPrintVerbosityNone, "none",
155*f6aab3d8Srobert      "Use no verbosity when running dwim-print."},
156*f6aab3d8Srobert     {eDWIMPrintVerbosityExpression, "expression",
157*f6aab3d8Srobert      "Use partial verbosity when running dwim-print - display a message when "
158*f6aab3d8Srobert      "`expression` evaluation is used."},
159*f6aab3d8Srobert     {eDWIMPrintVerbosityFull, "full",
160*f6aab3d8Srobert      "Use full verbosity when running dwim-print."},
161*f6aab3d8Srobert };
162*f6aab3d8Srobert 
163061da546Spatrick static constexpr OptionEnumValueElement s_stop_show_column_values[] = {
164061da546Spatrick     {
165061da546Spatrick         eStopShowColumnAnsiOrCaret,
166061da546Spatrick         "ansi-or-caret",
167061da546Spatrick         "Highlight the stop column with ANSI terminal codes when color/ANSI "
168061da546Spatrick         "mode is enabled; otherwise, fall back to using a text-only caret (^) "
169061da546Spatrick         "as if \"caret-only\" mode was selected.",
170061da546Spatrick     },
171061da546Spatrick     {
172061da546Spatrick         eStopShowColumnAnsi,
173061da546Spatrick         "ansi",
174061da546Spatrick         "Highlight the stop column with ANSI terminal codes when running LLDB "
175061da546Spatrick         "with color/ANSI enabled.",
176061da546Spatrick     },
177061da546Spatrick     {
178061da546Spatrick         eStopShowColumnCaret,
179061da546Spatrick         "caret",
180061da546Spatrick         "Highlight the stop column with a caret character (^) underneath the "
181061da546Spatrick         "stop column. This method introduces a new line in source listings "
182061da546Spatrick         "that display thread stop locations.",
183061da546Spatrick     },
184061da546Spatrick     {
185061da546Spatrick         eStopShowColumnNone,
186061da546Spatrick         "none",
187061da546Spatrick         "Do not highlight the stop column.",
188061da546Spatrick     },
189061da546Spatrick };
190061da546Spatrick 
191061da546Spatrick #define LLDB_PROPERTIES_debugger
192061da546Spatrick #include "CoreProperties.inc"
193061da546Spatrick 
194061da546Spatrick enum {
195061da546Spatrick #define LLDB_PROPERTIES_debugger
196061da546Spatrick #include "CorePropertiesEnum.inc"
197061da546Spatrick };
198061da546Spatrick 
199061da546Spatrick LoadPluginCallbackType Debugger::g_load_plugin_callback = nullptr;
200061da546Spatrick 
SetPropertyValue(const ExecutionContext * exe_ctx,VarSetOperationType op,llvm::StringRef property_path,llvm::StringRef value)201061da546Spatrick Status Debugger::SetPropertyValue(const ExecutionContext *exe_ctx,
202061da546Spatrick                                   VarSetOperationType op,
203061da546Spatrick                                   llvm::StringRef property_path,
204061da546Spatrick                                   llvm::StringRef value) {
205061da546Spatrick   bool is_load_script =
206061da546Spatrick       (property_path == "target.load-script-from-symbol-file");
207061da546Spatrick   // These properties might change how we visualize data.
208061da546Spatrick   bool invalidate_data_vis = (property_path == "escape-non-printables");
209061da546Spatrick   invalidate_data_vis |=
210061da546Spatrick       (property_path == "target.max-zero-padding-in-float-format");
211061da546Spatrick   if (invalidate_data_vis) {
212061da546Spatrick     DataVisualization::ForceUpdate();
213061da546Spatrick   }
214061da546Spatrick 
215061da546Spatrick   TargetSP target_sp;
216*f6aab3d8Srobert   LoadScriptFromSymFile load_script_old_value = eLoadScriptFromSymFileFalse;
217061da546Spatrick   if (is_load_script && exe_ctx->GetTargetSP()) {
218061da546Spatrick     target_sp = exe_ctx->GetTargetSP();
219061da546Spatrick     load_script_old_value =
220061da546Spatrick         target_sp->TargetProperties::GetLoadScriptFromSymbolFile();
221061da546Spatrick   }
222061da546Spatrick   Status error(Properties::SetPropertyValue(exe_ctx, op, property_path, value));
223061da546Spatrick   if (error.Success()) {
224061da546Spatrick     // FIXME it would be nice to have "on-change" callbacks for properties
225061da546Spatrick     if (property_path == g_debugger_properties[ePropertyPrompt].name) {
226061da546Spatrick       llvm::StringRef new_prompt = GetPrompt();
227061da546Spatrick       std::string str = lldb_private::ansi::FormatAnsiTerminalCodes(
228061da546Spatrick           new_prompt, GetUseColor());
229061da546Spatrick       if (str.length())
230061da546Spatrick         new_prompt = str;
231061da546Spatrick       GetCommandInterpreter().UpdatePrompt(new_prompt);
232061da546Spatrick       auto bytes = std::make_unique<EventDataBytes>(new_prompt);
233061da546Spatrick       auto prompt_change_event_sp = std::make_shared<Event>(
234061da546Spatrick           CommandInterpreter::eBroadcastBitResetPrompt, bytes.release());
235061da546Spatrick       GetCommandInterpreter().BroadcastEvent(prompt_change_event_sp);
236061da546Spatrick     } else if (property_path == g_debugger_properties[ePropertyUseColor].name) {
237061da546Spatrick       // use-color changed. Ping the prompt so it can reset the ansi terminal
238061da546Spatrick       // codes.
239061da546Spatrick       SetPrompt(GetPrompt());
240dda28197Spatrick     } else if (property_path == g_debugger_properties[ePropertyUseSourceCache].name) {
241dda28197Spatrick       // use-source-cache changed. Wipe out the cache contents if it was disabled.
242dda28197Spatrick       if (!GetUseSourceCache()) {
243dda28197Spatrick         m_source_file_cache.Clear();
244dda28197Spatrick       }
245061da546Spatrick     } else if (is_load_script && target_sp &&
246061da546Spatrick                load_script_old_value == eLoadScriptFromSymFileWarn) {
247061da546Spatrick       if (target_sp->TargetProperties::GetLoadScriptFromSymbolFile() ==
248061da546Spatrick           eLoadScriptFromSymFileTrue) {
249061da546Spatrick         std::list<Status> errors;
250061da546Spatrick         StreamString feedback_stream;
251061da546Spatrick         if (!target_sp->LoadScriptingResources(errors, &feedback_stream)) {
252061da546Spatrick           Stream &s = GetErrorStream();
253061da546Spatrick           for (auto error : errors) {
254061da546Spatrick             s.Printf("%s\n", error.AsCString());
255061da546Spatrick           }
256061da546Spatrick           if (feedback_stream.GetSize())
257061da546Spatrick             s.PutCString(feedback_stream.GetString());
258061da546Spatrick         }
259061da546Spatrick       }
260061da546Spatrick     }
261061da546Spatrick   }
262061da546Spatrick   return error;
263061da546Spatrick }
264061da546Spatrick 
GetAutoConfirm() const265061da546Spatrick bool Debugger::GetAutoConfirm() const {
266061da546Spatrick   const uint32_t idx = ePropertyAutoConfirm;
267061da546Spatrick   return m_collection_sp->GetPropertyAtIndexAsBoolean(
268061da546Spatrick       nullptr, idx, g_debugger_properties[idx].default_uint_value != 0);
269061da546Spatrick }
270061da546Spatrick 
GetDisassemblyFormat() const271061da546Spatrick const FormatEntity::Entry *Debugger::GetDisassemblyFormat() const {
272061da546Spatrick   const uint32_t idx = ePropertyDisassemblyFormat;
273061da546Spatrick   return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
274061da546Spatrick }
275061da546Spatrick 
GetFrameFormat() const276061da546Spatrick const FormatEntity::Entry *Debugger::GetFrameFormat() const {
277061da546Spatrick   const uint32_t idx = ePropertyFrameFormat;
278061da546Spatrick   return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
279061da546Spatrick }
280061da546Spatrick 
GetFrameFormatUnique() const281061da546Spatrick const FormatEntity::Entry *Debugger::GetFrameFormatUnique() const {
282061da546Spatrick   const uint32_t idx = ePropertyFrameFormatUnique;
283061da546Spatrick   return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
284061da546Spatrick }
285061da546Spatrick 
GetStopDisassemblyMaxSize() const286be691f3bSpatrick uint32_t Debugger::GetStopDisassemblyMaxSize() const {
287be691f3bSpatrick   const uint32_t idx = ePropertyStopDisassemblyMaxSize;
288be691f3bSpatrick   return m_collection_sp->GetPropertyAtIndexAsUInt64(
289be691f3bSpatrick       nullptr, idx, g_debugger_properties[idx].default_uint_value);
290be691f3bSpatrick }
291be691f3bSpatrick 
GetNotifyVoid() const292061da546Spatrick bool Debugger::GetNotifyVoid() const {
293061da546Spatrick   const uint32_t idx = ePropertyNotiftVoid;
294061da546Spatrick   return m_collection_sp->GetPropertyAtIndexAsBoolean(
295061da546Spatrick       nullptr, idx, g_debugger_properties[idx].default_uint_value != 0);
296061da546Spatrick }
297061da546Spatrick 
GetPrompt() const298061da546Spatrick llvm::StringRef Debugger::GetPrompt() const {
299061da546Spatrick   const uint32_t idx = ePropertyPrompt;
300061da546Spatrick   return m_collection_sp->GetPropertyAtIndexAsString(
301061da546Spatrick       nullptr, idx, g_debugger_properties[idx].default_cstr_value);
302061da546Spatrick }
303061da546Spatrick 
SetPrompt(llvm::StringRef p)304061da546Spatrick void Debugger::SetPrompt(llvm::StringRef p) {
305061da546Spatrick   const uint32_t idx = ePropertyPrompt;
306061da546Spatrick   m_collection_sp->SetPropertyAtIndexAsString(nullptr, idx, p);
307061da546Spatrick   llvm::StringRef new_prompt = GetPrompt();
308061da546Spatrick   std::string str =
309061da546Spatrick       lldb_private::ansi::FormatAnsiTerminalCodes(new_prompt, GetUseColor());
310061da546Spatrick   if (str.length())
311061da546Spatrick     new_prompt = str;
312061da546Spatrick   GetCommandInterpreter().UpdatePrompt(new_prompt);
313061da546Spatrick }
314061da546Spatrick 
GetThreadFormat() const315061da546Spatrick const FormatEntity::Entry *Debugger::GetThreadFormat() const {
316061da546Spatrick   const uint32_t idx = ePropertyThreadFormat;
317061da546Spatrick   return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
318061da546Spatrick }
319061da546Spatrick 
GetThreadStopFormat() const320061da546Spatrick const FormatEntity::Entry *Debugger::GetThreadStopFormat() const {
321061da546Spatrick   const uint32_t idx = ePropertyThreadStopFormat;
322061da546Spatrick   return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
323061da546Spatrick }
324061da546Spatrick 
GetScriptLanguage() const325061da546Spatrick lldb::ScriptLanguage Debugger::GetScriptLanguage() const {
326061da546Spatrick   const uint32_t idx = ePropertyScriptLanguage;
327061da546Spatrick   return (lldb::ScriptLanguage)m_collection_sp->GetPropertyAtIndexAsEnumeration(
328061da546Spatrick       nullptr, idx, g_debugger_properties[idx].default_uint_value);
329061da546Spatrick }
330061da546Spatrick 
SetScriptLanguage(lldb::ScriptLanguage script_lang)331061da546Spatrick bool Debugger::SetScriptLanguage(lldb::ScriptLanguage script_lang) {
332061da546Spatrick   const uint32_t idx = ePropertyScriptLanguage;
333061da546Spatrick   return m_collection_sp->SetPropertyAtIndexAsEnumeration(nullptr, idx,
334061da546Spatrick                                                           script_lang);
335061da546Spatrick }
336061da546Spatrick 
GetREPLLanguage() const337*f6aab3d8Srobert lldb::LanguageType Debugger::GetREPLLanguage() const {
338*f6aab3d8Srobert   const uint32_t idx = ePropertyREPLLanguage;
339*f6aab3d8Srobert   OptionValueLanguage *value =
340*f6aab3d8Srobert       m_collection_sp->GetPropertyAtIndexAsOptionValueLanguage(nullptr, idx);
341*f6aab3d8Srobert   if (value)
342*f6aab3d8Srobert     return value->GetCurrentValue();
343*f6aab3d8Srobert   return LanguageType();
344*f6aab3d8Srobert }
345*f6aab3d8Srobert 
SetREPLLanguage(lldb::LanguageType repl_lang)346*f6aab3d8Srobert bool Debugger::SetREPLLanguage(lldb::LanguageType repl_lang) {
347*f6aab3d8Srobert   const uint32_t idx = ePropertyREPLLanguage;
348*f6aab3d8Srobert   return m_collection_sp->SetPropertyAtIndexAsLanguage(nullptr, idx, repl_lang);
349*f6aab3d8Srobert }
350*f6aab3d8Srobert 
GetTerminalWidth() const351061da546Spatrick uint32_t Debugger::GetTerminalWidth() const {
352061da546Spatrick   const uint32_t idx = ePropertyTerminalWidth;
353061da546Spatrick   return m_collection_sp->GetPropertyAtIndexAsSInt64(
354061da546Spatrick       nullptr, idx, g_debugger_properties[idx].default_uint_value);
355061da546Spatrick }
356061da546Spatrick 
SetTerminalWidth(uint32_t term_width)357061da546Spatrick bool Debugger::SetTerminalWidth(uint32_t term_width) {
358dda28197Spatrick   if (auto handler_sp = m_io_handler_stack.Top())
359dda28197Spatrick     handler_sp->TerminalSizeChanged();
360dda28197Spatrick 
361061da546Spatrick   const uint32_t idx = ePropertyTerminalWidth;
362061da546Spatrick   return m_collection_sp->SetPropertyAtIndexAsSInt64(nullptr, idx, term_width);
363061da546Spatrick }
364061da546Spatrick 
GetUseExternalEditor() const365061da546Spatrick bool Debugger::GetUseExternalEditor() const {
366061da546Spatrick   const uint32_t idx = ePropertyUseExternalEditor;
367061da546Spatrick   return m_collection_sp->GetPropertyAtIndexAsBoolean(
368061da546Spatrick       nullptr, idx, g_debugger_properties[idx].default_uint_value != 0);
369061da546Spatrick }
370061da546Spatrick 
SetUseExternalEditor(bool b)371061da546Spatrick bool Debugger::SetUseExternalEditor(bool b) {
372061da546Spatrick   const uint32_t idx = ePropertyUseExternalEditor;
373061da546Spatrick   return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
374061da546Spatrick }
375061da546Spatrick 
GetUseColor() const376061da546Spatrick bool Debugger::GetUseColor() const {
377061da546Spatrick   const uint32_t idx = ePropertyUseColor;
378061da546Spatrick   return m_collection_sp->GetPropertyAtIndexAsBoolean(
379061da546Spatrick       nullptr, idx, g_debugger_properties[idx].default_uint_value != 0);
380061da546Spatrick }
381061da546Spatrick 
SetUseColor(bool b)382061da546Spatrick bool Debugger::SetUseColor(bool b) {
383061da546Spatrick   const uint32_t idx = ePropertyUseColor;
384061da546Spatrick   bool ret = m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
385061da546Spatrick   SetPrompt(GetPrompt());
386061da546Spatrick   return ret;
387061da546Spatrick }
388061da546Spatrick 
GetShowProgress() const389*f6aab3d8Srobert bool Debugger::GetShowProgress() const {
390*f6aab3d8Srobert   const uint32_t idx = ePropertyShowProgress;
391*f6aab3d8Srobert   return m_collection_sp->GetPropertyAtIndexAsBoolean(
392*f6aab3d8Srobert       nullptr, idx, g_debugger_properties[idx].default_uint_value != 0);
393*f6aab3d8Srobert }
394*f6aab3d8Srobert 
SetShowProgress(bool show_progress)395*f6aab3d8Srobert bool Debugger::SetShowProgress(bool show_progress) {
396*f6aab3d8Srobert   const uint32_t idx = ePropertyShowProgress;
397*f6aab3d8Srobert   return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx,
398*f6aab3d8Srobert                                                       show_progress);
399*f6aab3d8Srobert }
400*f6aab3d8Srobert 
GetShowProgressAnsiPrefix() const401*f6aab3d8Srobert llvm::StringRef Debugger::GetShowProgressAnsiPrefix() const {
402*f6aab3d8Srobert   const uint32_t idx = ePropertyShowProgressAnsiPrefix;
403*f6aab3d8Srobert   return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, "");
404*f6aab3d8Srobert }
405*f6aab3d8Srobert 
GetShowProgressAnsiSuffix() const406*f6aab3d8Srobert llvm::StringRef Debugger::GetShowProgressAnsiSuffix() const {
407*f6aab3d8Srobert   const uint32_t idx = ePropertyShowProgressAnsiSuffix;
408*f6aab3d8Srobert   return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, "");
409*f6aab3d8Srobert }
410*f6aab3d8Srobert 
GetUseAutosuggestion() const411be691f3bSpatrick bool Debugger::GetUseAutosuggestion() const {
412be691f3bSpatrick   const uint32_t idx = ePropertyShowAutosuggestion;
413be691f3bSpatrick   return m_collection_sp->GetPropertyAtIndexAsBoolean(
414be691f3bSpatrick       nullptr, idx, g_debugger_properties[idx].default_uint_value != 0);
415be691f3bSpatrick }
416be691f3bSpatrick 
GetAutosuggestionAnsiPrefix() const417*f6aab3d8Srobert llvm::StringRef Debugger::GetAutosuggestionAnsiPrefix() const {
418*f6aab3d8Srobert   const uint32_t idx = ePropertyShowAutosuggestionAnsiPrefix;
419*f6aab3d8Srobert   return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, "");
420*f6aab3d8Srobert }
421*f6aab3d8Srobert 
GetAutosuggestionAnsiSuffix() const422*f6aab3d8Srobert llvm::StringRef Debugger::GetAutosuggestionAnsiSuffix() const {
423*f6aab3d8Srobert   const uint32_t idx = ePropertyShowAutosuggestionAnsiSuffix;
424*f6aab3d8Srobert   return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, "");
425*f6aab3d8Srobert }
426*f6aab3d8Srobert 
GetUseSourceCache() const427dda28197Spatrick bool Debugger::GetUseSourceCache() const {
428dda28197Spatrick   const uint32_t idx = ePropertyUseSourceCache;
429dda28197Spatrick   return m_collection_sp->GetPropertyAtIndexAsBoolean(
430dda28197Spatrick       nullptr, idx, g_debugger_properties[idx].default_uint_value != 0);
431dda28197Spatrick }
432dda28197Spatrick 
SetUseSourceCache(bool b)433dda28197Spatrick bool Debugger::SetUseSourceCache(bool b) {
434dda28197Spatrick   const uint32_t idx = ePropertyUseSourceCache;
435dda28197Spatrick   bool ret = m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
436dda28197Spatrick   if (!ret) {
437dda28197Spatrick     m_source_file_cache.Clear();
438dda28197Spatrick   }
439dda28197Spatrick   return ret;
440dda28197Spatrick }
GetHighlightSource() const441061da546Spatrick bool Debugger::GetHighlightSource() const {
442061da546Spatrick   const uint32_t idx = ePropertyHighlightSource;
443061da546Spatrick   return m_collection_sp->GetPropertyAtIndexAsBoolean(
444061da546Spatrick       nullptr, idx, g_debugger_properties[idx].default_uint_value);
445061da546Spatrick }
446061da546Spatrick 
GetStopShowColumn() const447061da546Spatrick StopShowColumn Debugger::GetStopShowColumn() const {
448061da546Spatrick   const uint32_t idx = ePropertyStopShowColumn;
449061da546Spatrick   return (lldb::StopShowColumn)m_collection_sp->GetPropertyAtIndexAsEnumeration(
450061da546Spatrick       nullptr, idx, g_debugger_properties[idx].default_uint_value);
451061da546Spatrick }
452061da546Spatrick 
GetStopShowColumnAnsiPrefix() const453061da546Spatrick llvm::StringRef Debugger::GetStopShowColumnAnsiPrefix() const {
454061da546Spatrick   const uint32_t idx = ePropertyStopShowColumnAnsiPrefix;
455061da546Spatrick   return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, "");
456061da546Spatrick }
457061da546Spatrick 
GetStopShowColumnAnsiSuffix() const458061da546Spatrick llvm::StringRef Debugger::GetStopShowColumnAnsiSuffix() const {
459061da546Spatrick   const uint32_t idx = ePropertyStopShowColumnAnsiSuffix;
460061da546Spatrick   return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, "");
461061da546Spatrick }
462061da546Spatrick 
GetStopShowLineMarkerAnsiPrefix() const463dda28197Spatrick llvm::StringRef Debugger::GetStopShowLineMarkerAnsiPrefix() const {
464dda28197Spatrick   const uint32_t idx = ePropertyStopShowLineMarkerAnsiPrefix;
465dda28197Spatrick   return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, "");
466dda28197Spatrick }
467dda28197Spatrick 
GetStopShowLineMarkerAnsiSuffix() const468dda28197Spatrick llvm::StringRef Debugger::GetStopShowLineMarkerAnsiSuffix() const {
469dda28197Spatrick   const uint32_t idx = ePropertyStopShowLineMarkerAnsiSuffix;
470dda28197Spatrick   return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, "");
471dda28197Spatrick }
472dda28197Spatrick 
GetStopSourceLineCount(bool before) const473061da546Spatrick uint32_t Debugger::GetStopSourceLineCount(bool before) const {
474061da546Spatrick   const uint32_t idx =
475061da546Spatrick       before ? ePropertyStopLineCountBefore : ePropertyStopLineCountAfter;
476061da546Spatrick   return m_collection_sp->GetPropertyAtIndexAsSInt64(
477061da546Spatrick       nullptr, idx, g_debugger_properties[idx].default_uint_value);
478061da546Spatrick }
479061da546Spatrick 
GetStopDisassemblyDisplay() const480061da546Spatrick Debugger::StopDisassemblyType Debugger::GetStopDisassemblyDisplay() const {
481061da546Spatrick   const uint32_t idx = ePropertyStopDisassemblyDisplay;
482061da546Spatrick   return (Debugger::StopDisassemblyType)
483061da546Spatrick       m_collection_sp->GetPropertyAtIndexAsEnumeration(
484061da546Spatrick           nullptr, idx, g_debugger_properties[idx].default_uint_value);
485061da546Spatrick }
486061da546Spatrick 
GetDisassemblyLineCount() const487061da546Spatrick uint32_t Debugger::GetDisassemblyLineCount() const {
488061da546Spatrick   const uint32_t idx = ePropertyStopDisassemblyCount;
489061da546Spatrick   return m_collection_sp->GetPropertyAtIndexAsSInt64(
490061da546Spatrick       nullptr, idx, g_debugger_properties[idx].default_uint_value);
491061da546Spatrick }
492061da546Spatrick 
GetAutoOneLineSummaries() const493061da546Spatrick bool Debugger::GetAutoOneLineSummaries() const {
494061da546Spatrick   const uint32_t idx = ePropertyAutoOneLineSummaries;
495061da546Spatrick   return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true);
496061da546Spatrick }
497061da546Spatrick 
GetEscapeNonPrintables() const498061da546Spatrick bool Debugger::GetEscapeNonPrintables() const {
499061da546Spatrick   const uint32_t idx = ePropertyEscapeNonPrintables;
500061da546Spatrick   return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true);
501061da546Spatrick }
502061da546Spatrick 
GetAutoIndent() const503061da546Spatrick bool Debugger::GetAutoIndent() const {
504061da546Spatrick   const uint32_t idx = ePropertyAutoIndent;
505061da546Spatrick   return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true);
506061da546Spatrick }
507061da546Spatrick 
SetAutoIndent(bool b)508061da546Spatrick bool Debugger::SetAutoIndent(bool b) {
509061da546Spatrick   const uint32_t idx = ePropertyAutoIndent;
510061da546Spatrick   return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
511061da546Spatrick }
512061da546Spatrick 
GetPrintDecls() const513061da546Spatrick bool Debugger::GetPrintDecls() const {
514061da546Spatrick   const uint32_t idx = ePropertyPrintDecls;
515061da546Spatrick   return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true);
516061da546Spatrick }
517061da546Spatrick 
SetPrintDecls(bool b)518061da546Spatrick bool Debugger::SetPrintDecls(bool b) {
519061da546Spatrick   const uint32_t idx = ePropertyPrintDecls;
520061da546Spatrick   return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
521061da546Spatrick }
522061da546Spatrick 
GetTabSize() const523061da546Spatrick uint32_t Debugger::GetTabSize() const {
524061da546Spatrick   const uint32_t idx = ePropertyTabSize;
525061da546Spatrick   return m_collection_sp->GetPropertyAtIndexAsUInt64(
526061da546Spatrick       nullptr, idx, g_debugger_properties[idx].default_uint_value);
527061da546Spatrick }
528061da546Spatrick 
SetTabSize(uint32_t tab_size)529061da546Spatrick bool Debugger::SetTabSize(uint32_t tab_size) {
530061da546Spatrick   const uint32_t idx = ePropertyTabSize;
531061da546Spatrick   return m_collection_sp->SetPropertyAtIndexAsUInt64(nullptr, idx, tab_size);
532061da546Spatrick }
533061da546Spatrick 
GetDWIMPrintVerbosity() const534*f6aab3d8Srobert lldb::DWIMPrintVerbosity Debugger::GetDWIMPrintVerbosity() const {
535*f6aab3d8Srobert   const uint32_t idx = ePropertyDWIMPrintVerbosity;
536*f6aab3d8Srobert   return (lldb::DWIMPrintVerbosity)
537*f6aab3d8Srobert       m_collection_sp->GetPropertyAtIndexAsEnumeration(
538*f6aab3d8Srobert           nullptr, idx, g_debugger_properties[idx].default_uint_value);
539*f6aab3d8Srobert }
540*f6aab3d8Srobert 
541061da546Spatrick #pragma mark Debugger
542061da546Spatrick 
543061da546Spatrick // const DebuggerPropertiesSP &
544061da546Spatrick // Debugger::GetSettings() const
545061da546Spatrick //{
546061da546Spatrick //    return m_properties_sp;
547061da546Spatrick //}
548061da546Spatrick //
549061da546Spatrick 
Initialize(LoadPluginCallbackType load_plugin_callback)550061da546Spatrick void Debugger::Initialize(LoadPluginCallbackType load_plugin_callback) {
551061da546Spatrick   assert(g_debugger_list_ptr == nullptr &&
552061da546Spatrick          "Debugger::Initialize called more than once!");
553061da546Spatrick   g_debugger_list_mutex_ptr = new std::recursive_mutex();
554061da546Spatrick   g_debugger_list_ptr = new DebuggerList();
555*f6aab3d8Srobert   g_thread_pool = new llvm::ThreadPool(llvm::optimal_concurrency());
556061da546Spatrick   g_load_plugin_callback = load_plugin_callback;
557061da546Spatrick }
558061da546Spatrick 
Terminate()559061da546Spatrick void Debugger::Terminate() {
560061da546Spatrick   assert(g_debugger_list_ptr &&
561061da546Spatrick          "Debugger::Terminate called without a matching Debugger::Initialize!");
562061da546Spatrick 
563*f6aab3d8Srobert   if (g_thread_pool) {
564*f6aab3d8Srobert     // The destructor will wait for all the threads to complete.
565*f6aab3d8Srobert     delete g_thread_pool;
566*f6aab3d8Srobert   }
567*f6aab3d8Srobert 
568061da546Spatrick   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
569*f6aab3d8Srobert     // Clear our global list of debugger objects
570061da546Spatrick     {
571061da546Spatrick       std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
572061da546Spatrick       for (const auto &debugger : *g_debugger_list_ptr)
573061da546Spatrick         debugger->Clear();
574061da546Spatrick       g_debugger_list_ptr->clear();
575061da546Spatrick     }
576061da546Spatrick   }
577061da546Spatrick }
578061da546Spatrick 
SettingsInitialize()579061da546Spatrick void Debugger::SettingsInitialize() { Target::SettingsInitialize(); }
580061da546Spatrick 
SettingsTerminate()581061da546Spatrick void Debugger::SettingsTerminate() { Target::SettingsTerminate(); }
582061da546Spatrick 
LoadPlugin(const FileSpec & spec,Status & error)583061da546Spatrick bool Debugger::LoadPlugin(const FileSpec &spec, Status &error) {
584061da546Spatrick   if (g_load_plugin_callback) {
585061da546Spatrick     llvm::sys::DynamicLibrary dynlib =
586061da546Spatrick         g_load_plugin_callback(shared_from_this(), spec, error);
587061da546Spatrick     if (dynlib.isValid()) {
588061da546Spatrick       m_loaded_plugins.push_back(dynlib);
589061da546Spatrick       return true;
590061da546Spatrick     }
591061da546Spatrick   } else {
592061da546Spatrick     // The g_load_plugin_callback is registered in SBDebugger::Initialize() and
593061da546Spatrick     // if the public API layer isn't available (code is linking against all of
594061da546Spatrick     // the internal LLDB static libraries), then we can't load plugins
595061da546Spatrick     error.SetErrorString("Public API layer is not available");
596061da546Spatrick   }
597061da546Spatrick   return false;
598061da546Spatrick }
599061da546Spatrick 
600061da546Spatrick static FileSystem::EnumerateDirectoryResult
LoadPluginCallback(void * baton,llvm::sys::fs::file_type ft,llvm::StringRef path)601061da546Spatrick LoadPluginCallback(void *baton, llvm::sys::fs::file_type ft,
602061da546Spatrick                    llvm::StringRef path) {
603061da546Spatrick   Status error;
604061da546Spatrick 
605061da546Spatrick   static ConstString g_dylibext(".dylib");
606061da546Spatrick   static ConstString g_solibext(".so");
607061da546Spatrick 
608061da546Spatrick   if (!baton)
609061da546Spatrick     return FileSystem::eEnumerateDirectoryResultQuit;
610061da546Spatrick 
611061da546Spatrick   Debugger *debugger = (Debugger *)baton;
612061da546Spatrick 
613061da546Spatrick   namespace fs = llvm::sys::fs;
614061da546Spatrick   // If we have a regular file, a symbolic link or unknown file type, try and
615061da546Spatrick   // process the file. We must handle unknown as sometimes the directory
616061da546Spatrick   // enumeration might be enumerating a file system that doesn't have correct
617061da546Spatrick   // file type information.
618061da546Spatrick   if (ft == fs::file_type::regular_file || ft == fs::file_type::symlink_file ||
619061da546Spatrick       ft == fs::file_type::type_unknown) {
620061da546Spatrick     FileSpec plugin_file_spec(path);
621061da546Spatrick     FileSystem::Instance().Resolve(plugin_file_spec);
622061da546Spatrick 
623061da546Spatrick     if (plugin_file_spec.GetFileNameExtension() != g_dylibext &&
624061da546Spatrick         plugin_file_spec.GetFileNameExtension() != g_solibext) {
625061da546Spatrick       return FileSystem::eEnumerateDirectoryResultNext;
626061da546Spatrick     }
627061da546Spatrick 
628061da546Spatrick     Status plugin_load_error;
629061da546Spatrick     debugger->LoadPlugin(plugin_file_spec, plugin_load_error);
630061da546Spatrick 
631061da546Spatrick     return FileSystem::eEnumerateDirectoryResultNext;
632061da546Spatrick   } else if (ft == fs::file_type::directory_file ||
633061da546Spatrick              ft == fs::file_type::symlink_file ||
634061da546Spatrick              ft == fs::file_type::type_unknown) {
635061da546Spatrick     // Try and recurse into anything that a directory or symbolic link. We must
636061da546Spatrick     // also do this for unknown as sometimes the directory enumeration might be
637061da546Spatrick     // enumerating a file system that doesn't have correct file type
638061da546Spatrick     // information.
639061da546Spatrick     return FileSystem::eEnumerateDirectoryResultEnter;
640061da546Spatrick   }
641061da546Spatrick 
642061da546Spatrick   return FileSystem::eEnumerateDirectoryResultNext;
643061da546Spatrick }
644061da546Spatrick 
InstanceInitialize()645061da546Spatrick void Debugger::InstanceInitialize() {
646061da546Spatrick   const bool find_directories = true;
647061da546Spatrick   const bool find_files = true;
648061da546Spatrick   const bool find_other = true;
649061da546Spatrick   char dir_path[PATH_MAX];
650061da546Spatrick   if (FileSpec dir_spec = HostInfo::GetSystemPluginDir()) {
651061da546Spatrick     if (FileSystem::Instance().Exists(dir_spec) &&
652061da546Spatrick         dir_spec.GetPath(dir_path, sizeof(dir_path))) {
653061da546Spatrick       FileSystem::Instance().EnumerateDirectory(dir_path, find_directories,
654061da546Spatrick                                                 find_files, find_other,
655061da546Spatrick                                                 LoadPluginCallback, this);
656061da546Spatrick     }
657061da546Spatrick   }
658061da546Spatrick 
659061da546Spatrick   if (FileSpec dir_spec = HostInfo::GetUserPluginDir()) {
660061da546Spatrick     if (FileSystem::Instance().Exists(dir_spec) &&
661061da546Spatrick         dir_spec.GetPath(dir_path, sizeof(dir_path))) {
662061da546Spatrick       FileSystem::Instance().EnumerateDirectory(dir_path, find_directories,
663061da546Spatrick                                                 find_files, find_other,
664061da546Spatrick                                                 LoadPluginCallback, this);
665061da546Spatrick     }
666061da546Spatrick   }
667061da546Spatrick 
668061da546Spatrick   PluginManager::DebuggerInitialize(*this);
669061da546Spatrick }
670061da546Spatrick 
CreateInstance(lldb::LogOutputCallback log_callback,void * baton)671061da546Spatrick DebuggerSP Debugger::CreateInstance(lldb::LogOutputCallback log_callback,
672061da546Spatrick                                     void *baton) {
673061da546Spatrick   DebuggerSP debugger_sp(new Debugger(log_callback, baton));
674061da546Spatrick   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
675061da546Spatrick     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
676061da546Spatrick     g_debugger_list_ptr->push_back(debugger_sp);
677061da546Spatrick   }
678061da546Spatrick   debugger_sp->InstanceInitialize();
679061da546Spatrick   return debugger_sp;
680061da546Spatrick }
681061da546Spatrick 
Destroy(DebuggerSP & debugger_sp)682061da546Spatrick void Debugger::Destroy(DebuggerSP &debugger_sp) {
683061da546Spatrick   if (!debugger_sp)
684061da546Spatrick     return;
685061da546Spatrick 
686be691f3bSpatrick   CommandInterpreter &cmd_interpreter = debugger_sp->GetCommandInterpreter();
687be691f3bSpatrick 
688be691f3bSpatrick   if (cmd_interpreter.GetSaveSessionOnQuit()) {
689be691f3bSpatrick     CommandReturnObject result(debugger_sp->GetUseColor());
690be691f3bSpatrick     cmd_interpreter.SaveTranscript(result);
691be691f3bSpatrick     if (result.Succeeded())
692*f6aab3d8Srobert       (*debugger_sp->GetAsyncOutputStream()) << result.GetOutputData() << '\n';
693be691f3bSpatrick     else
694*f6aab3d8Srobert       (*debugger_sp->GetAsyncErrorStream()) << result.GetErrorData() << '\n';
695be691f3bSpatrick   }
696be691f3bSpatrick 
697061da546Spatrick   debugger_sp->Clear();
698061da546Spatrick 
699061da546Spatrick   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
700061da546Spatrick     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
701061da546Spatrick     DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
702061da546Spatrick     for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
703061da546Spatrick       if ((*pos).get() == debugger_sp.get()) {
704061da546Spatrick         g_debugger_list_ptr->erase(pos);
705061da546Spatrick         return;
706061da546Spatrick       }
707061da546Spatrick     }
708061da546Spatrick   }
709061da546Spatrick }
710061da546Spatrick 
FindDebuggerWithInstanceName(ConstString instance_name)711061da546Spatrick DebuggerSP Debugger::FindDebuggerWithInstanceName(ConstString instance_name) {
712061da546Spatrick   DebuggerSP debugger_sp;
713061da546Spatrick   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
714061da546Spatrick     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
715061da546Spatrick     DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
716061da546Spatrick     for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
717061da546Spatrick       if ((*pos)->m_instance_name == instance_name) {
718061da546Spatrick         debugger_sp = *pos;
719061da546Spatrick         break;
720061da546Spatrick       }
721061da546Spatrick     }
722061da546Spatrick   }
723061da546Spatrick   return debugger_sp;
724061da546Spatrick }
725061da546Spatrick 
FindTargetWithProcessID(lldb::pid_t pid)726061da546Spatrick TargetSP Debugger::FindTargetWithProcessID(lldb::pid_t pid) {
727061da546Spatrick   TargetSP target_sp;
728061da546Spatrick   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
729061da546Spatrick     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
730061da546Spatrick     DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
731061da546Spatrick     for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
732061da546Spatrick       target_sp = (*pos)->GetTargetList().FindTargetWithProcessID(pid);
733061da546Spatrick       if (target_sp)
734061da546Spatrick         break;
735061da546Spatrick     }
736061da546Spatrick   }
737061da546Spatrick   return target_sp;
738061da546Spatrick }
739061da546Spatrick 
FindTargetWithProcess(Process * process)740061da546Spatrick TargetSP Debugger::FindTargetWithProcess(Process *process) {
741061da546Spatrick   TargetSP target_sp;
742061da546Spatrick   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
743061da546Spatrick     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
744061da546Spatrick     DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
745061da546Spatrick     for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
746061da546Spatrick       target_sp = (*pos)->GetTargetList().FindTargetWithProcess(process);
747061da546Spatrick       if (target_sp)
748061da546Spatrick         break;
749061da546Spatrick     }
750061da546Spatrick   }
751061da546Spatrick   return target_sp;
752061da546Spatrick }
753061da546Spatrick 
GetStaticBroadcasterClass()754be691f3bSpatrick ConstString Debugger::GetStaticBroadcasterClass() {
755be691f3bSpatrick   static ConstString class_name("lldb.debugger");
756be691f3bSpatrick   return class_name;
757be691f3bSpatrick }
758be691f3bSpatrick 
Debugger(lldb::LogOutputCallback log_callback,void * baton)759061da546Spatrick Debugger::Debugger(lldb::LogOutputCallback log_callback, void *baton)
760061da546Spatrick     : UserID(g_unique_id++),
761061da546Spatrick       Properties(std::make_shared<OptionValueProperties>()),
762061da546Spatrick       m_input_file_sp(std::make_shared<NativeFile>(stdin, false)),
763061da546Spatrick       m_output_stream_sp(std::make_shared<StreamFile>(stdout, false)),
764061da546Spatrick       m_error_stream_sp(std::make_shared<StreamFile>(stderr, false)),
765061da546Spatrick       m_input_recorder(nullptr),
766061da546Spatrick       m_broadcaster_manager_sp(BroadcasterManager::MakeBroadcasterManager()),
767061da546Spatrick       m_terminal_state(), m_target_list(*this), m_platform_list(),
768061da546Spatrick       m_listener_sp(Listener::MakeListener("lldb.Debugger")),
769061da546Spatrick       m_source_manager_up(), m_source_file_cache(),
770061da546Spatrick       m_command_interpreter_up(
771061da546Spatrick           std::make_unique<CommandInterpreter>(*this, false)),
772dda28197Spatrick       m_io_handler_stack(), m_instance_name(), m_loaded_plugins(),
773061da546Spatrick       m_event_handler_thread(), m_io_handler_thread(),
774061da546Spatrick       m_sync_broadcaster(nullptr, "lldb.debugger.sync"),
775be691f3bSpatrick       m_broadcaster(m_broadcaster_manager_sp,
776be691f3bSpatrick                     GetStaticBroadcasterClass().AsCString()),
777061da546Spatrick       m_forward_listener_sp(), m_clear_once() {
778be691f3bSpatrick   m_instance_name.SetString(llvm::formatv("debugger_{0}", GetID()).str());
779061da546Spatrick   if (log_callback)
780*f6aab3d8Srobert     m_callback_handler_sp =
781*f6aab3d8Srobert         std::make_shared<CallbackLogHandler>(log_callback, baton);
782061da546Spatrick   m_command_interpreter_up->Initialize();
783061da546Spatrick   // Always add our default platform to the platform list
784061da546Spatrick   PlatformSP default_platform_sp(Platform::GetHostPlatform());
785061da546Spatrick   assert(default_platform_sp);
786061da546Spatrick   m_platform_list.Append(default_platform_sp, true);
787061da546Spatrick 
788be691f3bSpatrick   // Create the dummy target.
789be691f3bSpatrick   {
790be691f3bSpatrick     ArchSpec arch(Target::GetDefaultArchitecture());
791be691f3bSpatrick     if (!arch.IsValid())
792be691f3bSpatrick       arch = HostInfo::GetArchitecture();
793be691f3bSpatrick     assert(arch.IsValid() && "No valid default or host archspec");
794be691f3bSpatrick     const bool is_dummy_target = true;
795be691f3bSpatrick     m_dummy_target_sp.reset(
796be691f3bSpatrick         new Target(*this, arch, default_platform_sp, is_dummy_target));
797be691f3bSpatrick   }
798061da546Spatrick   assert(m_dummy_target_sp.get() && "Couldn't construct dummy target?");
799061da546Spatrick 
800061da546Spatrick   m_collection_sp->Initialize(g_debugger_properties);
801061da546Spatrick   m_collection_sp->AppendProperty(
802061da546Spatrick       ConstString("target"),
803061da546Spatrick       ConstString("Settings specify to debugging targets."), true,
804*f6aab3d8Srobert       Target::GetGlobalProperties().GetValueProperties());
805061da546Spatrick   m_collection_sp->AppendProperty(
806061da546Spatrick       ConstString("platform"), ConstString("Platform settings."), true,
807*f6aab3d8Srobert       Platform::GetGlobalPlatformProperties().GetValueProperties());
808061da546Spatrick   m_collection_sp->AppendProperty(
809061da546Spatrick       ConstString("symbols"), ConstString("Symbol lookup and cache settings."),
810061da546Spatrick       true, ModuleList::GetGlobalModuleListProperties().GetValueProperties());
811061da546Spatrick   if (m_command_interpreter_up) {
812061da546Spatrick     m_collection_sp->AppendProperty(
813061da546Spatrick         ConstString("interpreter"),
814061da546Spatrick         ConstString("Settings specify to the debugger's command interpreter."),
815061da546Spatrick         true, m_command_interpreter_up->GetValueProperties());
816061da546Spatrick   }
817061da546Spatrick   OptionValueSInt64 *term_width =
818061da546Spatrick       m_collection_sp->GetPropertyAtIndexAsOptionValueSInt64(
819061da546Spatrick           nullptr, ePropertyTerminalWidth);
820061da546Spatrick   term_width->SetMinimumValue(10);
821061da546Spatrick   term_width->SetMaximumValue(1024);
822061da546Spatrick 
823061da546Spatrick   // Turn off use-color if this is a dumb terminal.
824061da546Spatrick   const char *term = getenv("TERM");
825061da546Spatrick   if (term && !strcmp(term, "dumb"))
826061da546Spatrick     SetUseColor(false);
827061da546Spatrick   // Turn off use-color if we don't write to a terminal with color support.
828061da546Spatrick   if (!GetOutputFile().GetIsTerminalWithColors())
829061da546Spatrick     SetUseColor(false);
830061da546Spatrick 
831061da546Spatrick #if defined(_WIN32) && defined(ENABLE_VIRTUAL_TERMINAL_PROCESSING)
832061da546Spatrick   // Enabling use of ANSI color codes because LLDB is using them to highlight
833061da546Spatrick   // text.
834061da546Spatrick   llvm::sys::Process::UseANSIEscapeCodes(true);
835061da546Spatrick #endif
836061da546Spatrick }
837061da546Spatrick 
~Debugger()838061da546Spatrick Debugger::~Debugger() { Clear(); }
839061da546Spatrick 
Clear()840061da546Spatrick void Debugger::Clear() {
841061da546Spatrick   // Make sure we call this function only once. With the C++ global destructor
842061da546Spatrick   // chain having a list of debuggers and with code that can be running on
843061da546Spatrick   // other threads, we need to ensure this doesn't happen multiple times.
844061da546Spatrick   //
845061da546Spatrick   // The following functions call Debugger::Clear():
846061da546Spatrick   //     Debugger::~Debugger();
847061da546Spatrick   //     static void Debugger::Destroy(lldb::DebuggerSP &debugger_sp);
848061da546Spatrick   //     static void Debugger::Terminate();
849061da546Spatrick   llvm::call_once(m_clear_once, [this]() {
850061da546Spatrick     ClearIOHandlers();
851061da546Spatrick     StopIOHandlerThread();
852061da546Spatrick     StopEventHandlerThread();
853061da546Spatrick     m_listener_sp->Clear();
854be691f3bSpatrick     for (TargetSP target_sp : m_target_list.Targets()) {
855061da546Spatrick       if (target_sp) {
856be691f3bSpatrick         if (ProcessSP process_sp = target_sp->GetProcessSP())
857061da546Spatrick           process_sp->Finalize();
858061da546Spatrick         target_sp->Destroy();
859061da546Spatrick       }
860061da546Spatrick     }
861061da546Spatrick     m_broadcaster_manager_sp->Clear();
862061da546Spatrick 
863061da546Spatrick     // Close the input file _before_ we close the input read communications
864061da546Spatrick     // class as it does NOT own the input file, our m_input_file does.
865061da546Spatrick     m_terminal_state.Clear();
866061da546Spatrick     GetInputFile().Close();
867061da546Spatrick 
868061da546Spatrick     m_command_interpreter_up->Clear();
869061da546Spatrick   });
870061da546Spatrick }
871061da546Spatrick 
GetCloseInputOnEOF() const872061da546Spatrick bool Debugger::GetCloseInputOnEOF() const {
873061da546Spatrick   //    return m_input_comm.GetCloseOnEOF();
874061da546Spatrick   return false;
875061da546Spatrick }
876061da546Spatrick 
SetCloseInputOnEOF(bool b)877061da546Spatrick void Debugger::SetCloseInputOnEOF(bool b) {
878061da546Spatrick   //    m_input_comm.SetCloseOnEOF(b);
879061da546Spatrick }
880061da546Spatrick 
GetAsyncExecution()881061da546Spatrick bool Debugger::GetAsyncExecution() {
882061da546Spatrick   return !m_command_interpreter_up->GetSynchronous();
883061da546Spatrick }
884061da546Spatrick 
SetAsyncExecution(bool async_execution)885061da546Spatrick void Debugger::SetAsyncExecution(bool async_execution) {
886061da546Spatrick   m_command_interpreter_up->SetSynchronous(!async_execution);
887061da546Spatrick }
888061da546Spatrick 
GetInputRecorder()889061da546Spatrick repro::DataRecorder *Debugger::GetInputRecorder() { return m_input_recorder; }
890061da546Spatrick 
OpenPipe(int fds[2],std::size_t size)891*f6aab3d8Srobert static inline int OpenPipe(int fds[2], std::size_t size) {
892*f6aab3d8Srobert #ifdef _WIN32
893*f6aab3d8Srobert   return _pipe(fds, size, O_BINARY);
894*f6aab3d8Srobert #else
895*f6aab3d8Srobert   (void)size;
896*f6aab3d8Srobert   return pipe(fds);
897*f6aab3d8Srobert #endif
898*f6aab3d8Srobert }
899*f6aab3d8Srobert 
SetInputString(const char * data)900*f6aab3d8Srobert Status Debugger::SetInputString(const char *data) {
901*f6aab3d8Srobert   Status result;
902*f6aab3d8Srobert   enum PIPES { READ, WRITE }; // Indexes for the read and write fds
903*f6aab3d8Srobert   int fds[2] = {-1, -1};
904*f6aab3d8Srobert 
905*f6aab3d8Srobert   if (data == nullptr) {
906*f6aab3d8Srobert     result.SetErrorString("String data is null");
907*f6aab3d8Srobert     return result;
908*f6aab3d8Srobert   }
909*f6aab3d8Srobert 
910*f6aab3d8Srobert   size_t size = strlen(data);
911*f6aab3d8Srobert   if (size == 0) {
912*f6aab3d8Srobert     result.SetErrorString("String data is empty");
913*f6aab3d8Srobert     return result;
914*f6aab3d8Srobert   }
915*f6aab3d8Srobert 
916*f6aab3d8Srobert   if (OpenPipe(fds, size) != 0) {
917*f6aab3d8Srobert     result.SetErrorString(
918*f6aab3d8Srobert         "can't create pipe file descriptors for LLDB commands");
919*f6aab3d8Srobert     return result;
920*f6aab3d8Srobert   }
921*f6aab3d8Srobert 
922*f6aab3d8Srobert   int r = write(fds[WRITE], data, size);
923*f6aab3d8Srobert   (void)r;
924*f6aab3d8Srobert   // Close the write end of the pipe, so that the command interpreter will exit
925*f6aab3d8Srobert   // when it consumes all the data.
926*f6aab3d8Srobert   llvm::sys::Process::SafelyCloseFileDescriptor(fds[WRITE]);
927*f6aab3d8Srobert 
928*f6aab3d8Srobert   // Open the read file descriptor as a FILE * that we can return as an input
929*f6aab3d8Srobert   // handle.
930*f6aab3d8Srobert   FILE *commands_file = fdopen(fds[READ], "rb");
931*f6aab3d8Srobert   if (commands_file == nullptr) {
932*f6aab3d8Srobert     result.SetErrorStringWithFormat("fdopen(%i, \"rb\") failed (errno = %i) "
933*f6aab3d8Srobert                                     "when trying to open LLDB commands pipe",
934*f6aab3d8Srobert                                     fds[READ], errno);
935*f6aab3d8Srobert     llvm::sys::Process::SafelyCloseFileDescriptor(fds[READ]);
936*f6aab3d8Srobert     return result;
937*f6aab3d8Srobert   }
938*f6aab3d8Srobert 
939*f6aab3d8Srobert   SetInputFile((FileSP)std::make_shared<NativeFile>(commands_file, true));
940*f6aab3d8Srobert   return result;
941*f6aab3d8Srobert }
942*f6aab3d8Srobert 
SetInputFile(FileSP file_sp)943*f6aab3d8Srobert void Debugger::SetInputFile(FileSP file_sp) {
944061da546Spatrick   assert(file_sp && file_sp->IsValid());
945be691f3bSpatrick   m_input_file_sp = std::move(file_sp);
946061da546Spatrick   // Save away the terminal state if that is relevant, so that we can restore
947061da546Spatrick   // it in RestoreInputState.
948061da546Spatrick   SaveInputTerminalState();
949061da546Spatrick }
950061da546Spatrick 
SetOutputFile(FileSP file_sp)951061da546Spatrick void Debugger::SetOutputFile(FileSP file_sp) {
952061da546Spatrick   assert(file_sp && file_sp->IsValid());
953061da546Spatrick   m_output_stream_sp = std::make_shared<StreamFile>(file_sp);
954061da546Spatrick }
955061da546Spatrick 
SetErrorFile(FileSP file_sp)956061da546Spatrick void Debugger::SetErrorFile(FileSP file_sp) {
957061da546Spatrick   assert(file_sp && file_sp->IsValid());
958061da546Spatrick   m_error_stream_sp = std::make_shared<StreamFile>(file_sp);
959061da546Spatrick }
960061da546Spatrick 
SaveInputTerminalState()961061da546Spatrick void Debugger::SaveInputTerminalState() {
962061da546Spatrick   int fd = GetInputFile().GetDescriptor();
963061da546Spatrick   if (fd != File::kInvalidDescriptor)
964061da546Spatrick     m_terminal_state.Save(fd, true);
965061da546Spatrick }
966061da546Spatrick 
RestoreInputTerminalState()967061da546Spatrick void Debugger::RestoreInputTerminalState() { m_terminal_state.Restore(); }
968061da546Spatrick 
GetSelectedExecutionContext()969061da546Spatrick ExecutionContext Debugger::GetSelectedExecutionContext() {
970be691f3bSpatrick   bool adopt_selected = true;
971be691f3bSpatrick   ExecutionContextRef exe_ctx_ref(GetSelectedTarget().get(), adopt_selected);
972be691f3bSpatrick   return ExecutionContext(exe_ctx_ref);
973061da546Spatrick }
974061da546Spatrick 
DispatchInputInterrupt()975061da546Spatrick void Debugger::DispatchInputInterrupt() {
976dda28197Spatrick   std::lock_guard<std::recursive_mutex> guard(m_io_handler_stack.GetMutex());
977dda28197Spatrick   IOHandlerSP reader_sp(m_io_handler_stack.Top());
978061da546Spatrick   if (reader_sp)
979061da546Spatrick     reader_sp->Interrupt();
980061da546Spatrick }
981061da546Spatrick 
DispatchInputEndOfFile()982061da546Spatrick void Debugger::DispatchInputEndOfFile() {
983dda28197Spatrick   std::lock_guard<std::recursive_mutex> guard(m_io_handler_stack.GetMutex());
984dda28197Spatrick   IOHandlerSP reader_sp(m_io_handler_stack.Top());
985061da546Spatrick   if (reader_sp)
986061da546Spatrick     reader_sp->GotEOF();
987061da546Spatrick }
988061da546Spatrick 
ClearIOHandlers()989061da546Spatrick void Debugger::ClearIOHandlers() {
990061da546Spatrick   // The bottom input reader should be the main debugger input reader.  We do
991061da546Spatrick   // not want to close that one here.
992dda28197Spatrick   std::lock_guard<std::recursive_mutex> guard(m_io_handler_stack.GetMutex());
993dda28197Spatrick   while (m_io_handler_stack.GetSize() > 1) {
994dda28197Spatrick     IOHandlerSP reader_sp(m_io_handler_stack.Top());
995061da546Spatrick     if (reader_sp)
996061da546Spatrick       PopIOHandler(reader_sp);
997061da546Spatrick   }
998061da546Spatrick }
999061da546Spatrick 
RunIOHandlers()1000dda28197Spatrick void Debugger::RunIOHandlers() {
1001dda28197Spatrick   IOHandlerSP reader_sp = m_io_handler_stack.Top();
1002061da546Spatrick   while (true) {
1003061da546Spatrick     if (!reader_sp)
1004061da546Spatrick       break;
1005061da546Spatrick 
1006061da546Spatrick     reader_sp->Run();
1007dda28197Spatrick     {
1008dda28197Spatrick       std::lock_guard<std::recursive_mutex> guard(
1009dda28197Spatrick           m_io_handler_synchronous_mutex);
1010061da546Spatrick 
1011061da546Spatrick       // Remove all input readers that are done from the top of the stack
1012061da546Spatrick       while (true) {
1013dda28197Spatrick         IOHandlerSP top_reader_sp = m_io_handler_stack.Top();
1014061da546Spatrick         if (top_reader_sp && top_reader_sp->GetIsDone())
1015061da546Spatrick           PopIOHandler(top_reader_sp);
1016061da546Spatrick         else
1017061da546Spatrick           break;
1018061da546Spatrick       }
1019dda28197Spatrick       reader_sp = m_io_handler_stack.Top();
1020dda28197Spatrick     }
1021061da546Spatrick   }
1022061da546Spatrick   ClearIOHandlers();
1023061da546Spatrick }
1024061da546Spatrick 
RunIOHandlerSync(const IOHandlerSP & reader_sp)1025dda28197Spatrick void Debugger::RunIOHandlerSync(const IOHandlerSP &reader_sp) {
1026dda28197Spatrick   std::lock_guard<std::recursive_mutex> guard(m_io_handler_synchronous_mutex);
1027061da546Spatrick 
1028061da546Spatrick   PushIOHandler(reader_sp);
1029061da546Spatrick   IOHandlerSP top_reader_sp = reader_sp;
1030dda28197Spatrick 
1031061da546Spatrick   while (top_reader_sp) {
1032dda28197Spatrick     if (!top_reader_sp)
1033dda28197Spatrick       break;
1034dda28197Spatrick 
1035061da546Spatrick     top_reader_sp->Run();
1036061da546Spatrick 
1037dda28197Spatrick     // Don't unwind past the starting point.
1038061da546Spatrick     if (top_reader_sp.get() == reader_sp.get()) {
1039061da546Spatrick       if (PopIOHandler(reader_sp))
1040061da546Spatrick         break;
1041061da546Spatrick     }
1042061da546Spatrick 
1043dda28197Spatrick     // If we pushed new IO handlers, pop them if they're done or restart the
1044dda28197Spatrick     // loop to run them if they're not.
1045061da546Spatrick     while (true) {
1046dda28197Spatrick       top_reader_sp = m_io_handler_stack.Top();
1047dda28197Spatrick       if (top_reader_sp && top_reader_sp->GetIsDone()) {
1048061da546Spatrick         PopIOHandler(top_reader_sp);
1049dda28197Spatrick         // Don't unwind past the starting point.
1050dda28197Spatrick         if (top_reader_sp.get() == reader_sp.get())
1051dda28197Spatrick           return;
1052dda28197Spatrick       } else {
1053061da546Spatrick         break;
1054061da546Spatrick       }
1055061da546Spatrick     }
1056061da546Spatrick   }
1057dda28197Spatrick }
1058dda28197Spatrick 
IsTopIOHandler(const lldb::IOHandlerSP & reader_sp)1059dda28197Spatrick bool Debugger::IsTopIOHandler(const lldb::IOHandlerSP &reader_sp) {
1060dda28197Spatrick   return m_io_handler_stack.IsTop(reader_sp);
1061dda28197Spatrick }
1062dda28197Spatrick 
CheckTopIOHandlerTypes(IOHandler::Type top_type,IOHandler::Type second_top_type)1063dda28197Spatrick bool Debugger::CheckTopIOHandlerTypes(IOHandler::Type top_type,
1064dda28197Spatrick                                       IOHandler::Type second_top_type) {
1065dda28197Spatrick   return m_io_handler_stack.CheckTopIOHandlerTypes(top_type, second_top_type);
1066dda28197Spatrick }
1067dda28197Spatrick 
PrintAsync(const char * s,size_t len,bool is_stdout)1068dda28197Spatrick void Debugger::PrintAsync(const char *s, size_t len, bool is_stdout) {
1069*f6aab3d8Srobert   bool printed = m_io_handler_stack.PrintAsync(s, len, is_stdout);
1070*f6aab3d8Srobert   if (!printed) {
1071*f6aab3d8Srobert     lldb::StreamFileSP stream =
1072*f6aab3d8Srobert         is_stdout ? m_output_stream_sp : m_error_stream_sp;
1073*f6aab3d8Srobert     stream->Write(s, len);
1074*f6aab3d8Srobert   }
1075dda28197Spatrick }
1076dda28197Spatrick 
GetTopIOHandlerControlSequence(char ch)1077dda28197Spatrick ConstString Debugger::GetTopIOHandlerControlSequence(char ch) {
1078dda28197Spatrick   return m_io_handler_stack.GetTopIOHandlerControlSequence(ch);
1079dda28197Spatrick }
1080dda28197Spatrick 
GetIOHandlerCommandPrefix()1081dda28197Spatrick const char *Debugger::GetIOHandlerCommandPrefix() {
1082dda28197Spatrick   return m_io_handler_stack.GetTopIOHandlerCommandPrefix();
1083dda28197Spatrick }
1084dda28197Spatrick 
GetIOHandlerHelpPrologue()1085dda28197Spatrick const char *Debugger::GetIOHandlerHelpPrologue() {
1086dda28197Spatrick   return m_io_handler_stack.GetTopIOHandlerHelpPrologue();
1087dda28197Spatrick }
1088dda28197Spatrick 
RemoveIOHandler(const IOHandlerSP & reader_sp)1089dda28197Spatrick bool Debugger::RemoveIOHandler(const IOHandlerSP &reader_sp) {
1090dda28197Spatrick   return PopIOHandler(reader_sp);
1091dda28197Spatrick }
1092dda28197Spatrick 
RunIOHandlerAsync(const IOHandlerSP & reader_sp,bool cancel_top_handler)1093dda28197Spatrick void Debugger::RunIOHandlerAsync(const IOHandlerSP &reader_sp,
1094dda28197Spatrick                                  bool cancel_top_handler) {
1095dda28197Spatrick   PushIOHandler(reader_sp, cancel_top_handler);
1096dda28197Spatrick }
1097061da546Spatrick 
AdoptTopIOHandlerFilesIfInvalid(FileSP & in,StreamFileSP & out,StreamFileSP & err)1098061da546Spatrick void Debugger::AdoptTopIOHandlerFilesIfInvalid(FileSP &in, StreamFileSP &out,
1099061da546Spatrick                                                StreamFileSP &err) {
1100061da546Spatrick   // Before an IOHandler runs, it must have in/out/err streams. This function
1101061da546Spatrick   // is called when one ore more of the streams are nullptr. We use the top
1102061da546Spatrick   // input reader's in/out/err streams, or fall back to the debugger file
1103061da546Spatrick   // handles, or we fall back onto stdin/stdout/stderr as a last resort.
1104061da546Spatrick 
1105dda28197Spatrick   std::lock_guard<std::recursive_mutex> guard(m_io_handler_stack.GetMutex());
1106dda28197Spatrick   IOHandlerSP top_reader_sp(m_io_handler_stack.Top());
1107061da546Spatrick   // If no STDIN has been set, then set it appropriately
1108061da546Spatrick   if (!in || !in->IsValid()) {
1109061da546Spatrick     if (top_reader_sp)
1110061da546Spatrick       in = top_reader_sp->GetInputFileSP();
1111061da546Spatrick     else
1112061da546Spatrick       in = GetInputFileSP();
1113061da546Spatrick     // If there is nothing, use stdin
1114061da546Spatrick     if (!in)
1115061da546Spatrick       in = std::make_shared<NativeFile>(stdin, false);
1116061da546Spatrick   }
1117061da546Spatrick   // If no STDOUT has been set, then set it appropriately
1118061da546Spatrick   if (!out || !out->GetFile().IsValid()) {
1119061da546Spatrick     if (top_reader_sp)
1120061da546Spatrick       out = top_reader_sp->GetOutputStreamFileSP();
1121061da546Spatrick     else
1122061da546Spatrick       out = GetOutputStreamSP();
1123061da546Spatrick     // If there is nothing, use stdout
1124061da546Spatrick     if (!out)
1125061da546Spatrick       out = std::make_shared<StreamFile>(stdout, false);
1126061da546Spatrick   }
1127061da546Spatrick   // If no STDERR has been set, then set it appropriately
1128061da546Spatrick   if (!err || !err->GetFile().IsValid()) {
1129061da546Spatrick     if (top_reader_sp)
1130061da546Spatrick       err = top_reader_sp->GetErrorStreamFileSP();
1131061da546Spatrick     else
1132061da546Spatrick       err = GetErrorStreamSP();
1133061da546Spatrick     // If there is nothing, use stderr
1134061da546Spatrick     if (!err)
1135061da546Spatrick       err = std::make_shared<StreamFile>(stderr, false);
1136061da546Spatrick   }
1137061da546Spatrick }
1138061da546Spatrick 
PushIOHandler(const IOHandlerSP & reader_sp,bool cancel_top_handler)1139061da546Spatrick void Debugger::PushIOHandler(const IOHandlerSP &reader_sp,
1140061da546Spatrick                              bool cancel_top_handler) {
1141061da546Spatrick   if (!reader_sp)
1142061da546Spatrick     return;
1143061da546Spatrick 
1144dda28197Spatrick   std::lock_guard<std::recursive_mutex> guard(m_io_handler_stack.GetMutex());
1145061da546Spatrick 
1146061da546Spatrick   // Get the current top input reader...
1147dda28197Spatrick   IOHandlerSP top_reader_sp(m_io_handler_stack.Top());
1148061da546Spatrick 
1149061da546Spatrick   // Don't push the same IO handler twice...
1150061da546Spatrick   if (reader_sp == top_reader_sp)
1151061da546Spatrick     return;
1152061da546Spatrick 
1153061da546Spatrick   // Push our new input reader
1154dda28197Spatrick   m_io_handler_stack.Push(reader_sp);
1155061da546Spatrick   reader_sp->Activate();
1156061da546Spatrick 
1157061da546Spatrick   // Interrupt the top input reader to it will exit its Run() function and let
1158061da546Spatrick   // this new input reader take over
1159061da546Spatrick   if (top_reader_sp) {
1160061da546Spatrick     top_reader_sp->Deactivate();
1161061da546Spatrick     if (cancel_top_handler)
1162061da546Spatrick       top_reader_sp->Cancel();
1163061da546Spatrick   }
1164061da546Spatrick }
1165061da546Spatrick 
PopIOHandler(const IOHandlerSP & pop_reader_sp)1166061da546Spatrick bool Debugger::PopIOHandler(const IOHandlerSP &pop_reader_sp) {
1167061da546Spatrick   if (!pop_reader_sp)
1168061da546Spatrick     return false;
1169061da546Spatrick 
1170dda28197Spatrick   std::lock_guard<std::recursive_mutex> guard(m_io_handler_stack.GetMutex());
1171061da546Spatrick 
1172061da546Spatrick   // The reader on the stop of the stack is done, so let the next read on the
1173061da546Spatrick   // stack refresh its prompt and if there is one...
1174dda28197Spatrick   if (m_io_handler_stack.IsEmpty())
1175061da546Spatrick     return false;
1176061da546Spatrick 
1177dda28197Spatrick   IOHandlerSP reader_sp(m_io_handler_stack.Top());
1178061da546Spatrick 
1179061da546Spatrick   if (pop_reader_sp != reader_sp)
1180061da546Spatrick     return false;
1181061da546Spatrick 
1182061da546Spatrick   reader_sp->Deactivate();
1183061da546Spatrick   reader_sp->Cancel();
1184dda28197Spatrick   m_io_handler_stack.Pop();
1185061da546Spatrick 
1186dda28197Spatrick   reader_sp = m_io_handler_stack.Top();
1187061da546Spatrick   if (reader_sp)
1188061da546Spatrick     reader_sp->Activate();
1189061da546Spatrick 
1190061da546Spatrick   return true;
1191061da546Spatrick }
1192061da546Spatrick 
GetAsyncOutputStream()1193061da546Spatrick StreamSP Debugger::GetAsyncOutputStream() {
1194*f6aab3d8Srobert   return std::make_shared<StreamAsynchronousIO>(*this, true, GetUseColor());
1195061da546Spatrick }
1196061da546Spatrick 
GetAsyncErrorStream()1197061da546Spatrick StreamSP Debugger::GetAsyncErrorStream() {
1198*f6aab3d8Srobert   return std::make_shared<StreamAsynchronousIO>(*this, false, GetUseColor());
1199061da546Spatrick }
1200061da546Spatrick 
GetNumDebuggers()1201061da546Spatrick size_t Debugger::GetNumDebuggers() {
1202061da546Spatrick   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
1203061da546Spatrick     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
1204061da546Spatrick     return g_debugger_list_ptr->size();
1205061da546Spatrick   }
1206061da546Spatrick   return 0;
1207061da546Spatrick }
1208061da546Spatrick 
GetDebuggerAtIndex(size_t index)1209061da546Spatrick lldb::DebuggerSP Debugger::GetDebuggerAtIndex(size_t index) {
1210061da546Spatrick   DebuggerSP debugger_sp;
1211061da546Spatrick 
1212061da546Spatrick   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
1213061da546Spatrick     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
1214061da546Spatrick     if (index < g_debugger_list_ptr->size())
1215061da546Spatrick       debugger_sp = g_debugger_list_ptr->at(index);
1216061da546Spatrick   }
1217061da546Spatrick 
1218061da546Spatrick   return debugger_sp;
1219061da546Spatrick }
1220061da546Spatrick 
FindDebuggerWithID(lldb::user_id_t id)1221061da546Spatrick DebuggerSP Debugger::FindDebuggerWithID(lldb::user_id_t id) {
1222061da546Spatrick   DebuggerSP debugger_sp;
1223061da546Spatrick 
1224061da546Spatrick   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
1225061da546Spatrick     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
1226061da546Spatrick     DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
1227061da546Spatrick     for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
1228061da546Spatrick       if ((*pos)->GetID() == id) {
1229061da546Spatrick         debugger_sp = *pos;
1230061da546Spatrick         break;
1231061da546Spatrick       }
1232061da546Spatrick     }
1233061da546Spatrick   }
1234061da546Spatrick   return debugger_sp;
1235061da546Spatrick }
1236061da546Spatrick 
FormatDisassemblerAddress(const FormatEntity::Entry * format,const SymbolContext * sc,const SymbolContext * prev_sc,const ExecutionContext * exe_ctx,const Address * addr,Stream & s)1237061da546Spatrick bool Debugger::FormatDisassemblerAddress(const FormatEntity::Entry *format,
1238061da546Spatrick                                          const SymbolContext *sc,
1239061da546Spatrick                                          const SymbolContext *prev_sc,
1240061da546Spatrick                                          const ExecutionContext *exe_ctx,
1241061da546Spatrick                                          const Address *addr, Stream &s) {
1242061da546Spatrick   FormatEntity::Entry format_entry;
1243061da546Spatrick 
1244061da546Spatrick   if (format == nullptr) {
1245061da546Spatrick     if (exe_ctx != nullptr && exe_ctx->HasTargetScope())
1246061da546Spatrick       format = exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat();
1247061da546Spatrick     if (format == nullptr) {
1248061da546Spatrick       FormatEntity::Parse("${addr}: ", format_entry);
1249061da546Spatrick       format = &format_entry;
1250061da546Spatrick     }
1251061da546Spatrick   }
1252061da546Spatrick   bool function_changed = false;
1253061da546Spatrick   bool initial_function = false;
1254061da546Spatrick   if (prev_sc && (prev_sc->function || prev_sc->symbol)) {
1255061da546Spatrick     if (sc && (sc->function || sc->symbol)) {
1256061da546Spatrick       if (prev_sc->symbol && sc->symbol) {
1257061da546Spatrick         if (!sc->symbol->Compare(prev_sc->symbol->GetName(),
1258061da546Spatrick                                  prev_sc->symbol->GetType())) {
1259061da546Spatrick           function_changed = true;
1260061da546Spatrick         }
1261061da546Spatrick       } else if (prev_sc->function && sc->function) {
1262061da546Spatrick         if (prev_sc->function->GetMangled() != sc->function->GetMangled()) {
1263061da546Spatrick           function_changed = true;
1264061da546Spatrick         }
1265061da546Spatrick       }
1266061da546Spatrick     }
1267061da546Spatrick   }
1268061da546Spatrick   // The first context on a list of instructions will have a prev_sc that has
1269061da546Spatrick   // no Function or Symbol -- if SymbolContext had an IsValid() method, it
1270061da546Spatrick   // would return false.  But we do get a prev_sc pointer.
1271061da546Spatrick   if ((sc && (sc->function || sc->symbol)) && prev_sc &&
1272061da546Spatrick       (prev_sc->function == nullptr && prev_sc->symbol == nullptr)) {
1273061da546Spatrick     initial_function = true;
1274061da546Spatrick   }
1275061da546Spatrick   return FormatEntity::Format(*format, s, sc, exe_ctx, addr, nullptr,
1276061da546Spatrick                               function_changed, initial_function);
1277061da546Spatrick }
1278061da546Spatrick 
SetLoggingCallback(lldb::LogOutputCallback log_callback,void * baton)1279061da546Spatrick void Debugger::SetLoggingCallback(lldb::LogOutputCallback log_callback,
1280061da546Spatrick                                   void *baton) {
1281061da546Spatrick   // For simplicity's sake, I am not going to deal with how to close down any
1282061da546Spatrick   // open logging streams, I just redirect everything from here on out to the
1283061da546Spatrick   // callback.
1284*f6aab3d8Srobert   m_callback_handler_sp =
1285*f6aab3d8Srobert       std::make_shared<CallbackLogHandler>(log_callback, baton);
1286be691f3bSpatrick }
1287be691f3bSpatrick 
PrivateReportProgress(Debugger & debugger,uint64_t progress_id,const std::string & message,uint64_t completed,uint64_t total,bool is_debugger_specific)1288be691f3bSpatrick static void PrivateReportProgress(Debugger &debugger, uint64_t progress_id,
1289be691f3bSpatrick                                   const std::string &message,
1290be691f3bSpatrick                                   uint64_t completed, uint64_t total,
1291be691f3bSpatrick                                   bool is_debugger_specific) {
1292be691f3bSpatrick   // Only deliver progress events if we have any progress listeners.
1293be691f3bSpatrick   const uint32_t event_type = Debugger::eBroadcastBitProgress;
1294be691f3bSpatrick   if (!debugger.GetBroadcaster().EventTypeHasListeners(event_type))
1295be691f3bSpatrick     return;
1296*f6aab3d8Srobert   EventSP event_sp(new Event(
1297*f6aab3d8Srobert       event_type, new ProgressEventData(progress_id, message, completed, total,
1298*f6aab3d8Srobert                                         is_debugger_specific)));
1299be691f3bSpatrick   debugger.GetBroadcaster().BroadcastEvent(event_sp);
1300be691f3bSpatrick }
1301be691f3bSpatrick 
ReportProgress(uint64_t progress_id,const std::string & message,uint64_t completed,uint64_t total,std::optional<lldb::user_id_t> debugger_id)1302be691f3bSpatrick void Debugger::ReportProgress(uint64_t progress_id, const std::string &message,
1303be691f3bSpatrick                               uint64_t completed, uint64_t total,
1304*f6aab3d8Srobert                               std::optional<lldb::user_id_t> debugger_id) {
1305be691f3bSpatrick   // Check if this progress is for a specific debugger.
1306*f6aab3d8Srobert   if (debugger_id) {
1307be691f3bSpatrick     // It is debugger specific, grab it and deliver the event if the debugger
1308be691f3bSpatrick     // still exists.
1309be691f3bSpatrick     DebuggerSP debugger_sp = FindDebuggerWithID(*debugger_id);
1310be691f3bSpatrick     if (debugger_sp)
1311be691f3bSpatrick       PrivateReportProgress(*debugger_sp, progress_id, message, completed,
1312be691f3bSpatrick                             total, /*is_debugger_specific*/ true);
1313be691f3bSpatrick     return;
1314be691f3bSpatrick   }
1315be691f3bSpatrick   // The progress event is not debugger specific, iterate over all debuggers
1316be691f3bSpatrick   // and deliver a progress event to each one.
1317be691f3bSpatrick   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
1318be691f3bSpatrick     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
1319be691f3bSpatrick     DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
1320be691f3bSpatrick     for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos)
1321be691f3bSpatrick       PrivateReportProgress(*(*pos), progress_id, message, completed, total,
1322be691f3bSpatrick                             /*is_debugger_specific*/ false);
1323be691f3bSpatrick   }
1324be691f3bSpatrick }
1325be691f3bSpatrick 
PrivateReportDiagnostic(Debugger & debugger,DiagnosticEventData::Type type,std::string message,bool debugger_specific)1326*f6aab3d8Srobert static void PrivateReportDiagnostic(Debugger &debugger,
1327*f6aab3d8Srobert                                     DiagnosticEventData::Type type,
1328*f6aab3d8Srobert                                     std::string message,
1329*f6aab3d8Srobert                                     bool debugger_specific) {
1330*f6aab3d8Srobert   uint32_t event_type = 0;
1331*f6aab3d8Srobert   switch (type) {
1332*f6aab3d8Srobert   case DiagnosticEventData::Type::Info:
1333*f6aab3d8Srobert     assert(false && "DiagnosticEventData::Type::Info should not be broadcast");
1334*f6aab3d8Srobert     return;
1335*f6aab3d8Srobert   case DiagnosticEventData::Type::Warning:
1336*f6aab3d8Srobert     event_type = Debugger::eBroadcastBitWarning;
1337*f6aab3d8Srobert     break;
1338*f6aab3d8Srobert   case DiagnosticEventData::Type::Error:
1339*f6aab3d8Srobert     event_type = Debugger::eBroadcastBitError;
1340*f6aab3d8Srobert     break;
1341*f6aab3d8Srobert   }
1342*f6aab3d8Srobert 
1343*f6aab3d8Srobert   Broadcaster &broadcaster = debugger.GetBroadcaster();
1344*f6aab3d8Srobert   if (!broadcaster.EventTypeHasListeners(event_type)) {
1345*f6aab3d8Srobert     // Diagnostics are too important to drop. If nobody is listening, print the
1346*f6aab3d8Srobert     // diagnostic directly to the debugger's error stream.
1347*f6aab3d8Srobert     DiagnosticEventData event_data(type, std::move(message), debugger_specific);
1348*f6aab3d8Srobert     StreamSP stream = debugger.GetAsyncErrorStream();
1349*f6aab3d8Srobert     event_data.Dump(stream.get());
1350*f6aab3d8Srobert     return;
1351*f6aab3d8Srobert   }
1352*f6aab3d8Srobert   EventSP event_sp = std::make_shared<Event>(
1353*f6aab3d8Srobert       event_type,
1354*f6aab3d8Srobert       new DiagnosticEventData(type, std::move(message), debugger_specific));
1355*f6aab3d8Srobert   broadcaster.BroadcastEvent(event_sp);
1356*f6aab3d8Srobert }
1357*f6aab3d8Srobert 
ReportDiagnosticImpl(DiagnosticEventData::Type type,std::string message,std::optional<lldb::user_id_t> debugger_id,std::once_flag * once)1358*f6aab3d8Srobert void Debugger::ReportDiagnosticImpl(DiagnosticEventData::Type type,
1359*f6aab3d8Srobert                                     std::string message,
1360*f6aab3d8Srobert                                     std::optional<lldb::user_id_t> debugger_id,
1361*f6aab3d8Srobert                                     std::once_flag *once) {
1362*f6aab3d8Srobert   auto ReportDiagnosticLambda = [&]() {
1363*f6aab3d8Srobert     // The diagnostic subsystem is optional but we still want to broadcast
1364*f6aab3d8Srobert     // events when it's disabled.
1365*f6aab3d8Srobert     if (Diagnostics::Enabled())
1366*f6aab3d8Srobert       Diagnostics::Instance().Report(message);
1367*f6aab3d8Srobert 
1368*f6aab3d8Srobert     // We don't broadcast info events.
1369*f6aab3d8Srobert     if (type == DiagnosticEventData::Type::Info)
1370*f6aab3d8Srobert       return;
1371*f6aab3d8Srobert 
1372*f6aab3d8Srobert     // Check if this diagnostic is for a specific debugger.
1373*f6aab3d8Srobert     if (debugger_id) {
1374*f6aab3d8Srobert       // It is debugger specific, grab it and deliver the event if the debugger
1375*f6aab3d8Srobert       // still exists.
1376*f6aab3d8Srobert       DebuggerSP debugger_sp = FindDebuggerWithID(*debugger_id);
1377*f6aab3d8Srobert       if (debugger_sp)
1378*f6aab3d8Srobert         PrivateReportDiagnostic(*debugger_sp, type, std::move(message), true);
1379*f6aab3d8Srobert       return;
1380*f6aab3d8Srobert     }
1381*f6aab3d8Srobert     // The diagnostic event is not debugger specific, iterate over all debuggers
1382*f6aab3d8Srobert     // and deliver a diagnostic event to each one.
1383*f6aab3d8Srobert     if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
1384*f6aab3d8Srobert       std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
1385*f6aab3d8Srobert       for (const auto &debugger : *g_debugger_list_ptr)
1386*f6aab3d8Srobert         PrivateReportDiagnostic(*debugger, type, message, false);
1387*f6aab3d8Srobert     }
1388*f6aab3d8Srobert   };
1389*f6aab3d8Srobert 
1390*f6aab3d8Srobert   if (once)
1391*f6aab3d8Srobert     std::call_once(*once, ReportDiagnosticLambda);
1392*f6aab3d8Srobert   else
1393*f6aab3d8Srobert     ReportDiagnosticLambda();
1394*f6aab3d8Srobert }
1395*f6aab3d8Srobert 
ReportWarning(std::string message,std::optional<lldb::user_id_t> debugger_id,std::once_flag * once)1396*f6aab3d8Srobert void Debugger::ReportWarning(std::string message,
1397*f6aab3d8Srobert                              std::optional<lldb::user_id_t> debugger_id,
1398*f6aab3d8Srobert                              std::once_flag *once) {
1399*f6aab3d8Srobert   ReportDiagnosticImpl(DiagnosticEventData::Type::Warning, std::move(message),
1400*f6aab3d8Srobert                        debugger_id, once);
1401*f6aab3d8Srobert }
1402*f6aab3d8Srobert 
ReportError(std::string message,std::optional<lldb::user_id_t> debugger_id,std::once_flag * once)1403*f6aab3d8Srobert void Debugger::ReportError(std::string message,
1404*f6aab3d8Srobert                            std::optional<lldb::user_id_t> debugger_id,
1405*f6aab3d8Srobert                            std::once_flag *once) {
1406*f6aab3d8Srobert   ReportDiagnosticImpl(DiagnosticEventData::Type::Error, std::move(message),
1407*f6aab3d8Srobert                        debugger_id, once);
1408*f6aab3d8Srobert }
1409*f6aab3d8Srobert 
ReportInfo(std::string message,std::optional<lldb::user_id_t> debugger_id,std::once_flag * once)1410*f6aab3d8Srobert void Debugger::ReportInfo(std::string message,
1411*f6aab3d8Srobert                           std::optional<lldb::user_id_t> debugger_id,
1412*f6aab3d8Srobert                           std::once_flag *once) {
1413*f6aab3d8Srobert   ReportDiagnosticImpl(DiagnosticEventData::Type::Info, std::move(message),
1414*f6aab3d8Srobert                        debugger_id, once);
1415*f6aab3d8Srobert }
1416*f6aab3d8Srobert 
ReportSymbolChange(const ModuleSpec & module_spec)1417*f6aab3d8Srobert void Debugger::ReportSymbolChange(const ModuleSpec &module_spec) {
1418*f6aab3d8Srobert   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
1419*f6aab3d8Srobert     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
1420*f6aab3d8Srobert     for (DebuggerSP debugger_sp : *g_debugger_list_ptr) {
1421*f6aab3d8Srobert       EventSP event_sp = std::make_shared<Event>(
1422*f6aab3d8Srobert           Debugger::eBroadcastSymbolChange,
1423*f6aab3d8Srobert           new SymbolChangeEventData(debugger_sp, module_spec));
1424*f6aab3d8Srobert       debugger_sp->GetBroadcaster().BroadcastEvent(event_sp);
1425*f6aab3d8Srobert     }
1426*f6aab3d8Srobert   }
1427*f6aab3d8Srobert }
1428*f6aab3d8Srobert 
1429*f6aab3d8Srobert static std::shared_ptr<LogHandler>
CreateLogHandler(LogHandlerKind log_handler_kind,int fd,bool should_close,size_t buffer_size)1430*f6aab3d8Srobert CreateLogHandler(LogHandlerKind log_handler_kind, int fd, bool should_close,
1431*f6aab3d8Srobert                  size_t buffer_size) {
1432*f6aab3d8Srobert   switch (log_handler_kind) {
1433*f6aab3d8Srobert   case eLogHandlerStream:
1434*f6aab3d8Srobert     return std::make_shared<StreamLogHandler>(fd, should_close, buffer_size);
1435*f6aab3d8Srobert   case eLogHandlerCircular:
1436*f6aab3d8Srobert     return std::make_shared<RotatingLogHandler>(buffer_size);
1437*f6aab3d8Srobert   case eLogHandlerSystem:
1438*f6aab3d8Srobert     return std::make_shared<SystemLogHandler>();
1439*f6aab3d8Srobert   case eLogHandlerCallback:
1440*f6aab3d8Srobert     return {};
1441*f6aab3d8Srobert   }
1442*f6aab3d8Srobert   return {};
1443*f6aab3d8Srobert }
1444*f6aab3d8Srobert 
EnableLog(llvm::StringRef channel,llvm::ArrayRef<const char * > categories,llvm::StringRef log_file,uint32_t log_options,size_t buffer_size,LogHandlerKind log_handler_kind,llvm::raw_ostream & error_stream)1445061da546Spatrick bool Debugger::EnableLog(llvm::StringRef channel,
1446061da546Spatrick                          llvm::ArrayRef<const char *> categories,
1447061da546Spatrick                          llvm::StringRef log_file, uint32_t log_options,
1448*f6aab3d8Srobert                          size_t buffer_size, LogHandlerKind log_handler_kind,
1449061da546Spatrick                          llvm::raw_ostream &error_stream) {
1450061da546Spatrick 
1451*f6aab3d8Srobert   std::shared_ptr<LogHandler> log_handler_sp;
1452*f6aab3d8Srobert   if (m_callback_handler_sp) {
1453*f6aab3d8Srobert     log_handler_sp = m_callback_handler_sp;
1454061da546Spatrick     // For now when using the callback mode you always get thread & timestamp.
1455061da546Spatrick     log_options |=
1456061da546Spatrick         LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_THREAD_NAME;
1457061da546Spatrick   } else if (log_file.empty()) {
1458*f6aab3d8Srobert     log_handler_sp =
1459*f6aab3d8Srobert         CreateLogHandler(log_handler_kind, GetOutputFile().GetDescriptor(),
1460*f6aab3d8Srobert                          /*should_close=*/false, buffer_size);
1461061da546Spatrick   } else {
1462*f6aab3d8Srobert     auto pos = m_stream_handlers.find(log_file);
1463*f6aab3d8Srobert     if (pos != m_stream_handlers.end())
1464*f6aab3d8Srobert       log_handler_sp = pos->second.lock();
1465*f6aab3d8Srobert     if (!log_handler_sp) {
1466dda28197Spatrick       File::OpenOptions flags =
1467*f6aab3d8Srobert           File::eOpenOptionWriteOnly | File::eOpenOptionCanCreate;
1468061da546Spatrick       if (log_options & LLDB_LOG_OPTION_APPEND)
1469dda28197Spatrick         flags |= File::eOpenOptionAppend;
1470dda28197Spatrick       else
1471dda28197Spatrick         flags |= File::eOpenOptionTruncate;
1472be691f3bSpatrick       llvm::Expected<FileUP> file = FileSystem::Instance().Open(
1473dda28197Spatrick           FileSpec(log_file), flags, lldb::eFilePermissionsFileDefault, false);
1474dda28197Spatrick       if (!file) {
1475be691f3bSpatrick         error_stream << "Unable to open log file '" << log_file
1476be691f3bSpatrick                      << "': " << llvm::toString(file.takeError()) << "\n";
1477061da546Spatrick         return false;
1478061da546Spatrick       }
1479dda28197Spatrick 
1480*f6aab3d8Srobert       log_handler_sp =
1481*f6aab3d8Srobert           CreateLogHandler(log_handler_kind, (*file)->GetDescriptor(),
1482*f6aab3d8Srobert                            /*should_close=*/true, buffer_size);
1483*f6aab3d8Srobert       m_stream_handlers[log_file] = log_handler_sp;
1484061da546Spatrick     }
1485061da546Spatrick   }
1486*f6aab3d8Srobert   assert(log_handler_sp);
1487061da546Spatrick 
1488061da546Spatrick   if (log_options == 0)
1489*f6aab3d8Srobert     log_options = LLDB_LOG_OPTION_PREPEND_THREAD_NAME;
1490061da546Spatrick 
1491*f6aab3d8Srobert   return Log::EnableLogChannel(log_handler_sp, log_options, channel, categories,
1492061da546Spatrick                                error_stream);
1493061da546Spatrick }
1494061da546Spatrick 
1495061da546Spatrick ScriptInterpreter *
GetScriptInterpreter(bool can_create,std::optional<lldb::ScriptLanguage> language)1496061da546Spatrick Debugger::GetScriptInterpreter(bool can_create,
1497*f6aab3d8Srobert                                std::optional<lldb::ScriptLanguage> language) {
1498061da546Spatrick   std::lock_guard<std::recursive_mutex> locker(m_script_interpreter_mutex);
1499061da546Spatrick   lldb::ScriptLanguage script_language =
1500061da546Spatrick       language ? *language : GetScriptLanguage();
1501061da546Spatrick 
1502061da546Spatrick   if (!m_script_interpreters[script_language]) {
1503061da546Spatrick     if (!can_create)
1504061da546Spatrick       return nullptr;
1505061da546Spatrick     m_script_interpreters[script_language] =
1506061da546Spatrick         PluginManager::GetScriptInterpreterForLanguage(script_language, *this);
1507061da546Spatrick   }
1508061da546Spatrick 
1509061da546Spatrick   return m_script_interpreters[script_language].get();
1510061da546Spatrick }
1511061da546Spatrick 
GetSourceManager()1512061da546Spatrick SourceManager &Debugger::GetSourceManager() {
1513061da546Spatrick   if (!m_source_manager_up)
1514061da546Spatrick     m_source_manager_up = std::make_unique<SourceManager>(shared_from_this());
1515061da546Spatrick   return *m_source_manager_up;
1516061da546Spatrick }
1517061da546Spatrick 
1518061da546Spatrick // This function handles events that were broadcast by the process.
HandleBreakpointEvent(const EventSP & event_sp)1519061da546Spatrick void Debugger::HandleBreakpointEvent(const EventSP &event_sp) {
1520061da546Spatrick   using namespace lldb;
1521061da546Spatrick   const uint32_t event_type =
1522061da546Spatrick       Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent(
1523061da546Spatrick           event_sp);
1524061da546Spatrick 
1525061da546Spatrick   //    if (event_type & eBreakpointEventTypeAdded
1526061da546Spatrick   //        || event_type & eBreakpointEventTypeRemoved
1527061da546Spatrick   //        || event_type & eBreakpointEventTypeEnabled
1528061da546Spatrick   //        || event_type & eBreakpointEventTypeDisabled
1529061da546Spatrick   //        || event_type & eBreakpointEventTypeCommandChanged
1530061da546Spatrick   //        || event_type & eBreakpointEventTypeConditionChanged
1531061da546Spatrick   //        || event_type & eBreakpointEventTypeIgnoreChanged
1532061da546Spatrick   //        || event_type & eBreakpointEventTypeLocationsResolved)
1533061da546Spatrick   //    {
1534061da546Spatrick   //        // Don't do anything about these events, since the breakpoint
1535061da546Spatrick   //        commands already echo these actions.
1536061da546Spatrick   //    }
1537061da546Spatrick   //
1538061da546Spatrick   if (event_type & eBreakpointEventTypeLocationsAdded) {
1539061da546Spatrick     uint32_t num_new_locations =
1540061da546Spatrick         Breakpoint::BreakpointEventData::GetNumBreakpointLocationsFromEvent(
1541061da546Spatrick             event_sp);
1542061da546Spatrick     if (num_new_locations > 0) {
1543061da546Spatrick       BreakpointSP breakpoint =
1544061da546Spatrick           Breakpoint::BreakpointEventData::GetBreakpointFromEvent(event_sp);
1545061da546Spatrick       StreamSP output_sp(GetAsyncOutputStream());
1546061da546Spatrick       if (output_sp) {
1547061da546Spatrick         output_sp->Printf("%d location%s added to breakpoint %d\n",
1548061da546Spatrick                           num_new_locations, num_new_locations == 1 ? "" : "s",
1549061da546Spatrick                           breakpoint->GetID());
1550061da546Spatrick         output_sp->Flush();
1551061da546Spatrick       }
1552061da546Spatrick     }
1553061da546Spatrick   }
1554061da546Spatrick   //    else if (event_type & eBreakpointEventTypeLocationsRemoved)
1555061da546Spatrick   //    {
1556061da546Spatrick   //        // These locations just get disabled, not sure it is worth spamming
1557061da546Spatrick   //        folks about this on the command line.
1558061da546Spatrick   //    }
1559061da546Spatrick   //    else if (event_type & eBreakpointEventTypeLocationsResolved)
1560061da546Spatrick   //    {
1561061da546Spatrick   //        // This might be an interesting thing to note, but I'm going to
1562061da546Spatrick   //        leave it quiet for now, it just looked noisy.
1563061da546Spatrick   //    }
1564061da546Spatrick }
1565061da546Spatrick 
FlushProcessOutput(Process & process,bool flush_stdout,bool flush_stderr)1566061da546Spatrick void Debugger::FlushProcessOutput(Process &process, bool flush_stdout,
1567061da546Spatrick                                   bool flush_stderr) {
1568061da546Spatrick   const auto &flush = [&](Stream &stream,
1569061da546Spatrick                           size_t (Process::*get)(char *, size_t, Status &)) {
1570061da546Spatrick     Status error;
1571061da546Spatrick     size_t len;
1572061da546Spatrick     char buffer[1024];
1573061da546Spatrick     while ((len = (process.*get)(buffer, sizeof(buffer), error)) > 0)
1574061da546Spatrick       stream.Write(buffer, len);
1575061da546Spatrick     stream.Flush();
1576061da546Spatrick   };
1577061da546Spatrick 
1578061da546Spatrick   std::lock_guard<std::mutex> guard(m_output_flush_mutex);
1579061da546Spatrick   if (flush_stdout)
1580061da546Spatrick     flush(*GetAsyncOutputStream(), &Process::GetSTDOUT);
1581061da546Spatrick   if (flush_stderr)
1582061da546Spatrick     flush(*GetAsyncErrorStream(), &Process::GetSTDERR);
1583061da546Spatrick }
1584061da546Spatrick 
1585061da546Spatrick // This function handles events that were broadcast by the process.
HandleProcessEvent(const EventSP & event_sp)1586061da546Spatrick void Debugger::HandleProcessEvent(const EventSP &event_sp) {
1587061da546Spatrick   using namespace lldb;
1588061da546Spatrick   const uint32_t event_type = event_sp->GetType();
1589061da546Spatrick   ProcessSP process_sp =
1590061da546Spatrick       (event_type == Process::eBroadcastBitStructuredData)
1591061da546Spatrick           ? EventDataStructuredData::GetProcessFromEvent(event_sp.get())
1592061da546Spatrick           : Process::ProcessEventData::GetProcessFromEvent(event_sp.get());
1593061da546Spatrick 
1594061da546Spatrick   StreamSP output_stream_sp = GetAsyncOutputStream();
1595061da546Spatrick   StreamSP error_stream_sp = GetAsyncErrorStream();
1596061da546Spatrick   const bool gui_enabled = IsForwardingEvents();
1597061da546Spatrick 
1598061da546Spatrick   if (!gui_enabled) {
1599061da546Spatrick     bool pop_process_io_handler = false;
1600061da546Spatrick     assert(process_sp);
1601061da546Spatrick 
1602061da546Spatrick     bool state_is_stopped = false;
1603061da546Spatrick     const bool got_state_changed =
1604061da546Spatrick         (event_type & Process::eBroadcastBitStateChanged) != 0;
1605061da546Spatrick     const bool got_stdout = (event_type & Process::eBroadcastBitSTDOUT) != 0;
1606061da546Spatrick     const bool got_stderr = (event_type & Process::eBroadcastBitSTDERR) != 0;
1607061da546Spatrick     const bool got_structured_data =
1608061da546Spatrick         (event_type & Process::eBroadcastBitStructuredData) != 0;
1609061da546Spatrick 
1610061da546Spatrick     if (got_state_changed) {
1611061da546Spatrick       StateType event_state =
1612061da546Spatrick           Process::ProcessEventData::GetStateFromEvent(event_sp.get());
1613061da546Spatrick       state_is_stopped = StateIsStoppedState(event_state, false);
1614061da546Spatrick     }
1615061da546Spatrick 
1616061da546Spatrick     // Display running state changes first before any STDIO
1617061da546Spatrick     if (got_state_changed && !state_is_stopped) {
1618061da546Spatrick       Process::HandleProcessStateChangedEvent(event_sp, output_stream_sp.get(),
1619061da546Spatrick                                               pop_process_io_handler);
1620061da546Spatrick     }
1621061da546Spatrick 
1622061da546Spatrick     // Now display STDOUT and STDERR
1623061da546Spatrick     FlushProcessOutput(*process_sp, got_stdout || got_state_changed,
1624061da546Spatrick                        got_stderr || got_state_changed);
1625061da546Spatrick 
1626061da546Spatrick     // Give structured data events an opportunity to display.
1627061da546Spatrick     if (got_structured_data) {
1628061da546Spatrick       StructuredDataPluginSP plugin_sp =
1629061da546Spatrick           EventDataStructuredData::GetPluginFromEvent(event_sp.get());
1630061da546Spatrick       if (plugin_sp) {
1631061da546Spatrick         auto structured_data_sp =
1632061da546Spatrick             EventDataStructuredData::GetObjectFromEvent(event_sp.get());
1633061da546Spatrick         if (output_stream_sp) {
1634061da546Spatrick           StreamString content_stream;
1635061da546Spatrick           Status error =
1636061da546Spatrick               plugin_sp->GetDescription(structured_data_sp, content_stream);
1637061da546Spatrick           if (error.Success()) {
1638061da546Spatrick             if (!content_stream.GetString().empty()) {
1639061da546Spatrick               // Add newline.
1640061da546Spatrick               content_stream.PutChar('\n');
1641061da546Spatrick               content_stream.Flush();
1642061da546Spatrick 
1643061da546Spatrick               // Print it.
1644061da546Spatrick               output_stream_sp->PutCString(content_stream.GetString());
1645061da546Spatrick             }
1646061da546Spatrick           } else {
1647*f6aab3d8Srobert             error_stream_sp->Format("Failed to print structured "
1648*f6aab3d8Srobert                                     "data with plugin {0}: {1}",
1649*f6aab3d8Srobert                                     plugin_sp->GetPluginName(), error);
1650061da546Spatrick           }
1651061da546Spatrick         }
1652061da546Spatrick       }
1653061da546Spatrick     }
1654061da546Spatrick 
1655061da546Spatrick     // Now display any stopped state changes after any STDIO
1656061da546Spatrick     if (got_state_changed && state_is_stopped) {
1657061da546Spatrick       Process::HandleProcessStateChangedEvent(event_sp, output_stream_sp.get(),
1658061da546Spatrick                                               pop_process_io_handler);
1659061da546Spatrick     }
1660061da546Spatrick 
1661061da546Spatrick     output_stream_sp->Flush();
1662061da546Spatrick     error_stream_sp->Flush();
1663061da546Spatrick 
1664061da546Spatrick     if (pop_process_io_handler)
1665061da546Spatrick       process_sp->PopProcessIOHandler();
1666061da546Spatrick   }
1667061da546Spatrick }
1668061da546Spatrick 
HandleThreadEvent(const EventSP & event_sp)1669061da546Spatrick void Debugger::HandleThreadEvent(const EventSP &event_sp) {
1670061da546Spatrick   // At present the only thread event we handle is the Frame Changed event, and
1671061da546Spatrick   // all we do for that is just reprint the thread status for that thread.
1672061da546Spatrick   using namespace lldb;
1673061da546Spatrick   const uint32_t event_type = event_sp->GetType();
1674061da546Spatrick   const bool stop_format = true;
1675061da546Spatrick   if (event_type == Thread::eBroadcastBitStackChanged ||
1676061da546Spatrick       event_type == Thread::eBroadcastBitThreadSelected) {
1677061da546Spatrick     ThreadSP thread_sp(
1678061da546Spatrick         Thread::ThreadEventData::GetThreadFromEvent(event_sp.get()));
1679061da546Spatrick     if (thread_sp) {
1680061da546Spatrick       thread_sp->GetStatus(*GetAsyncOutputStream(), 0, 1, 1, stop_format);
1681061da546Spatrick     }
1682061da546Spatrick   }
1683061da546Spatrick }
1684061da546Spatrick 
IsForwardingEvents()1685061da546Spatrick bool Debugger::IsForwardingEvents() { return (bool)m_forward_listener_sp; }
1686061da546Spatrick 
EnableForwardEvents(const ListenerSP & listener_sp)1687061da546Spatrick void Debugger::EnableForwardEvents(const ListenerSP &listener_sp) {
1688061da546Spatrick   m_forward_listener_sp = listener_sp;
1689061da546Spatrick }
1690061da546Spatrick 
CancelForwardEvents(const ListenerSP & listener_sp)1691061da546Spatrick void Debugger::CancelForwardEvents(const ListenerSP &listener_sp) {
1692061da546Spatrick   m_forward_listener_sp.reset();
1693061da546Spatrick }
1694061da546Spatrick 
DefaultEventHandler()1695*f6aab3d8Srobert lldb::thread_result_t Debugger::DefaultEventHandler() {
1696061da546Spatrick   ListenerSP listener_sp(GetListener());
1697061da546Spatrick   ConstString broadcaster_class_target(Target::GetStaticBroadcasterClass());
1698061da546Spatrick   ConstString broadcaster_class_process(Process::GetStaticBroadcasterClass());
1699061da546Spatrick   ConstString broadcaster_class_thread(Thread::GetStaticBroadcasterClass());
1700061da546Spatrick   BroadcastEventSpec target_event_spec(broadcaster_class_target,
1701061da546Spatrick                                        Target::eBroadcastBitBreakpointChanged);
1702061da546Spatrick 
1703061da546Spatrick   BroadcastEventSpec process_event_spec(
1704061da546Spatrick       broadcaster_class_process,
1705061da546Spatrick       Process::eBroadcastBitStateChanged | Process::eBroadcastBitSTDOUT |
1706061da546Spatrick           Process::eBroadcastBitSTDERR | Process::eBroadcastBitStructuredData);
1707061da546Spatrick 
1708061da546Spatrick   BroadcastEventSpec thread_event_spec(broadcaster_class_thread,
1709061da546Spatrick                                        Thread::eBroadcastBitStackChanged |
1710061da546Spatrick                                            Thread::eBroadcastBitThreadSelected);
1711061da546Spatrick 
1712061da546Spatrick   listener_sp->StartListeningForEventSpec(m_broadcaster_manager_sp,
1713061da546Spatrick                                           target_event_spec);
1714061da546Spatrick   listener_sp->StartListeningForEventSpec(m_broadcaster_manager_sp,
1715061da546Spatrick                                           process_event_spec);
1716061da546Spatrick   listener_sp->StartListeningForEventSpec(m_broadcaster_manager_sp,
1717061da546Spatrick                                           thread_event_spec);
1718061da546Spatrick   listener_sp->StartListeningForEvents(
1719061da546Spatrick       m_command_interpreter_up.get(),
1720061da546Spatrick       CommandInterpreter::eBroadcastBitQuitCommandReceived |
1721061da546Spatrick           CommandInterpreter::eBroadcastBitAsynchronousOutputData |
1722061da546Spatrick           CommandInterpreter::eBroadcastBitAsynchronousErrorData);
1723061da546Spatrick 
1724*f6aab3d8Srobert   listener_sp->StartListeningForEvents(
1725*f6aab3d8Srobert       &m_broadcaster, eBroadcastBitProgress | eBroadcastBitWarning |
1726*f6aab3d8Srobert                           eBroadcastBitError | eBroadcastSymbolChange);
1727*f6aab3d8Srobert 
1728061da546Spatrick   // Let the thread that spawned us know that we have started up and that we
1729061da546Spatrick   // are now listening to all required events so no events get missed
1730061da546Spatrick   m_sync_broadcaster.BroadcastEvent(eBroadcastBitEventThreadIsListening);
1731061da546Spatrick 
1732061da546Spatrick   bool done = false;
1733061da546Spatrick   while (!done) {
1734061da546Spatrick     EventSP event_sp;
1735*f6aab3d8Srobert     if (listener_sp->GetEvent(event_sp, std::nullopt)) {
1736061da546Spatrick       if (event_sp) {
1737061da546Spatrick         Broadcaster *broadcaster = event_sp->GetBroadcaster();
1738061da546Spatrick         if (broadcaster) {
1739061da546Spatrick           uint32_t event_type = event_sp->GetType();
1740061da546Spatrick           ConstString broadcaster_class(broadcaster->GetBroadcasterClass());
1741061da546Spatrick           if (broadcaster_class == broadcaster_class_process) {
1742061da546Spatrick             HandleProcessEvent(event_sp);
1743061da546Spatrick           } else if (broadcaster_class == broadcaster_class_target) {
1744061da546Spatrick             if (Breakpoint::BreakpointEventData::GetEventDataFromEvent(
1745061da546Spatrick                     event_sp.get())) {
1746061da546Spatrick               HandleBreakpointEvent(event_sp);
1747061da546Spatrick             }
1748061da546Spatrick           } else if (broadcaster_class == broadcaster_class_thread) {
1749061da546Spatrick             HandleThreadEvent(event_sp);
1750061da546Spatrick           } else if (broadcaster == m_command_interpreter_up.get()) {
1751061da546Spatrick             if (event_type &
1752061da546Spatrick                 CommandInterpreter::eBroadcastBitQuitCommandReceived) {
1753061da546Spatrick               done = true;
1754061da546Spatrick             } else if (event_type &
1755061da546Spatrick                        CommandInterpreter::eBroadcastBitAsynchronousErrorData) {
1756061da546Spatrick               const char *data = static_cast<const char *>(
1757061da546Spatrick                   EventDataBytes::GetBytesFromEvent(event_sp.get()));
1758061da546Spatrick               if (data && data[0]) {
1759061da546Spatrick                 StreamSP error_sp(GetAsyncErrorStream());
1760061da546Spatrick                 if (error_sp) {
1761061da546Spatrick                   error_sp->PutCString(data);
1762061da546Spatrick                   error_sp->Flush();
1763061da546Spatrick                 }
1764061da546Spatrick               }
1765061da546Spatrick             } else if (event_type & CommandInterpreter::
1766061da546Spatrick                                         eBroadcastBitAsynchronousOutputData) {
1767061da546Spatrick               const char *data = static_cast<const char *>(
1768061da546Spatrick                   EventDataBytes::GetBytesFromEvent(event_sp.get()));
1769061da546Spatrick               if (data && data[0]) {
1770061da546Spatrick                 StreamSP output_sp(GetAsyncOutputStream());
1771061da546Spatrick                 if (output_sp) {
1772061da546Spatrick                   output_sp->PutCString(data);
1773061da546Spatrick                   output_sp->Flush();
1774061da546Spatrick                 }
1775061da546Spatrick               }
1776061da546Spatrick             }
1777*f6aab3d8Srobert           } else if (broadcaster == &m_broadcaster) {
1778*f6aab3d8Srobert             if (event_type & Debugger::eBroadcastBitProgress)
1779*f6aab3d8Srobert               HandleProgressEvent(event_sp);
1780*f6aab3d8Srobert             else if (event_type & Debugger::eBroadcastBitWarning)
1781*f6aab3d8Srobert               HandleDiagnosticEvent(event_sp);
1782*f6aab3d8Srobert             else if (event_type & Debugger::eBroadcastBitError)
1783*f6aab3d8Srobert               HandleDiagnosticEvent(event_sp);
1784061da546Spatrick           }
1785061da546Spatrick         }
1786061da546Spatrick 
1787061da546Spatrick         if (m_forward_listener_sp)
1788061da546Spatrick           m_forward_listener_sp->AddEvent(event_sp);
1789061da546Spatrick       }
1790061da546Spatrick     }
1791061da546Spatrick   }
1792061da546Spatrick   return {};
1793061da546Spatrick }
1794061da546Spatrick 
StartEventHandlerThread()1795061da546Spatrick bool Debugger::StartEventHandlerThread() {
1796061da546Spatrick   if (!m_event_handler_thread.IsJoinable()) {
1797061da546Spatrick     // We must synchronize with the DefaultEventHandler() thread to ensure it
1798061da546Spatrick     // is up and running and listening to events before we return from this
1799061da546Spatrick     // function. We do this by listening to events for the
1800061da546Spatrick     // eBroadcastBitEventThreadIsListening from the m_sync_broadcaster
1801061da546Spatrick     ConstString full_name("lldb.debugger.event-handler");
1802061da546Spatrick     ListenerSP listener_sp(Listener::MakeListener(full_name.AsCString()));
1803061da546Spatrick     listener_sp->StartListeningForEvents(&m_sync_broadcaster,
1804061da546Spatrick                                          eBroadcastBitEventThreadIsListening);
1805061da546Spatrick 
1806dda28197Spatrick     llvm::StringRef thread_name =
1807061da546Spatrick         full_name.GetLength() < llvm::get_max_thread_name_length()
1808dda28197Spatrick             ? full_name.GetStringRef()
1809061da546Spatrick             : "dbg.evt-handler";
1810061da546Spatrick 
1811061da546Spatrick     // Use larger 8MB stack for this thread
1812061da546Spatrick     llvm::Expected<HostThread> event_handler_thread =
1813*f6aab3d8Srobert         ThreadLauncher::LaunchThread(
1814*f6aab3d8Srobert             thread_name, [this] { return DefaultEventHandler(); },
1815061da546Spatrick             g_debugger_event_thread_stack_bytes);
1816061da546Spatrick 
1817061da546Spatrick     if (event_handler_thread) {
1818061da546Spatrick       m_event_handler_thread = *event_handler_thread;
1819061da546Spatrick     } else {
1820*f6aab3d8Srobert       LLDB_LOG(GetLog(LLDBLog::Host), "failed to launch host thread: {}",
1821061da546Spatrick                llvm::toString(event_handler_thread.takeError()));
1822061da546Spatrick     }
1823061da546Spatrick 
1824061da546Spatrick     // Make sure DefaultEventHandler() is running and listening to events
1825061da546Spatrick     // before we return from this function. We are only listening for events of
1826061da546Spatrick     // type eBroadcastBitEventThreadIsListening so we don't need to check the
1827061da546Spatrick     // event, we just need to wait an infinite amount of time for it (nullptr
1828061da546Spatrick     // timeout as the first parameter)
1829061da546Spatrick     lldb::EventSP event_sp;
1830*f6aab3d8Srobert     listener_sp->GetEvent(event_sp, std::nullopt);
1831061da546Spatrick   }
1832061da546Spatrick   return m_event_handler_thread.IsJoinable();
1833061da546Spatrick }
1834061da546Spatrick 
StopEventHandlerThread()1835061da546Spatrick void Debugger::StopEventHandlerThread() {
1836061da546Spatrick   if (m_event_handler_thread.IsJoinable()) {
1837061da546Spatrick     GetCommandInterpreter().BroadcastEvent(
1838061da546Spatrick         CommandInterpreter::eBroadcastBitQuitCommandReceived);
1839061da546Spatrick     m_event_handler_thread.Join(nullptr);
1840061da546Spatrick   }
1841061da546Spatrick }
1842061da546Spatrick 
IOHandlerThread()1843*f6aab3d8Srobert lldb::thread_result_t Debugger::IOHandlerThread() {
1844*f6aab3d8Srobert   RunIOHandlers();
1845*f6aab3d8Srobert   StopEventHandlerThread();
1846061da546Spatrick   return {};
1847061da546Spatrick }
1848061da546Spatrick 
HandleProgressEvent(const lldb::EventSP & event_sp)1849*f6aab3d8Srobert void Debugger::HandleProgressEvent(const lldb::EventSP &event_sp) {
1850*f6aab3d8Srobert   auto *data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
1851*f6aab3d8Srobert   if (!data)
1852*f6aab3d8Srobert     return;
1853*f6aab3d8Srobert 
1854*f6aab3d8Srobert   // Do some bookkeeping for the current event, regardless of whether we're
1855*f6aab3d8Srobert   // going to show the progress.
1856*f6aab3d8Srobert   const uint64_t id = data->GetID();
1857*f6aab3d8Srobert   if (m_current_event_id) {
1858*f6aab3d8Srobert     Log *log = GetLog(LLDBLog::Events);
1859*f6aab3d8Srobert     if (log && log->GetVerbose()) {
1860*f6aab3d8Srobert       StreamString log_stream;
1861*f6aab3d8Srobert       log_stream.AsRawOstream()
1862*f6aab3d8Srobert           << static_cast<void *>(this) << " Debugger(" << GetID()
1863*f6aab3d8Srobert           << ")::HandleProgressEvent( m_current_event_id = "
1864*f6aab3d8Srobert           << *m_current_event_id << ", data = { ";
1865*f6aab3d8Srobert       data->Dump(&log_stream);
1866*f6aab3d8Srobert       log_stream << " } )";
1867*f6aab3d8Srobert       log->PutString(log_stream.GetString());
1868*f6aab3d8Srobert     }
1869*f6aab3d8Srobert     if (id != *m_current_event_id)
1870*f6aab3d8Srobert       return;
1871*f6aab3d8Srobert     if (data->GetCompleted() == data->GetTotal())
1872*f6aab3d8Srobert       m_current_event_id.reset();
1873*f6aab3d8Srobert   } else {
1874*f6aab3d8Srobert     m_current_event_id = id;
1875*f6aab3d8Srobert   }
1876*f6aab3d8Srobert 
1877*f6aab3d8Srobert   // Decide whether we actually are going to show the progress. This decision
1878*f6aab3d8Srobert   // can change between iterations so check it inside the loop.
1879*f6aab3d8Srobert   if (!GetShowProgress())
1880*f6aab3d8Srobert     return;
1881*f6aab3d8Srobert 
1882*f6aab3d8Srobert   // Determine whether the current output file is an interactive terminal with
1883*f6aab3d8Srobert   // color support. We assume that if we support ANSI escape codes we support
1884*f6aab3d8Srobert   // vt100 escape codes.
1885*f6aab3d8Srobert   File &file = GetOutputFile();
1886*f6aab3d8Srobert   if (!file.GetIsInteractive() || !file.GetIsTerminalWithColors())
1887*f6aab3d8Srobert     return;
1888*f6aab3d8Srobert 
1889*f6aab3d8Srobert   StreamSP output = GetAsyncOutputStream();
1890*f6aab3d8Srobert 
1891*f6aab3d8Srobert   // Print over previous line, if any.
1892*f6aab3d8Srobert   output->Printf("\r");
1893*f6aab3d8Srobert 
1894*f6aab3d8Srobert   if (data->GetCompleted() == data->GetTotal()) {
1895*f6aab3d8Srobert     // Clear the current line.
1896*f6aab3d8Srobert     output->Printf("\x1B[2K");
1897*f6aab3d8Srobert     output->Flush();
1898*f6aab3d8Srobert     return;
1899*f6aab3d8Srobert   }
1900*f6aab3d8Srobert 
1901*f6aab3d8Srobert   // Trim the progress message if it exceeds the window's width and print it.
1902*f6aab3d8Srobert   std::string message = data->GetMessage();
1903*f6aab3d8Srobert   if (data->IsFinite())
1904*f6aab3d8Srobert     message = llvm::formatv("[{0}/{1}] {2}", data->GetCompleted(),
1905*f6aab3d8Srobert                             data->GetTotal(), message)
1906*f6aab3d8Srobert                   .str();
1907*f6aab3d8Srobert 
1908*f6aab3d8Srobert   // Trim the progress message if it exceeds the window's width and print it.
1909*f6aab3d8Srobert   const uint32_t term_width = GetTerminalWidth();
1910*f6aab3d8Srobert   const uint32_t ellipsis = 3;
1911*f6aab3d8Srobert   if (message.size() + ellipsis >= term_width)
1912*f6aab3d8Srobert     message = message.substr(0, term_width - ellipsis);
1913*f6aab3d8Srobert 
1914*f6aab3d8Srobert   const bool use_color = GetUseColor();
1915*f6aab3d8Srobert   llvm::StringRef ansi_prefix = GetShowProgressAnsiPrefix();
1916*f6aab3d8Srobert   if (!ansi_prefix.empty())
1917*f6aab3d8Srobert     output->Printf(
1918*f6aab3d8Srobert         "%s", ansi::FormatAnsiTerminalCodes(ansi_prefix, use_color).c_str());
1919*f6aab3d8Srobert 
1920*f6aab3d8Srobert   output->Printf("%s...", message.c_str());
1921*f6aab3d8Srobert 
1922*f6aab3d8Srobert   llvm::StringRef ansi_suffix = GetShowProgressAnsiSuffix();
1923*f6aab3d8Srobert   if (!ansi_suffix.empty())
1924*f6aab3d8Srobert     output->Printf(
1925*f6aab3d8Srobert         "%s", ansi::FormatAnsiTerminalCodes(ansi_suffix, use_color).c_str());
1926*f6aab3d8Srobert 
1927*f6aab3d8Srobert   // Clear until the end of the line.
1928*f6aab3d8Srobert   output->Printf("\x1B[K\r");
1929*f6aab3d8Srobert 
1930*f6aab3d8Srobert   // Flush the output.
1931*f6aab3d8Srobert   output->Flush();
1932*f6aab3d8Srobert }
1933*f6aab3d8Srobert 
HandleDiagnosticEvent(const lldb::EventSP & event_sp)1934*f6aab3d8Srobert void Debugger::HandleDiagnosticEvent(const lldb::EventSP &event_sp) {
1935*f6aab3d8Srobert   auto *data = DiagnosticEventData::GetEventDataFromEvent(event_sp.get());
1936*f6aab3d8Srobert   if (!data)
1937*f6aab3d8Srobert     return;
1938*f6aab3d8Srobert 
1939*f6aab3d8Srobert   StreamSP stream = GetAsyncErrorStream();
1940*f6aab3d8Srobert   data->Dump(stream.get());
1941*f6aab3d8Srobert }
1942*f6aab3d8Srobert 
HasIOHandlerThread()1943061da546Spatrick bool Debugger::HasIOHandlerThread() { return m_io_handler_thread.IsJoinable(); }
1944061da546Spatrick 
StartIOHandlerThread()1945061da546Spatrick bool Debugger::StartIOHandlerThread() {
1946061da546Spatrick   if (!m_io_handler_thread.IsJoinable()) {
1947061da546Spatrick     llvm::Expected<HostThread> io_handler_thread = ThreadLauncher::LaunchThread(
1948*f6aab3d8Srobert         "lldb.debugger.io-handler", [this] { return IOHandlerThread(); },
1949061da546Spatrick         8 * 1024 * 1024); // Use larger 8MB stack for this thread
1950061da546Spatrick     if (io_handler_thread) {
1951061da546Spatrick       m_io_handler_thread = *io_handler_thread;
1952061da546Spatrick     } else {
1953*f6aab3d8Srobert       LLDB_LOG(GetLog(LLDBLog::Host), "failed to launch host thread: {}",
1954061da546Spatrick                llvm::toString(io_handler_thread.takeError()));
1955061da546Spatrick     }
1956061da546Spatrick   }
1957061da546Spatrick   return m_io_handler_thread.IsJoinable();
1958061da546Spatrick }
1959061da546Spatrick 
StopIOHandlerThread()1960061da546Spatrick void Debugger::StopIOHandlerThread() {
1961061da546Spatrick   if (m_io_handler_thread.IsJoinable()) {
1962061da546Spatrick     GetInputFile().Close();
1963061da546Spatrick     m_io_handler_thread.Join(nullptr);
1964061da546Spatrick   }
1965061da546Spatrick }
1966061da546Spatrick 
JoinIOHandlerThread()1967061da546Spatrick void Debugger::JoinIOHandlerThread() {
1968061da546Spatrick   if (HasIOHandlerThread()) {
1969061da546Spatrick     thread_result_t result;
1970061da546Spatrick     m_io_handler_thread.Join(&result);
1971061da546Spatrick     m_io_handler_thread = LLDB_INVALID_HOST_THREAD;
1972061da546Spatrick   }
1973061da546Spatrick }
1974061da546Spatrick 
GetSelectedOrDummyTarget(bool prefer_dummy)1975be691f3bSpatrick Target &Debugger::GetSelectedOrDummyTarget(bool prefer_dummy) {
1976061da546Spatrick   if (!prefer_dummy) {
1977be691f3bSpatrick     if (TargetSP target = m_target_list.GetSelectedTarget())
1978be691f3bSpatrick       return *target;
1979061da546Spatrick   }
1980061da546Spatrick   return GetDummyTarget();
1981061da546Spatrick }
1982061da546Spatrick 
RunREPL(LanguageType language,const char * repl_options)1983061da546Spatrick Status Debugger::RunREPL(LanguageType language, const char *repl_options) {
1984061da546Spatrick   Status err;
1985061da546Spatrick   FileSpec repl_executable;
1986061da546Spatrick 
1987*f6aab3d8Srobert   if (language == eLanguageTypeUnknown)
1988*f6aab3d8Srobert     language = GetREPLLanguage();
1989*f6aab3d8Srobert 
1990061da546Spatrick   if (language == eLanguageTypeUnknown) {
1991061da546Spatrick     LanguageSet repl_languages = Language::GetLanguagesSupportingREPLs();
1992061da546Spatrick 
1993061da546Spatrick     if (auto single_lang = repl_languages.GetSingularLanguage()) {
1994061da546Spatrick       language = *single_lang;
1995061da546Spatrick     } else if (repl_languages.Empty()) {
1996*f6aab3d8Srobert       err.SetErrorString(
1997061da546Spatrick           "LLDB isn't configured with REPL support for any languages.");
1998061da546Spatrick       return err;
1999061da546Spatrick     } else {
2000*f6aab3d8Srobert       err.SetErrorString(
2001061da546Spatrick           "Multiple possible REPL languages.  Please specify a language.");
2002061da546Spatrick       return err;
2003061da546Spatrick     }
2004061da546Spatrick   }
2005061da546Spatrick 
2006061da546Spatrick   Target *const target =
2007061da546Spatrick       nullptr; // passing in an empty target means the REPL must create one
2008061da546Spatrick 
2009061da546Spatrick   REPLSP repl_sp(REPL::Create(err, language, this, target, repl_options));
2010061da546Spatrick 
2011061da546Spatrick   if (!err.Success()) {
2012061da546Spatrick     return err;
2013061da546Spatrick   }
2014061da546Spatrick 
2015061da546Spatrick   if (!repl_sp) {
2016061da546Spatrick     err.SetErrorStringWithFormat("couldn't find a REPL for %s",
2017061da546Spatrick                                  Language::GetNameForLanguageType(language));
2018061da546Spatrick     return err;
2019061da546Spatrick   }
2020061da546Spatrick 
2021061da546Spatrick   repl_sp->SetCompilerOptions(repl_options);
2022061da546Spatrick   repl_sp->RunLoop();
2023061da546Spatrick 
2024061da546Spatrick   return err;
2025061da546Spatrick }
2026*f6aab3d8Srobert 
GetThreadPool()2027*f6aab3d8Srobert llvm::ThreadPool &Debugger::GetThreadPool() {
2028*f6aab3d8Srobert   assert(g_thread_pool &&
2029*f6aab3d8Srobert          "Debugger::GetThreadPool called before Debugger::Initialize");
2030*f6aab3d8Srobert   return *g_thread_pool;
2031*f6aab3d8Srobert }
2032