180814287SRaphael Isemann //===-- Debugger.cpp ------------------------------------------------------===//
230fdc8d8SChris Lattner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
630fdc8d8SChris Lattner //
730fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
830fdc8d8SChris Lattner 
94a33d318SGreg Clayton #include "lldb/Core/Debugger.h"
104a33d318SGreg Clayton 
11672d2c12SJonas Devlieghere #include "lldb/Breakpoint/Breakpoint.h"
125e65e79bSJonas Devlieghere #include "lldb/Core/DebuggerEvents.h"
13554f68d3SGreg Clayton #include "lldb/Core/FormatEntity.h"
14672d2c12SJonas Devlieghere #include "lldb/Core/Mangled.h"
15672d2c12SJonas Devlieghere #include "lldb/Core/ModuleList.h"
16e8cd0c98SGreg Clayton #include "lldb/Core/PluginManager.h"
175b52f0c7SJim Ingham #include "lldb/Core/StreamAsynchronousIO.h"
1844d93782SGreg Clayton #include "lldb/Core/StreamFile.h"
195548cb50SEnrico Granata #include "lldb/DataFormatters/DataVisualization.h"
203e7e915dSSean Callanan #include "lldb/Expression/REPL.h"
21672d2c12SJonas Devlieghere #include "lldb/Host/File.h"
2235e4c84cSJonas Devlieghere #include "lldb/Host/FileSystem.h"
2342ff0ad8SZachary Turner #include "lldb/Host/HostInfo.h"
24a3406614SGreg Clayton #include "lldb/Host/Terminal.h"
2539de3110SZachary Turner #include "lldb/Host/ThreadLauncher.h"
266611103cSGreg Clayton #include "lldb/Interpreter/CommandInterpreter.h"
27d6b64612SMed Ismail Bennani #include "lldb/Interpreter/CommandReturnObject.h"
28672d2c12SJonas Devlieghere #include "lldb/Interpreter/OptionValue.h"
2946a28a95SJonas Devlieghere #include "lldb/Interpreter/OptionValueLanguage.h"
30633a29cfSZachary Turner #include "lldb/Interpreter/OptionValueProperties.h"
3167cc0636SGreg Clayton #include "lldb/Interpreter/OptionValueSInt64.h"
3267cc0636SGreg Clayton #include "lldb/Interpreter/OptionValueString.h"
33672d2c12SJonas Devlieghere #include "lldb/Interpreter/Property.h"
34672d2c12SJonas Devlieghere #include "lldb/Interpreter/ScriptInterpreter.h"
351f746071SGreg Clayton #include "lldb/Symbol/Function.h"
361f746071SGreg Clayton #include "lldb/Symbol/Symbol.h"
37672d2c12SJonas Devlieghere #include "lldb/Symbol/SymbolContext.h"
383e7e915dSSean Callanan #include "lldb/Target/Language.h"
3930fdc8d8SChris Lattner #include "lldb/Target/Process.h"
4075930019STodd Fiala #include "lldb/Target/StructuredDataPlugin.h"
4184a53dfbSEnrico Granata #include "lldb/Target/Target.h"
42b9c1b51eSKate Stone #include "lldb/Target/TargetList.h"
4330fdc8d8SChris Lattner #include "lldb/Target/Thread.h"
44672d2c12SJonas Devlieghere #include "lldb/Target/ThreadList.h"
455a31471eSGreg Clayton #include "lldb/Utility/AnsiTerminal.h"
46181b823bSPavel Labath #include "lldb/Utility/Event.h"
47c34698a8SPavel Labath #include "lldb/Utility/LLDBLog.h"
48181b823bSPavel Labath #include "lldb/Utility/Listener.h"
49672d2c12SJonas Devlieghere #include "lldb/Utility/Log.h"
509e046f02SJonas Devlieghere #include "lldb/Utility/Reproducer.h"
51f23b829aSLevon Ter-Grigoryan #include "lldb/Utility/ReproducerProvider.h"
52d821c997SPavel Labath #include "lldb/Utility/State.h"
53672d2c12SJonas Devlieghere #include "lldb/Utility/Stream.h"
54fb1a0a0dSZachary Turner #include "lldb/Utility/StreamCallback.h"
55bf9a7730SZachary Turner #include "lldb/Utility/StreamString.h"
562f3df613SZachary Turner 
57b1cb0b79SNico Weber #if defined(_WIN32)
58672d2c12SJonas Devlieghere #include "lldb/Host/windows/PosixApi.h"
598aa23614SDavid Bolvansky #include "lldb/Host/windows/windows.h"
602f3df613SZachary Turner #endif
612f3df613SZachary Turner 
62672d2c12SJonas Devlieghere #include "llvm/ADT/None.h"
63672d2c12SJonas Devlieghere #include "llvm/ADT/STLExtras.h"
642f3df613SZachary Turner #include "llvm/ADT/StringRef.h"
65672d2c12SJonas Devlieghere #include "llvm/ADT/iterator.h"
662f3df613SZachary Turner #include "llvm/Support/DynamicLibrary.h"
672f3df613SZachary Turner #include "llvm/Support/FileSystem.h"
688aa23614SDavid Bolvansky #include "llvm/Support/Process.h"
692f3df613SZachary Turner #include "llvm/Support/Threading.h"
70672d2c12SJonas Devlieghere #include "llvm/Support/raw_ostream.h"
712f3df613SZachary Turner 
7276e47d48SRaphael Isemann #include <cstdio>
7376e47d48SRaphael Isemann #include <cstdlib>
7476e47d48SRaphael Isemann #include <cstring>
75672d2c12SJonas Devlieghere #include <list>
76672d2c12SJonas Devlieghere #include <memory>
772f3df613SZachary Turner #include <mutex>
78672d2c12SJonas Devlieghere #include <set>
79672d2c12SJonas Devlieghere #include <string>
80672d2c12SJonas Devlieghere #include <system_error>
812f3df613SZachary Turner 
82f23b829aSLevon Ter-Grigoryan // Includes for pipe()
83f23b829aSLevon Ter-Grigoryan #if defined(_WIN32)
84f23b829aSLevon Ter-Grigoryan #include <fcntl.h>
85f23b829aSLevon Ter-Grigoryan #include <io.h>
86f23b829aSLevon Ter-Grigoryan #else
87f23b829aSLevon Ter-Grigoryan #include <unistd.h>
88f23b829aSLevon Ter-Grigoryan #endif
89f23b829aSLevon Ter-Grigoryan 
902f3df613SZachary Turner namespace lldb_private {
912f3df613SZachary Turner class Address;
922f3df613SZachary Turner }
9330fdc8d8SChris Lattner 
9430fdc8d8SChris Lattner using namespace lldb;
9530fdc8d8SChris Lattner using namespace lldb_private;
9630fdc8d8SChris Lattner 
97ebc1bb27SCaroline Tice static lldb::user_id_t g_unique_id = 1;
987c2896a2SZachary Turner static size_t g_debugger_event_thread_stack_bytes = 8 * 1024 * 1024;
99ebc1bb27SCaroline Tice 
1001b654882SGreg Clayton #pragma mark Static Functions
1011b654882SGreg Clayton 
1021b654882SGreg Clayton typedef std::vector<DebuggerSP> DebuggerList;
103b9c1b51eSKate Stone static std::recursive_mutex *g_debugger_list_mutex_ptr =
104b9c1b51eSKate Stone     nullptr; // NOTE: intentional leak to avoid issues with C++ destructor chain
105b9c1b51eSKate Stone static DebuggerList *g_debugger_list_ptr =
106b9c1b51eSKate Stone     nullptr; // NOTE: intentional leak to avoid issues with C++ destructor chain
107e372b98dSGreg Clayton 
1088fe53c49STatyana Krasnukha static constexpr OptionEnumValueElement g_show_disassembly_enum_values[] = {
109e063ecccSJonas Devlieghere     {
110e063ecccSJonas Devlieghere         Debugger::eStopDisassemblyTypeNever,
111e063ecccSJonas Devlieghere         "never",
112e063ecccSJonas Devlieghere         "Never show disassembly when displaying a stop context.",
113e063ecccSJonas Devlieghere     },
114e063ecccSJonas Devlieghere     {
115e063ecccSJonas Devlieghere         Debugger::eStopDisassemblyTypeNoDebugInfo,
116e063ecccSJonas Devlieghere         "no-debuginfo",
117e063ecccSJonas Devlieghere         "Show disassembly when there is no debug information.",
118e063ecccSJonas Devlieghere     },
119e063ecccSJonas Devlieghere     {
120e063ecccSJonas Devlieghere         Debugger::eStopDisassemblyTypeNoSource,
121e063ecccSJonas Devlieghere         "no-source",
122e063ecccSJonas Devlieghere         "Show disassembly when there is no source information, or the source "
123e063ecccSJonas Devlieghere         "file "
124e063ecccSJonas Devlieghere         "is missing when displaying a stop context.",
125e063ecccSJonas Devlieghere     },
126e063ecccSJonas Devlieghere     {
127e063ecccSJonas Devlieghere         Debugger::eStopDisassemblyTypeAlways,
128e063ecccSJonas Devlieghere         "always",
129e063ecccSJonas Devlieghere         "Always show disassembly when displaying a stop context.",
130e063ecccSJonas Devlieghere     },
131e063ecccSJonas Devlieghere };
132e372b98dSGreg Clayton 
1338fe53c49STatyana Krasnukha static constexpr OptionEnumValueElement g_language_enumerators[] = {
134e063ecccSJonas Devlieghere     {
135e063ecccSJonas Devlieghere         eScriptLanguageNone,
136e063ecccSJonas Devlieghere         "none",
137e063ecccSJonas Devlieghere         "Disable scripting languages.",
138e063ecccSJonas Devlieghere     },
139e063ecccSJonas Devlieghere     {
140e063ecccSJonas Devlieghere         eScriptLanguagePython,
141e063ecccSJonas Devlieghere         "python",
142e063ecccSJonas Devlieghere         "Select python as the default scripting language.",
143e063ecccSJonas Devlieghere     },
144e063ecccSJonas Devlieghere     {
145e063ecccSJonas Devlieghere         eScriptLanguageDefault,
146e063ecccSJonas Devlieghere         "default",
147e063ecccSJonas Devlieghere         "Select the lldb default as the default scripting language.",
148e063ecccSJonas Devlieghere     },
149e063ecccSJonas Devlieghere };
150e372b98dSGreg Clayton 
1518fe53c49STatyana Krasnukha static constexpr OptionEnumValueElement s_stop_show_column_values[] = {
152e063ecccSJonas Devlieghere     {
153e063ecccSJonas Devlieghere         eStopShowColumnAnsiOrCaret,
154e063ecccSJonas Devlieghere         "ansi-or-caret",
155e063ecccSJonas Devlieghere         "Highlight the stop column with ANSI terminal codes when color/ANSI "
156e063ecccSJonas Devlieghere         "mode is enabled; otherwise, fall back to using a text-only caret (^) "
157e063ecccSJonas Devlieghere         "as if \"caret-only\" mode was selected.",
158e063ecccSJonas Devlieghere     },
159e063ecccSJonas Devlieghere     {
160e063ecccSJonas Devlieghere         eStopShowColumnAnsi,
161e063ecccSJonas Devlieghere         "ansi",
162e063ecccSJonas Devlieghere         "Highlight the stop column with ANSI terminal codes when running LLDB "
163e063ecccSJonas Devlieghere         "with color/ANSI enabled.",
164e063ecccSJonas Devlieghere     },
165e063ecccSJonas Devlieghere     {
166e063ecccSJonas Devlieghere         eStopShowColumnCaret,
167e063ecccSJonas Devlieghere         "caret",
168e063ecccSJonas Devlieghere         "Highlight the stop column with a caret character (^) underneath the "
169e063ecccSJonas Devlieghere         "stop column. This method introduces a new line in source listings "
170e063ecccSJonas Devlieghere         "that display thread stop locations.",
171e063ecccSJonas Devlieghere     },
172e063ecccSJonas Devlieghere     {
173e063ecccSJonas Devlieghere         eStopShowColumnNone,
174e063ecccSJonas Devlieghere         "none",
175e063ecccSJonas Devlieghere         "Do not highlight the stop column.",
176e063ecccSJonas Devlieghere     },
177e063ecccSJonas Devlieghere };
1789666ba75STodd Fiala 
179971f9ca6SJonas Devlieghere #define LLDB_PROPERTIES_debugger
1806a253d37SJordan Rupprecht #include "CoreProperties.inc"
18167cc0636SGreg Clayton 
182b9c1b51eSKate Stone enum {
183971f9ca6SJonas Devlieghere #define LLDB_PROPERTIES_debugger
1846a253d37SJordan Rupprecht #include "CorePropertiesEnum.inc"
18567cc0636SGreg Clayton };
18667cc0636SGreg Clayton 
187df370550SEugene Zelenko LoadPluginCallbackType Debugger::g_load_plugin_callback = nullptr;
1884c05410fSGreg Clayton 
18997206d57SZachary Turner Status Debugger::SetPropertyValue(const ExecutionContext *exe_ctx,
1904c05410fSGreg Clayton                                   VarSetOperationType op,
19197206d57SZachary Turner                                   llvm::StringRef property_path,
19297206d57SZachary Turner                                   llvm::StringRef value) {
193e063ecccSJonas Devlieghere   bool is_load_script =
194e063ecccSJonas Devlieghere       (property_path == "target.load-script-from-symbol-file");
195e5814d78SRaphael Isemann   // These properties might change how we visualize data.
196e5814d78SRaphael Isemann   bool invalidate_data_vis = (property_path == "escape-non-printables");
197e5814d78SRaphael Isemann   invalidate_data_vis |=
198e5814d78SRaphael Isemann       (property_path == "target.max-zero-padding-in-float-format");
199e5814d78SRaphael Isemann   if (invalidate_data_vis) {
200e5814d78SRaphael Isemann     DataVisualization::ForceUpdate();
201e5814d78SRaphael Isemann   }
202e5814d78SRaphael Isemann 
20384a53dfbSEnrico Granata   TargetSP target_sp;
204397ddd5fSEnrico Granata   LoadScriptFromSymFile load_script_old_value;
205b9c1b51eSKate Stone   if (is_load_script && exe_ctx->GetTargetSP()) {
20684a53dfbSEnrico Granata     target_sp = exe_ctx->GetTargetSP();
207b9c1b51eSKate Stone     load_script_old_value =
208b9c1b51eSKate Stone         target_sp->TargetProperties::GetLoadScriptFromSymbolFile();
20984a53dfbSEnrico Granata   }
21097206d57SZachary Turner   Status error(Properties::SetPropertyValue(exe_ctx, op, property_path, value));
211b9c1b51eSKate Stone   if (error.Success()) {
21284a53dfbSEnrico Granata     // FIXME it would be nice to have "on-change" callbacks for properties
213a8ea5955SJonas Devlieghere     if (property_path == g_debugger_properties[ePropertyPrompt].name) {
214514d8cd8SZachary Turner       llvm::StringRef new_prompt = GetPrompt();
2154b3c0fd5SJonas Devlieghere       std::string str = lldb_private::ansi::FormatAnsiTerminalCodes(
216b9c1b51eSKate Stone           new_prompt, GetUseColor());
217c3ce7f27SMichael Sartain       if (str.length())
218771ef6d4SMalcolm Parsons         new_prompt = str;
21944d93782SGreg Clayton       GetCommandInterpreter().UpdatePrompt(new_prompt);
220a8f3ae7cSJonas Devlieghere       auto bytes = std::make_unique<EventDataBytes>(new_prompt);
2212f3df613SZachary Turner       auto prompt_change_event_sp = std::make_shared<Event>(
2222f3df613SZachary Turner           CommandInterpreter::eBroadcastBitResetPrompt, bytes.release());
2234c05410fSGreg Clayton       GetCommandInterpreter().BroadcastEvent(prompt_change_event_sp);
224a8ea5955SJonas Devlieghere     } else if (property_path == g_debugger_properties[ePropertyUseColor].name) {
225b9c1b51eSKate Stone       // use-color changed. Ping the prompt so it can reset the ansi terminal
226b9c1b51eSKate Stone       // codes.
227c3ce7f27SMichael Sartain       SetPrompt(GetPrompt());
228acae69d0SEmre Kultursay     } else if (property_path == g_debugger_properties[ePropertyUseSourceCache].name) {
229acae69d0SEmre Kultursay       // use-source-cache changed. Wipe out the cache contents if it was disabled.
230acae69d0SEmre Kultursay       if (!GetUseSourceCache()) {
231acae69d0SEmre Kultursay         m_source_file_cache.Clear();
232acae69d0SEmre Kultursay       }
233b9c1b51eSKate Stone     } else if (is_load_script && target_sp &&
234b9c1b51eSKate Stone                load_script_old_value == eLoadScriptFromSymFileWarn) {
235b9c1b51eSKate Stone       if (target_sp->TargetProperties::GetLoadScriptFromSymbolFile() ==
236b9c1b51eSKate Stone           eLoadScriptFromSymFileTrue) {
23797206d57SZachary Turner         std::list<Status> errors;
2389730339bSEnrico Granata         StreamString feedback_stream;
239b9c1b51eSKate Stone         if (!target_sp->LoadScriptingResources(errors, &feedback_stream)) {
2407ca15ba7SLawrence D'Anna           Stream &s = GetErrorStream();
241b9c1b51eSKate Stone           for (auto error : errors) {
2427ca15ba7SLawrence D'Anna             s.Printf("%s\n", error.AsCString());
24384a53dfbSEnrico Granata           }
2449730339bSEnrico Granata           if (feedback_stream.GetSize())
2457ca15ba7SLawrence D'Anna             s.PutCString(feedback_stream.GetString());
24684a53dfbSEnrico Granata         }
24784a53dfbSEnrico Granata       }
248ebdc1ac0SEnrico Granata     }
2494c05410fSGreg Clayton   }
2504c05410fSGreg Clayton   return error;
2514c05410fSGreg Clayton }
2524c05410fSGreg Clayton 
253b9c1b51eSKate Stone bool Debugger::GetAutoConfirm() const {
25467cc0636SGreg Clayton   const uint32_t idx = ePropertyAutoConfirm;
255b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsBoolean(
256a8ea5955SJonas Devlieghere       nullptr, idx, g_debugger_properties[idx].default_uint_value != 0);
25767cc0636SGreg Clayton }
25867cc0636SGreg Clayton 
259b9c1b51eSKate Stone const FormatEntity::Entry *Debugger::GetDisassemblyFormat() const {
260aff1b357SJason Molenda   const uint32_t idx = ePropertyDisassemblyFormat;
261df370550SEugene Zelenko   return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
262aff1b357SJason Molenda }
263aff1b357SJason Molenda 
264b9c1b51eSKate Stone const FormatEntity::Entry *Debugger::GetFrameFormat() const {
26567cc0636SGreg Clayton   const uint32_t idx = ePropertyFrameFormat;
266df370550SEugene Zelenko   return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
26767cc0636SGreg Clayton }
26867cc0636SGreg Clayton 
2697f1c1211SPavel Labath const FormatEntity::Entry *Debugger::GetFrameFormatUnique() const {
2707f1c1211SPavel Labath   const uint32_t idx = ePropertyFrameFormatUnique;
2717f1c1211SPavel Labath   return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
2727f1c1211SPavel Labath }
2737f1c1211SPavel Labath 
274b889ef42SMed Ismail Bennani uint32_t Debugger::GetStopDisassemblyMaxSize() const {
275b889ef42SMed Ismail Bennani   const uint32_t idx = ePropertyStopDisassemblyMaxSize;
276b889ef42SMed Ismail Bennani   return m_collection_sp->GetPropertyAtIndexAsUInt64(
277b889ef42SMed Ismail Bennani       nullptr, idx, g_debugger_properties[idx].default_uint_value);
278b889ef42SMed Ismail Bennani }
279b889ef42SMed Ismail Bennani 
280b9c1b51eSKate Stone bool Debugger::GetNotifyVoid() const {
28167cc0636SGreg Clayton   const uint32_t idx = ePropertyNotiftVoid;
282b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsBoolean(
283a8ea5955SJonas Devlieghere       nullptr, idx, g_debugger_properties[idx].default_uint_value != 0);
28467cc0636SGreg Clayton }
28567cc0636SGreg Clayton 
286514d8cd8SZachary Turner llvm::StringRef Debugger::GetPrompt() const {
28767cc0636SGreg Clayton   const uint32_t idx = ePropertyPrompt;
288b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsString(
289a8ea5955SJonas Devlieghere       nullptr, idx, g_debugger_properties[idx].default_cstr_value);
29067cc0636SGreg Clayton }
29167cc0636SGreg Clayton 
292514d8cd8SZachary Turner void Debugger::SetPrompt(llvm::StringRef p) {
29367cc0636SGreg Clayton   const uint32_t idx = ePropertyPrompt;
294df370550SEugene Zelenko   m_collection_sp->SetPropertyAtIndexAsString(nullptr, idx, p);
295514d8cd8SZachary Turner   llvm::StringRef new_prompt = GetPrompt();
296b9c1b51eSKate Stone   std::string str =
2974b3c0fd5SJonas Devlieghere       lldb_private::ansi::FormatAnsiTerminalCodes(new_prompt, GetUseColor());
298c3ce7f27SMichael Sartain   if (str.length())
299771ef6d4SMalcolm Parsons     new_prompt = str;
30044d93782SGreg Clayton   GetCommandInterpreter().UpdatePrompt(new_prompt);
30167cc0636SGreg Clayton }
30267cc0636SGreg Clayton 
3039e046f02SJonas Devlieghere llvm::StringRef Debugger::GetReproducerPath() const {
3049e046f02SJonas Devlieghere   auto &r = repro::Reproducer::Instance();
3059e046f02SJonas Devlieghere   return r.GetReproducerPath().GetCString();
3069e046f02SJonas Devlieghere }
3079e046f02SJonas Devlieghere 
308b9c1b51eSKate Stone const FormatEntity::Entry *Debugger::GetThreadFormat() const {
30967cc0636SGreg Clayton   const uint32_t idx = ePropertyThreadFormat;
310df370550SEugene Zelenko   return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
31167cc0636SGreg Clayton }
31267cc0636SGreg Clayton 
3136a9767c7SJim Ingham const FormatEntity::Entry *Debugger::GetThreadStopFormat() const {
3146a9767c7SJim Ingham   const uint32_t idx = ePropertyThreadStopFormat;
3156a9767c7SJim Ingham   return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
3166a9767c7SJim Ingham }
3176a9767c7SJim Ingham 
318b9c1b51eSKate Stone lldb::ScriptLanguage Debugger::GetScriptLanguage() const {
31967cc0636SGreg Clayton   const uint32_t idx = ePropertyScriptLanguage;
320b9c1b51eSKate Stone   return (lldb::ScriptLanguage)m_collection_sp->GetPropertyAtIndexAsEnumeration(
321a8ea5955SJonas Devlieghere       nullptr, idx, g_debugger_properties[idx].default_uint_value);
32267cc0636SGreg Clayton }
32367cc0636SGreg Clayton 
324b9c1b51eSKate Stone bool Debugger::SetScriptLanguage(lldb::ScriptLanguage script_lang) {
32567cc0636SGreg Clayton   const uint32_t idx = ePropertyScriptLanguage;
326b9c1b51eSKate Stone   return m_collection_sp->SetPropertyAtIndexAsEnumeration(nullptr, idx,
327b9c1b51eSKate Stone                                                           script_lang);
32867cc0636SGreg Clayton }
32967cc0636SGreg Clayton 
33046a28a95SJonas Devlieghere lldb::LanguageType Debugger::GetREPLLanguage() const {
33146a28a95SJonas Devlieghere   const uint32_t idx = ePropertyREPLLanguage;
33246a28a95SJonas Devlieghere   OptionValueLanguage *value =
33346a28a95SJonas Devlieghere       m_collection_sp->GetPropertyAtIndexAsOptionValueLanguage(nullptr, idx);
33446a28a95SJonas Devlieghere   if (value)
33546a28a95SJonas Devlieghere     return value->GetCurrentValue();
33646a28a95SJonas Devlieghere   return LanguageType();
33746a28a95SJonas Devlieghere }
33846a28a95SJonas Devlieghere 
33946a28a95SJonas Devlieghere bool Debugger::SetREPLLanguage(lldb::LanguageType repl_lang) {
34046a28a95SJonas Devlieghere   const uint32_t idx = ePropertyREPLLanguage;
34146a28a95SJonas Devlieghere   return m_collection_sp->SetPropertyAtIndexAsLanguage(nullptr, idx, repl_lang);
34246a28a95SJonas Devlieghere }
34346a28a95SJonas Devlieghere 
344b9c1b51eSKate Stone uint32_t Debugger::GetTerminalWidth() const {
34567cc0636SGreg Clayton   const uint32_t idx = ePropertyTerminalWidth;
346b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsSInt64(
347a8ea5955SJonas Devlieghere       nullptr, idx, g_debugger_properties[idx].default_uint_value);
34867cc0636SGreg Clayton }
34967cc0636SGreg Clayton 
350b9c1b51eSKate Stone bool Debugger::SetTerminalWidth(uint32_t term_width) {
351d9166ad2SFred Riss   if (auto handler_sp = m_io_handler_stack.Top())
352d9166ad2SFred Riss     handler_sp->TerminalSizeChanged();
353d9166ad2SFred Riss 
35467cc0636SGreg Clayton   const uint32_t idx = ePropertyTerminalWidth;
355df370550SEugene Zelenko   return m_collection_sp->SetPropertyAtIndexAsSInt64(nullptr, idx, term_width);
35667cc0636SGreg Clayton }
35767cc0636SGreg Clayton 
358b9c1b51eSKate Stone bool Debugger::GetUseExternalEditor() const {
35967cc0636SGreg Clayton   const uint32_t idx = ePropertyUseExternalEditor;
360b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsBoolean(
361a8ea5955SJonas Devlieghere       nullptr, idx, g_debugger_properties[idx].default_uint_value != 0);
36267cc0636SGreg Clayton }
36367cc0636SGreg Clayton 
364b9c1b51eSKate Stone bool Debugger::SetUseExternalEditor(bool b) {
36567cc0636SGreg Clayton   const uint32_t idx = ePropertyUseExternalEditor;
366df370550SEugene Zelenko   return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
36767cc0636SGreg Clayton }
36867cc0636SGreg Clayton 
369b9c1b51eSKate Stone bool Debugger::GetUseColor() const {
370c3ce7f27SMichael Sartain   const uint32_t idx = ePropertyUseColor;
371b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsBoolean(
372a8ea5955SJonas Devlieghere       nullptr, idx, g_debugger_properties[idx].default_uint_value != 0);
373c3ce7f27SMichael Sartain }
374c3ce7f27SMichael Sartain 
375b9c1b51eSKate Stone bool Debugger::SetUseColor(bool b) {
376c3ce7f27SMichael Sartain   const uint32_t idx = ePropertyUseColor;
377df370550SEugene Zelenko   bool ret = m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
378c3ce7f27SMichael Sartain   SetPrompt(GetPrompt());
379c3ce7f27SMichael Sartain   return ret;
380c3ce7f27SMichael Sartain }
381c3ce7f27SMichael Sartain 
3825a27b998SJonas Devlieghere bool Debugger::GetShowProgress() const {
3835a27b998SJonas Devlieghere   const uint32_t idx = ePropertyShowProgress;
3845a27b998SJonas Devlieghere   return m_collection_sp->GetPropertyAtIndexAsBoolean(
3855a27b998SJonas Devlieghere       nullptr, idx, g_debugger_properties[idx].default_uint_value != 0);
3865a27b998SJonas Devlieghere }
3875a27b998SJonas Devlieghere 
388097d46f4SJonas Devlieghere llvm::StringRef Debugger::GetShowProgressAnsiPrefix() const {
389097d46f4SJonas Devlieghere   const uint32_t idx = ePropertyShowProgressAnsiPrefix;
390097d46f4SJonas Devlieghere   return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, "");
391097d46f4SJonas Devlieghere }
392097d46f4SJonas Devlieghere 
393097d46f4SJonas Devlieghere llvm::StringRef Debugger::GetShowProgressAnsiSuffix() const {
394097d46f4SJonas Devlieghere   const uint32_t idx = ePropertyShowProgressAnsiSuffix;
395097d46f4SJonas Devlieghere   return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, "");
396097d46f4SJonas Devlieghere }
397097d46f4SJonas Devlieghere 
398de9e8502SShu Anzai bool Debugger::GetUseAutosuggestion() const {
399de9e8502SShu Anzai   const uint32_t idx = ePropertyShowAutosuggestion;
400de9e8502SShu Anzai   return m_collection_sp->GetPropertyAtIndexAsBoolean(
401de9e8502SShu Anzai       nullptr, idx, g_debugger_properties[idx].default_uint_value != 0);
402de9e8502SShu Anzai }
403de9e8502SShu Anzai 
404080635efSJonas Devlieghere llvm::StringRef Debugger::GetAutosuggestionAnsiPrefix() const {
405080635efSJonas Devlieghere   const uint32_t idx = ePropertyShowAutosuggestionAnsiPrefix;
406080635efSJonas Devlieghere   return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, "");
407080635efSJonas Devlieghere }
408080635efSJonas Devlieghere 
409080635efSJonas Devlieghere llvm::StringRef Debugger::GetAutosuggestionAnsiSuffix() const {
410080635efSJonas Devlieghere   const uint32_t idx = ePropertyShowAutosuggestionAnsiSuffix;
411080635efSJonas Devlieghere   return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, "");
412080635efSJonas Devlieghere }
413080635efSJonas Devlieghere 
414acae69d0SEmre Kultursay bool Debugger::GetUseSourceCache() const {
415acae69d0SEmre Kultursay   const uint32_t idx = ePropertyUseSourceCache;
416acae69d0SEmre Kultursay   return m_collection_sp->GetPropertyAtIndexAsBoolean(
417acae69d0SEmre Kultursay       nullptr, idx, g_debugger_properties[idx].default_uint_value != 0);
418acae69d0SEmre Kultursay }
419acae69d0SEmre Kultursay 
420acae69d0SEmre Kultursay bool Debugger::SetUseSourceCache(bool b) {
421acae69d0SEmre Kultursay   const uint32_t idx = ePropertyUseSourceCache;
422acae69d0SEmre Kultursay   bool ret = m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
423acae69d0SEmre Kultursay   if (!ret) {
424acae69d0SEmre Kultursay     m_source_file_cache.Clear();
425acae69d0SEmre Kultursay   }
426acae69d0SEmre Kultursay   return ret;
427acae69d0SEmre Kultursay }
428566afa0aSRaphael Isemann bool Debugger::GetHighlightSource() const {
429566afa0aSRaphael Isemann   const uint32_t idx = ePropertyHighlightSource;
430566afa0aSRaphael Isemann   return m_collection_sp->GetPropertyAtIndexAsBoolean(
431a8ea5955SJonas Devlieghere       nullptr, idx, g_debugger_properties[idx].default_uint_value);
432566afa0aSRaphael Isemann }
433566afa0aSRaphael Isemann 
4349666ba75STodd Fiala StopShowColumn Debugger::GetStopShowColumn() const {
4359666ba75STodd Fiala   const uint32_t idx = ePropertyStopShowColumn;
4369666ba75STodd Fiala   return (lldb::StopShowColumn)m_collection_sp->GetPropertyAtIndexAsEnumeration(
437a8ea5955SJonas Devlieghere       nullptr, idx, g_debugger_properties[idx].default_uint_value);
4389666ba75STodd Fiala }
4399666ba75STodd Fiala 
44020786326SRaphael Isemann llvm::StringRef Debugger::GetStopShowColumnAnsiPrefix() const {
4419666ba75STodd Fiala   const uint32_t idx = ePropertyStopShowColumnAnsiPrefix;
44220786326SRaphael Isemann   return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, "");
4439666ba75STodd Fiala }
4449666ba75STodd Fiala 
44520786326SRaphael Isemann llvm::StringRef Debugger::GetStopShowColumnAnsiSuffix() const {
4469666ba75STodd Fiala   const uint32_t idx = ePropertyStopShowColumnAnsiSuffix;
44720786326SRaphael Isemann   return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, "");
4489666ba75STodd Fiala }
4499666ba75STodd Fiala 
450841be985SJonas Devlieghere llvm::StringRef Debugger::GetStopShowLineMarkerAnsiPrefix() const {
451841be985SJonas Devlieghere   const uint32_t idx = ePropertyStopShowLineMarkerAnsiPrefix;
452841be985SJonas Devlieghere   return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, "");
453841be985SJonas Devlieghere }
454841be985SJonas Devlieghere 
455841be985SJonas Devlieghere llvm::StringRef Debugger::GetStopShowLineMarkerAnsiSuffix() const {
456841be985SJonas Devlieghere   const uint32_t idx = ePropertyStopShowLineMarkerAnsiSuffix;
457841be985SJonas Devlieghere   return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, "");
458841be985SJonas Devlieghere }
459841be985SJonas Devlieghere 
460b9c1b51eSKate Stone uint32_t Debugger::GetStopSourceLineCount(bool before) const {
461b9c1b51eSKate Stone   const uint32_t idx =
462b9c1b51eSKate Stone       before ? ePropertyStopLineCountBefore : ePropertyStopLineCountAfter;
463b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsSInt64(
464a8ea5955SJonas Devlieghere       nullptr, idx, g_debugger_properties[idx].default_uint_value);
46567cc0636SGreg Clayton }
46667cc0636SGreg Clayton 
467b9c1b51eSKate Stone Debugger::StopDisassemblyType Debugger::GetStopDisassemblyDisplay() const {
46867cc0636SGreg Clayton   const uint32_t idx = ePropertyStopDisassemblyDisplay;
469b9c1b51eSKate Stone   return (Debugger::StopDisassemblyType)
470b9c1b51eSKate Stone       m_collection_sp->GetPropertyAtIndexAsEnumeration(
471a8ea5955SJonas Devlieghere           nullptr, idx, g_debugger_properties[idx].default_uint_value);
47267cc0636SGreg Clayton }
47367cc0636SGreg Clayton 
474b9c1b51eSKate Stone uint32_t Debugger::GetDisassemblyLineCount() const {
47567cc0636SGreg Clayton   const uint32_t idx = ePropertyStopDisassemblyCount;
476b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsSInt64(
477a8ea5955SJonas Devlieghere       nullptr, idx, g_debugger_properties[idx].default_uint_value);
47867cc0636SGreg Clayton }
479e372b98dSGreg Clayton 
480b9c1b51eSKate Stone bool Debugger::GetAutoOneLineSummaries() const {
48190a8db30SEnrico Granata   const uint32_t idx = ePropertyAutoOneLineSummaries;
482df370550SEugene Zelenko   return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true);
483ebdc1ac0SEnrico Granata }
484553fad5cSEnrico Granata 
485b9c1b51eSKate Stone bool Debugger::GetEscapeNonPrintables() const {
486ebdc1ac0SEnrico Granata   const uint32_t idx = ePropertyEscapeNonPrintables;
487df370550SEugene Zelenko   return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true);
488553fad5cSEnrico Granata }
489553fad5cSEnrico Granata 
490b9c1b51eSKate Stone bool Debugger::GetAutoIndent() const {
4916681041dSSean Callanan   const uint32_t idx = ePropertyAutoIndent;
492df370550SEugene Zelenko   return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true);
4936681041dSSean Callanan }
4946681041dSSean Callanan 
495b9c1b51eSKate Stone bool Debugger::SetAutoIndent(bool b) {
4966681041dSSean Callanan   const uint32_t idx = ePropertyAutoIndent;
497df370550SEugene Zelenko   return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
4986681041dSSean Callanan }
4996681041dSSean Callanan 
500b9c1b51eSKate Stone bool Debugger::GetPrintDecls() const {
5016681041dSSean Callanan   const uint32_t idx = ePropertyPrintDecls;
502df370550SEugene Zelenko   return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true);
5036681041dSSean Callanan }
5046681041dSSean Callanan 
505b9c1b51eSKate Stone bool Debugger::SetPrintDecls(bool b) {
5066681041dSSean Callanan   const uint32_t idx = ePropertyPrintDecls;
507df370550SEugene Zelenko   return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
5086681041dSSean Callanan }
5096681041dSSean Callanan 
510b9c1b51eSKate Stone uint32_t Debugger::GetTabSize() const {
5116681041dSSean Callanan   const uint32_t idx = ePropertyTabSize;
512b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsUInt64(
513a8ea5955SJonas Devlieghere       nullptr, idx, g_debugger_properties[idx].default_uint_value);
5146681041dSSean Callanan }
5156681041dSSean Callanan 
516b9c1b51eSKate Stone bool Debugger::SetTabSize(uint32_t tab_size) {
5176681041dSSean Callanan   const uint32_t idx = ePropertyTabSize;
518df370550SEugene Zelenko   return m_collection_sp->SetPropertyAtIndexAsUInt64(nullptr, idx, tab_size);
5196681041dSSean Callanan }
5206681041dSSean Callanan 
5211b654882SGreg Clayton #pragma mark Debugger
5221b654882SGreg Clayton 
52367cc0636SGreg Clayton // const DebuggerPropertiesSP &
52467cc0636SGreg Clayton // Debugger::GetSettings() const
52567cc0636SGreg Clayton //{
52667cc0636SGreg Clayton //    return m_properties_sp;
52767cc0636SGreg Clayton //}
52867cc0636SGreg Clayton //
52999d0faf2SGreg Clayton 
530b9c1b51eSKate Stone void Debugger::Initialize(LoadPluginCallbackType load_plugin_callback) {
531b9c1b51eSKate Stone   assert(g_debugger_list_ptr == nullptr &&
532b9c1b51eSKate Stone          "Debugger::Initialize called more than once!");
5336c42e063SGreg Clayton   g_debugger_list_mutex_ptr = new std::recursive_mutex();
5346c42e063SGreg Clayton   g_debugger_list_ptr = new DebuggerList();
5355fb8f797SGreg Clayton   g_load_plugin_callback = load_plugin_callback;
53699d0faf2SGreg Clayton }
53730fdc8d8SChris Lattner 
538b9c1b51eSKate Stone void Debugger::Terminate() {
539b9c1b51eSKate Stone   assert(g_debugger_list_ptr &&
540b9c1b51eSKate Stone          "Debugger::Terminate called without a matching Debugger::Initialize!");
541e6e2bb38SZachary Turner 
542b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
54395af9d88SQuinn Pham     // Clear our global list of debugger objects
5446c42e063SGreg Clayton     {
5456c42e063SGreg Clayton       std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
5466c42e063SGreg Clayton       for (const auto &debugger : *g_debugger_list_ptr)
547f3cd1819SOleksiy Vyalov         debugger->Clear();
5486c42e063SGreg Clayton       g_debugger_list_ptr->clear();
5496c42e063SGreg Clayton     }
5506c42e063SGreg Clayton   }
55130fdc8d8SChris Lattner }
55230fdc8d8SChris Lattner 
553b9c1b51eSKate Stone void Debugger::SettingsInitialize() { Target::SettingsInitialize(); }
55420bd37f7SCaroline Tice 
555b9c1b51eSKate Stone void Debugger::SettingsTerminate() { Target::SettingsTerminate(); }
55620bd37f7SCaroline Tice 
55797206d57SZachary Turner bool Debugger::LoadPlugin(const FileSpec &spec, Status &error) {
558b9c1b51eSKate Stone   if (g_load_plugin_callback) {
559b9c1b51eSKate Stone     llvm::sys::DynamicLibrary dynlib =
560b9c1b51eSKate Stone         g_load_plugin_callback(shared_from_this(), spec, error);
561b9c1b51eSKate Stone     if (dynlib.isValid()) {
56258a559c0SZachary Turner       m_loaded_plugins.push_back(dynlib);
56321dfcd9dSEnrico Granata       return true;
56421dfcd9dSEnrico Granata     }
565b9c1b51eSKate Stone   } else {
56605097246SAdrian Prantl     // The g_load_plugin_callback is registered in SBDebugger::Initialize() and
56705097246SAdrian Prantl     // if the public API layer isn't available (code is linking against all of
56805097246SAdrian Prantl     // the internal LLDB static libraries), then we can't load plugins
5695fb8f797SGreg Clayton     error.SetErrorString("Public API layer is not available");
5705fb8f797SGreg Clayton   }
57121dfcd9dSEnrico Granata   return false;
57221dfcd9dSEnrico Granata }
57321dfcd9dSEnrico Granata 
57435e4c84cSJonas Devlieghere static FileSystem::EnumerateDirectoryResult
5757d86ee5aSZachary Turner LoadPluginCallback(void *baton, llvm::sys::fs::file_type ft,
57635e4c84cSJonas Devlieghere                    llvm::StringRef path) {
57797206d57SZachary Turner   Status error;
57821dfcd9dSEnrico Granata 
579ad8d48f9SJonas Devlieghere   static ConstString g_dylibext(".dylib");
580ad8d48f9SJonas Devlieghere   static ConstString g_solibext(".so");
58121dfcd9dSEnrico Granata 
58221dfcd9dSEnrico Granata   if (!baton)
58335e4c84cSJonas Devlieghere     return FileSystem::eEnumerateDirectoryResultQuit;
58421dfcd9dSEnrico Granata 
58521dfcd9dSEnrico Granata   Debugger *debugger = (Debugger *)baton;
58621dfcd9dSEnrico Granata 
5877d86ee5aSZachary Turner   namespace fs = llvm::sys::fs;
58805097246SAdrian Prantl   // If we have a regular file, a symbolic link or unknown file type, try and
58905097246SAdrian Prantl   // process the file. We must handle unknown as sometimes the directory
59021dfcd9dSEnrico Granata   // enumeration might be enumerating a file system that doesn't have correct
59121dfcd9dSEnrico Granata   // file type information.
5927d86ee5aSZachary Turner   if (ft == fs::file_type::regular_file || ft == fs::file_type::symlink_file ||
5937d86ee5aSZachary Turner       ft == fs::file_type::type_unknown) {
5948f3be7a3SJonas Devlieghere     FileSpec plugin_file_spec(path);
5958f3be7a3SJonas Devlieghere     FileSystem::Instance().Resolve(plugin_file_spec);
59621dfcd9dSEnrico Granata 
5973cf443ddSMichael Sartain     if (plugin_file_spec.GetFileNameExtension() != g_dylibext &&
598b9c1b51eSKate Stone         plugin_file_spec.GetFileNameExtension() != g_solibext) {
59935e4c84cSJonas Devlieghere       return FileSystem::eEnumerateDirectoryResultNext;
6003cf443ddSMichael Sartain     }
60121dfcd9dSEnrico Granata 
60297206d57SZachary Turner     Status plugin_load_error;
603e743c782SEnrico Granata     debugger->LoadPlugin(plugin_file_spec, plugin_load_error);
60421dfcd9dSEnrico Granata 
60535e4c84cSJonas Devlieghere     return FileSystem::eEnumerateDirectoryResultNext;
6067d86ee5aSZachary Turner   } else if (ft == fs::file_type::directory_file ||
6077d86ee5aSZachary Turner              ft == fs::file_type::symlink_file ||
6087d86ee5aSZachary Turner              ft == fs::file_type::type_unknown) {
60905097246SAdrian Prantl     // Try and recurse into anything that a directory or symbolic link. We must
61005097246SAdrian Prantl     // also do this for unknown as sometimes the directory enumeration might be
61105097246SAdrian Prantl     // enumerating a file system that doesn't have correct file type
61221dfcd9dSEnrico Granata     // information.
61335e4c84cSJonas Devlieghere     return FileSystem::eEnumerateDirectoryResultEnter;
61421dfcd9dSEnrico Granata   }
61521dfcd9dSEnrico Granata 
61635e4c84cSJonas Devlieghere   return FileSystem::eEnumerateDirectoryResultNext;
61721dfcd9dSEnrico Granata }
61821dfcd9dSEnrico Granata 
619b9c1b51eSKate Stone void Debugger::InstanceInitialize() {
62021dfcd9dSEnrico Granata   const bool find_directories = true;
62121dfcd9dSEnrico Granata   const bool find_files = true;
62221dfcd9dSEnrico Granata   const bool find_other = true;
62321dfcd9dSEnrico Granata   char dir_path[PATH_MAX];
62460f028ffSPavel Labath   if (FileSpec dir_spec = HostInfo::GetSystemPluginDir()) {
625dbd7fabaSJonas Devlieghere     if (FileSystem::Instance().Exists(dir_spec) &&
626dbd7fabaSJonas Devlieghere         dir_spec.GetPath(dir_path, sizeof(dir_path))) {
62735e4c84cSJonas Devlieghere       FileSystem::Instance().EnumerateDirectory(dir_path, find_directories,
62835e4c84cSJonas Devlieghere                                                 find_files, find_other,
62935e4c84cSJonas Devlieghere                                                 LoadPluginCallback, this);
63021dfcd9dSEnrico Granata     }
63121dfcd9dSEnrico Granata   }
63221dfcd9dSEnrico Granata 
63360f028ffSPavel Labath   if (FileSpec dir_spec = HostInfo::GetUserPluginDir()) {
634dbd7fabaSJonas Devlieghere     if (FileSystem::Instance().Exists(dir_spec) &&
635dbd7fabaSJonas Devlieghere         dir_spec.GetPath(dir_path, sizeof(dir_path))) {
63635e4c84cSJonas Devlieghere       FileSystem::Instance().EnumerateDirectory(dir_path, find_directories,
63735e4c84cSJonas Devlieghere                                                 find_files, find_other,
63835e4c84cSJonas Devlieghere                                                 LoadPluginCallback, this);
63921dfcd9dSEnrico Granata     }
64021dfcd9dSEnrico Granata   }
641e8cd0c98SGreg Clayton 
642e8cd0c98SGreg Clayton   PluginManager::DebuggerInitialize(*this);
64321dfcd9dSEnrico Granata }
64421dfcd9dSEnrico Granata 
645b9c1b51eSKate Stone DebuggerSP Debugger::CreateInstance(lldb::LogOutputCallback log_callback,
646b9c1b51eSKate Stone                                     void *baton) {
647228063cdSJim Ingham   DebuggerSP debugger_sp(new Debugger(log_callback, baton));
648b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
6496c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
6506c42e063SGreg Clayton     g_debugger_list_ptr->push_back(debugger_sp);
6516611103cSGreg Clayton   }
65221dfcd9dSEnrico Granata   debugger_sp->InstanceInitialize();
6536611103cSGreg Clayton   return debugger_sp;
6546611103cSGreg Clayton }
6556611103cSGreg Clayton 
656b9c1b51eSKate Stone void Debugger::Destroy(DebuggerSP &debugger_sp) {
657df370550SEugene Zelenko   if (!debugger_sp)
658e02657b1SCaroline Tice     return;
659e02657b1SCaroline Tice 
660d6b64612SMed Ismail Bennani   CommandInterpreter &cmd_interpreter = debugger_sp->GetCommandInterpreter();
661d6b64612SMed Ismail Bennani 
662d6b64612SMed Ismail Bennani   if (cmd_interpreter.GetSaveSessionOnQuit()) {
663d6b64612SMed Ismail Bennani     CommandReturnObject result(debugger_sp->GetUseColor());
664d6b64612SMed Ismail Bennani     cmd_interpreter.SaveTranscript(result);
665d6b64612SMed Ismail Bennani     if (result.Succeeded())
666d6b64612SMed Ismail Bennani       debugger_sp->GetOutputStream() << result.GetOutputData() << '\n';
667d6b64612SMed Ismail Bennani     else
668d6b64612SMed Ismail Bennani       debugger_sp->GetErrorStream() << result.GetErrorData() << '\n';
669d6b64612SMed Ismail Bennani   }
670d6b64612SMed Ismail Bennani 
6718314c525SJim Ingham   debugger_sp->Clear();
6728314c525SJim Ingham 
673b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
6746c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
6756c42e063SGreg Clayton     DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
676b9c1b51eSKate Stone     for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
677b9c1b51eSKate Stone       if ((*pos).get() == debugger_sp.get()) {
6786c42e063SGreg Clayton         g_debugger_list_ptr->erase(pos);
679e02657b1SCaroline Tice         return;
680e02657b1SCaroline Tice       }
681e02657b1SCaroline Tice     }
682e02657b1SCaroline Tice   }
683c15f55e2SGreg Clayton }
684e02657b1SCaroline Tice 
685e063ecccSJonas Devlieghere DebuggerSP Debugger::FindDebuggerWithInstanceName(ConstString instance_name) {
6864d122c40SGreg Clayton   DebuggerSP debugger_sp;
687b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
6886c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
6896c42e063SGreg Clayton     DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
690b9c1b51eSKate Stone     for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
691b9c1b51eSKate Stone       if ((*pos)->m_instance_name == instance_name) {
6926920b52bSGreg Clayton         debugger_sp = *pos;
6936920b52bSGreg Clayton         break;
6946920b52bSGreg Clayton       }
6956920b52bSGreg Clayton     }
6966920b52bSGreg Clayton   }
6973df9a8dfSCaroline Tice   return debugger_sp;
6983df9a8dfSCaroline Tice }
6996611103cSGreg Clayton 
700b9c1b51eSKate Stone TargetSP Debugger::FindTargetWithProcessID(lldb::pid_t pid) {
7014d122c40SGreg Clayton   TargetSP target_sp;
702b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
7036c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
7046c42e063SGreg Clayton     DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
705b9c1b51eSKate Stone     for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
7066611103cSGreg Clayton       target_sp = (*pos)->GetTargetList().FindTargetWithProcessID(pid);
7076611103cSGreg Clayton       if (target_sp)
7086611103cSGreg Clayton         break;
7096611103cSGreg Clayton     }
710c15f55e2SGreg Clayton   }
7116611103cSGreg Clayton   return target_sp;
7126611103cSGreg Clayton }
7136611103cSGreg Clayton 
714b9c1b51eSKate Stone TargetSP Debugger::FindTargetWithProcess(Process *process) {
715e4e45924SGreg Clayton   TargetSP target_sp;
716b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
7176c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
7186c42e063SGreg Clayton     DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
719b9c1b51eSKate Stone     for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
720e4e45924SGreg Clayton       target_sp = (*pos)->GetTargetList().FindTargetWithProcess(process);
721e4e45924SGreg Clayton       if (target_sp)
722e4e45924SGreg Clayton         break;
723e4e45924SGreg Clayton     }
724c15f55e2SGreg Clayton   }
725e4e45924SGreg Clayton   return target_sp;
726e4e45924SGreg Clayton }
727e4e45924SGreg Clayton 
728e122877fSGreg Clayton ConstString Debugger::GetStaticBroadcasterClass() {
729e122877fSGreg Clayton   static ConstString class_name("lldb.debugger");
730e122877fSGreg Clayton   return class_name;
731e122877fSGreg Clayton }
732e122877fSGreg Clayton 
733b9c1b51eSKate Stone Debugger::Debugger(lldb::LogOutputCallback log_callback, void *baton)
734b9c1b51eSKate Stone     : UserID(g_unique_id++),
7352f3df613SZachary Turner       Properties(std::make_shared<OptionValueProperties>()),
736f913fd6eSLawrence D'Anna       m_input_file_sp(std::make_shared<NativeFile>(stdin, false)),
7377ca15ba7SLawrence D'Anna       m_output_stream_sp(std::make_shared<StreamFile>(stdout, false)),
7387ca15ba7SLawrence D'Anna       m_error_stream_sp(std::make_shared<StreamFile>(stderr, false)),
739d77c2e09SJonas Devlieghere       m_input_recorder(nullptr),
740583bbb1dSJim Ingham       m_broadcaster_manager_sp(BroadcasterManager::MakeBroadcasterManager()),
741b9c1b51eSKate Stone       m_terminal_state(), m_target_list(*this), m_platform_list(),
742583bbb1dSJim Ingham       m_listener_sp(Listener::MakeListener("lldb.Debugger")),
743d5b44036SJonas Devlieghere       m_source_manager_up(), m_source_file_cache(),
744f20dd1d5SJonas Devlieghere       m_command_interpreter_up(
745a8f3ae7cSJonas Devlieghere           std::make_unique<CommandInterpreter>(*this, false)),
7467ce2de2cSJonas Devlieghere       m_io_handler_stack(), m_instance_name(), m_loaded_plugins(),
747bbf70c04SJonas Devlieghere       m_event_handler_thread(), m_io_handler_thread(),
7484329fe42SGreg Clayton       m_sync_broadcaster(nullptr, "lldb.debugger.sync"),
749e122877fSGreg Clayton       m_broadcaster(m_broadcaster_manager_sp,
750e122877fSGreg Clayton                     GetStaticBroadcasterClass().AsCString()),
751b9c1b51eSKate Stone       m_forward_listener_sp(), m_clear_once() {
752db203e02SRaphael Isemann   m_instance_name.SetString(llvm::formatv("debugger_{0}", GetID()).str());
753228063cdSJim Ingham   if (log_callback)
7542f3df613SZachary Turner     m_log_callback_stream_sp =
7552f3df613SZachary Turner         std::make_shared<StreamCallback>(log_callback, baton);
756d5b44036SJonas Devlieghere   m_command_interpreter_up->Initialize();
757ded470d3SGreg Clayton   // Always add our default platform to the platform list
758615eb7e6SGreg Clayton   PlatformSP default_platform_sp(Platform::GetHostPlatform());
759df370550SEugene Zelenko   assert(default_platform_sp);
760ded470d3SGreg Clayton   m_platform_list.Append(default_platform_sp, true);
76167cc0636SGreg Clayton 
76216e5a347SVedant Kumar   // Create the dummy target.
76316e5a347SVedant Kumar   {
76416e5a347SVedant Kumar     ArchSpec arch(Target::GetDefaultArchitecture());
76516e5a347SVedant Kumar     if (!arch.IsValid())
76616e5a347SVedant Kumar       arch = HostInfo::GetArchitecture();
76716e5a347SVedant Kumar     assert(arch.IsValid() && "No valid default or host archspec");
76816e5a347SVedant Kumar     const bool is_dummy_target = true;
76916e5a347SVedant Kumar     m_dummy_target_sp.reset(
77016e5a347SVedant Kumar         new Target(*this, arch, default_platform_sp, is_dummy_target));
77116e5a347SVedant Kumar   }
772d43d912bSRaphael Isemann   assert(m_dummy_target_sp.get() && "Couldn't construct dummy target?");
773d43d912bSRaphael Isemann 
774a8ea5955SJonas Devlieghere   m_collection_sp->Initialize(g_debugger_properties);
775b9c1b51eSKate Stone   m_collection_sp->AppendProperty(
776b9c1b51eSKate Stone       ConstString("target"),
777b9c1b51eSKate Stone       ConstString("Settings specify to debugging targets."), true,
7783d7161e3SPavel Labath       Target::GetGlobalProperties().GetValueProperties());
779b9c1b51eSKate Stone   m_collection_sp->AppendProperty(
780b9c1b51eSKate Stone       ConstString("platform"), ConstString("Platform settings."), true,
7813d7161e3SPavel Labath       Platform::GetGlobalPlatformProperties().GetValueProperties());
782235354beSAdrian Prantl   m_collection_sp->AppendProperty(
7833cd29bcfSAdrian Prantl       ConstString("symbols"), ConstString("Symbol lookup and cache settings."),
7843cd29bcfSAdrian Prantl       true, ModuleList::GetGlobalModuleListProperties().GetValueProperties());
785d5b44036SJonas Devlieghere   if (m_command_interpreter_up) {
786b9c1b51eSKate Stone     m_collection_sp->AppendProperty(
787b9c1b51eSKate Stone         ConstString("interpreter"),
788754a9369SGreg Clayton         ConstString("Settings specify to the debugger's command interpreter."),
789d5b44036SJonas Devlieghere         true, m_command_interpreter_up->GetValueProperties());
790754a9369SGreg Clayton   }
791b9c1b51eSKate Stone   OptionValueSInt64 *term_width =
792b9c1b51eSKate Stone       m_collection_sp->GetPropertyAtIndexAsOptionValueSInt64(
793b9c1b51eSKate Stone           nullptr, ePropertyTerminalWidth);
79467cc0636SGreg Clayton   term_width->SetMinimumValue(10);
79567cc0636SGreg Clayton   term_width->SetMaximumValue(1024);
796c3ce7f27SMichael Sartain 
797c3ce7f27SMichael Sartain   // Turn off use-color if this is a dumb terminal.
798c3ce7f27SMichael Sartain   const char *term = getenv("TERM");
799c3ce7f27SMichael Sartain   if (term && !strcmp(term, "dumb"))
800c3ce7f27SMichael Sartain     SetUseColor(false);
801eca9ce14SRaphael Isemann   // Turn off use-color if we don't write to a terminal with color support.
8027ca15ba7SLawrence D'Anna   if (!GetOutputFile().GetIsTerminalWithColors())
803eca9ce14SRaphael Isemann     SetUseColor(false);
8048aa23614SDavid Bolvansky 
8058aa23614SDavid Bolvansky #if defined(_WIN32) && defined(ENABLE_VIRTUAL_TERMINAL_PROCESSING)
8068aa23614SDavid Bolvansky   // Enabling use of ANSI color codes because LLDB is using them to highlight
8078aa23614SDavid Bolvansky   // text.
8088aa23614SDavid Bolvansky   llvm::sys::Process::UseANSIEscapeCodes(true);
8098aa23614SDavid Bolvansky #endif
81030fdc8d8SChris Lattner }
81130fdc8d8SChris Lattner 
812b9c1b51eSKate Stone Debugger::~Debugger() { Clear(); }
8138314c525SJim Ingham 
814b9c1b51eSKate Stone void Debugger::Clear() {
81505097246SAdrian Prantl   // Make sure we call this function only once. With the C++ global destructor
81605097246SAdrian Prantl   // chain having a list of debuggers and with code that can be running on
81705097246SAdrian Prantl   // other threads, we need to ensure this doesn't happen multiple times.
8184329fe42SGreg Clayton   //
8194329fe42SGreg Clayton   // The following functions call Debugger::Clear():
8204329fe42SGreg Clayton   //     Debugger::~Debugger();
8214329fe42SGreg Clayton   //     static void Debugger::Destroy(lldb::DebuggerSP &debugger_sp);
8224329fe42SGreg Clayton   //     static void Debugger::Terminate();
823c5f28e2aSKamil Rytarowski   llvm::call_once(m_clear_once, [this]() {
82444d93782SGreg Clayton     ClearIOHandlers();
82544d93782SGreg Clayton     StopIOHandlerThread();
82644d93782SGreg Clayton     StopEventHandlerThread();
827583bbb1dSJim Ingham     m_listener_sp->Clear();
828de448c0aSJonas Devlieghere     for (TargetSP target_sp : m_target_list.Targets()) {
829b9c1b51eSKate Stone       if (target_sp) {
830de448c0aSJonas Devlieghere         if (ProcessSP process_sp = target_sp->GetProcessSP())
8311fd07059SJim Ingham           process_sp->Finalize();
832ccbc08e6SGreg Clayton         target_sp->Destroy();
8336611103cSGreg Clayton       }
83430fdc8d8SChris Lattner     }
835583bbb1dSJim Ingham     m_broadcaster_manager_sp->Clear();
83630fdc8d8SChris Lattner 
837b9c1b51eSKate Stone     // Close the input file _before_ we close the input read communications
83805097246SAdrian Prantl     // class as it does NOT own the input file, our m_input_file does.
839c5917d9aSJim Ingham     m_terminal_state.Clear();
8407ca15ba7SLawrence D'Anna     GetInputFile().Close();
8410c4129f2SGreg Clayton 
842d5b44036SJonas Devlieghere     m_command_interpreter_up->Clear();
8434329fe42SGreg Clayton   });
8448314c525SJim Ingham }
84530fdc8d8SChris Lattner 
846b9c1b51eSKate Stone bool Debugger::GetCloseInputOnEOF() const {
84744d93782SGreg Clayton   //    return m_input_comm.GetCloseOnEOF();
84844d93782SGreg Clayton   return false;
849fc3f027dSGreg Clayton }
850fc3f027dSGreg Clayton 
851b9c1b51eSKate Stone void Debugger::SetCloseInputOnEOF(bool b) {
85244d93782SGreg Clayton   //    m_input_comm.SetCloseOnEOF(b);
853fc3f027dSGreg Clayton }
854fc3f027dSGreg Clayton 
855b9c1b51eSKate Stone bool Debugger::GetAsyncExecution() {
856d5b44036SJonas Devlieghere   return !m_command_interpreter_up->GetSynchronous();
85730fdc8d8SChris Lattner }
85830fdc8d8SChris Lattner 
859b9c1b51eSKate Stone void Debugger::SetAsyncExecution(bool async_execution) {
860d5b44036SJonas Devlieghere   m_command_interpreter_up->SetSynchronous(!async_execution);
86130fdc8d8SChris Lattner }
86230fdc8d8SChris Lattner 
863d77c2e09SJonas Devlieghere repro::DataRecorder *Debugger::GetInputRecorder() { return m_input_recorder; }
864d77c2e09SJonas Devlieghere 
865f23b829aSLevon Ter-Grigoryan static inline int OpenPipe(int fds[2], std::size_t size) {
866f23b829aSLevon Ter-Grigoryan #ifdef _WIN32
867f23b829aSLevon Ter-Grigoryan   return _pipe(fds, size, O_BINARY);
868f23b829aSLevon Ter-Grigoryan #else
869f23b829aSLevon Ter-Grigoryan   (void)size;
870f23b829aSLevon Ter-Grigoryan   return pipe(fds);
871f23b829aSLevon Ter-Grigoryan #endif
872f23b829aSLevon Ter-Grigoryan }
873f23b829aSLevon Ter-Grigoryan 
874f23b829aSLevon Ter-Grigoryan Status Debugger::SetInputString(const char *data) {
875f23b829aSLevon Ter-Grigoryan   Status result;
876f23b829aSLevon Ter-Grigoryan   enum PIPES { READ, WRITE }; // Indexes for the read and write fds
877f23b829aSLevon Ter-Grigoryan   int fds[2] = {-1, -1};
878f23b829aSLevon Ter-Grigoryan 
879f23b829aSLevon Ter-Grigoryan   if (data == nullptr) {
880f23b829aSLevon Ter-Grigoryan     result.SetErrorString("String data is null");
881f23b829aSLevon Ter-Grigoryan     return result;
882f23b829aSLevon Ter-Grigoryan   }
883f23b829aSLevon Ter-Grigoryan 
884f23b829aSLevon Ter-Grigoryan   size_t size = strlen(data);
885f23b829aSLevon Ter-Grigoryan   if (size == 0) {
886f23b829aSLevon Ter-Grigoryan     result.SetErrorString("String data is empty");
887f23b829aSLevon Ter-Grigoryan     return result;
888f23b829aSLevon Ter-Grigoryan   }
889f23b829aSLevon Ter-Grigoryan 
890f23b829aSLevon Ter-Grigoryan   if (OpenPipe(fds, size) != 0) {
891f23b829aSLevon Ter-Grigoryan     result.SetErrorString(
892f23b829aSLevon Ter-Grigoryan         "can't create pipe file descriptors for LLDB commands");
893f23b829aSLevon Ter-Grigoryan     return result;
894f23b829aSLevon Ter-Grigoryan   }
895f23b829aSLevon Ter-Grigoryan 
896f23b829aSLevon Ter-Grigoryan   write(fds[WRITE], data, size);
897f23b829aSLevon Ter-Grigoryan   // Close the write end of the pipe, so that the command interpreter will exit
898f23b829aSLevon Ter-Grigoryan   // when it consumes all the data.
899f23b829aSLevon Ter-Grigoryan   llvm::sys::Process::SafelyCloseFileDescriptor(fds[WRITE]);
900f23b829aSLevon Ter-Grigoryan 
901f23b829aSLevon Ter-Grigoryan   // Open the read file descriptor as a FILE * that we can return as an input
902f23b829aSLevon Ter-Grigoryan   // handle.
903f23b829aSLevon Ter-Grigoryan   FILE *commands_file = fdopen(fds[READ], "rb");
904f23b829aSLevon Ter-Grigoryan   if (commands_file == nullptr) {
905f23b829aSLevon Ter-Grigoryan     result.SetErrorStringWithFormat("fdopen(%i, \"rb\") failed (errno = %i) "
906f23b829aSLevon Ter-Grigoryan                                     "when trying to open LLDB commands pipe",
907f23b829aSLevon Ter-Grigoryan                                     fds[READ], errno);
908f23b829aSLevon Ter-Grigoryan     llvm::sys::Process::SafelyCloseFileDescriptor(fds[READ]);
909f23b829aSLevon Ter-Grigoryan     return result;
910f23b829aSLevon Ter-Grigoryan   }
911f23b829aSLevon Ter-Grigoryan 
912f23b829aSLevon Ter-Grigoryan   return SetInputFile(
913f23b829aSLevon Ter-Grigoryan       (FileSP)std::make_shared<NativeFile>(commands_file, true));
914f23b829aSLevon Ter-Grigoryan }
915f23b829aSLevon Ter-Grigoryan 
916f23b829aSLevon Ter-Grigoryan Status Debugger::SetInputFile(FileSP file_sp) {
917f23b829aSLevon Ter-Grigoryan   Status error;
918f23b829aSLevon Ter-Grigoryan   repro::DataRecorder *recorder = nullptr;
919f23b829aSLevon Ter-Grigoryan   if (repro::Generator *g = repro::Reproducer::Instance().GetGenerator())
920f23b829aSLevon Ter-Grigoryan     recorder = g->GetOrCreate<repro::CommandProvider>().GetNewRecorder();
921f23b829aSLevon Ter-Grigoryan 
922f23b829aSLevon Ter-Grigoryan   static std::unique_ptr<repro::MultiLoader<repro::CommandProvider>> loader =
923f23b829aSLevon Ter-Grigoryan       repro::MultiLoader<repro::CommandProvider>::Create(
924f23b829aSLevon Ter-Grigoryan           repro::Reproducer::Instance().GetLoader());
925f23b829aSLevon Ter-Grigoryan   if (loader) {
926f23b829aSLevon Ter-Grigoryan     llvm::Optional<std::string> nextfile = loader->GetNextFile();
927f23b829aSLevon Ter-Grigoryan     FILE *fh = nextfile ? FileSystem::Instance().Fopen(nextfile->c_str(), "r")
928f23b829aSLevon Ter-Grigoryan                         : nullptr;
929f23b829aSLevon Ter-Grigoryan     // FIXME Jonas Devlieghere: shouldn't this error be propagated out to the
930f23b829aSLevon Ter-Grigoryan     // reproducer somehow if fh is NULL?
931f23b829aSLevon Ter-Grigoryan     if (fh) {
932f23b829aSLevon Ter-Grigoryan       file_sp = std::make_shared<NativeFile>(fh, true);
933f23b829aSLevon Ter-Grigoryan     }
934f23b829aSLevon Ter-Grigoryan   }
935f23b829aSLevon Ter-Grigoryan 
936f23b829aSLevon Ter-Grigoryan   if (!file_sp || !file_sp->IsValid()) {
937f23b829aSLevon Ter-Grigoryan     error.SetErrorString("invalid file");
938f23b829aSLevon Ter-Grigoryan     return error;
939f23b829aSLevon Ter-Grigoryan   }
940f23b829aSLevon Ter-Grigoryan 
941f23b829aSLevon Ter-Grigoryan   SetInputFile(file_sp, recorder);
942f23b829aSLevon Ter-Grigoryan   return error;
943f23b829aSLevon Ter-Grigoryan }
944f23b829aSLevon Ter-Grigoryan 
94596898eb6SLawrence D'Anna void Debugger::SetInputFile(FileSP file_sp, repro::DataRecorder *recorder) {
94696898eb6SLawrence D'Anna   assert(file_sp && file_sp->IsValid());
947d77c2e09SJonas Devlieghere   m_input_recorder = recorder;
948c4701c9cSJonas Devlieghere   m_input_file_sp = std::move(file_sp);
94905097246SAdrian Prantl   // Save away the terminal state if that is relevant, so that we can restore
95005097246SAdrian Prantl   // it in RestoreInputState.
951c5917d9aSJim Ingham   SaveInputTerminalState();
95230fdc8d8SChris Lattner }
95330fdc8d8SChris Lattner 
95496898eb6SLawrence D'Anna void Debugger::SetOutputFile(FileSP file_sp) {
95596898eb6SLawrence D'Anna   assert(file_sp && file_sp->IsValid());
9567ca15ba7SLawrence D'Anna   m_output_stream_sp = std::make_shared<StreamFile>(file_sp);
95730fdc8d8SChris Lattner }
95830fdc8d8SChris Lattner 
95996898eb6SLawrence D'Anna void Debugger::SetErrorFile(FileSP file_sp) {
96096898eb6SLawrence D'Anna   assert(file_sp && file_sp->IsValid());
9617ca15ba7SLawrence D'Anna   m_error_stream_sp = std::make_shared<StreamFile>(file_sp);
96230fdc8d8SChris Lattner }
96330fdc8d8SChris Lattner 
964b9c1b51eSKate Stone void Debugger::SaveInputTerminalState() {
9657ca15ba7SLawrence D'Anna   int fd = GetInputFile().GetDescriptor();
9667ca15ba7SLawrence D'Anna   if (fd != File::kInvalidDescriptor)
9677ca15ba7SLawrence D'Anna     m_terminal_state.Save(fd, true);
96844d93782SGreg Clayton }
969c5917d9aSJim Ingham 
970b9c1b51eSKate Stone void Debugger::RestoreInputTerminalState() { m_terminal_state.Restore(); }
971c5917d9aSJim Ingham 
972b9c1b51eSKate Stone ExecutionContext Debugger::GetSelectedExecutionContext() {
973a39bcbcaSTatyana Krasnukha   bool adopt_selected = true;
974a39bcbcaSTatyana Krasnukha   ExecutionContextRef exe_ctx_ref(GetSelectedTarget().get(), adopt_selected);
975a39bcbcaSTatyana Krasnukha   return ExecutionContext(exe_ctx_ref);
97630fdc8d8SChris Lattner }
97730fdc8d8SChris Lattner 
978b9c1b51eSKate Stone void Debugger::DispatchInputInterrupt() {
9797ce2de2cSJonas Devlieghere   std::lock_guard<std::recursive_mutex> guard(m_io_handler_stack.GetMutex());
9807ce2de2cSJonas Devlieghere   IOHandlerSP reader_sp(m_io_handler_stack.Top());
981efed6131SCaroline Tice   if (reader_sp)
98244d93782SGreg Clayton     reader_sp->Interrupt();
983efed6131SCaroline Tice }
984efed6131SCaroline Tice 
985b9c1b51eSKate Stone void Debugger::DispatchInputEndOfFile() {
9867ce2de2cSJonas Devlieghere   std::lock_guard<std::recursive_mutex> guard(m_io_handler_stack.GetMutex());
9877ce2de2cSJonas Devlieghere   IOHandlerSP reader_sp(m_io_handler_stack.Top());
988efed6131SCaroline Tice   if (reader_sp)
98944d93782SGreg Clayton     reader_sp->GotEOF();
990efed6131SCaroline Tice }
991efed6131SCaroline Tice 
992b9c1b51eSKate Stone void Debugger::ClearIOHandlers() {
993b9c1b51eSKate Stone   // The bottom input reader should be the main debugger input reader.  We do
994b9c1b51eSKate Stone   // not want to close that one here.
9957ce2de2cSJonas Devlieghere   std::lock_guard<std::recursive_mutex> guard(m_io_handler_stack.GetMutex());
9967ce2de2cSJonas Devlieghere   while (m_io_handler_stack.GetSize() > 1) {
9977ce2de2cSJonas Devlieghere     IOHandlerSP reader_sp(m_io_handler_stack.Top());
9983d6086f6SCaroline Tice     if (reader_sp)
9994446487dSPavel Labath       PopIOHandler(reader_sp);
10003d6086f6SCaroline Tice   }
10013d6086f6SCaroline Tice }
10023d6086f6SCaroline Tice 
10032671df9bSJonas Devlieghere void Debugger::RunIOHandlers() {
100404de24e6SJonas Devlieghere   IOHandlerSP reader_sp = m_io_handler_stack.Top();
1005b9c1b51eSKate Stone   while (true) {
100630fdc8d8SChris Lattner     if (!reader_sp)
100730fdc8d8SChris Lattner       break;
100830fdc8d8SChris Lattner 
100944d93782SGreg Clayton     reader_sp->Run();
101004de24e6SJonas Devlieghere     {
101104de24e6SJonas Devlieghere       std::lock_guard<std::recursive_mutex> guard(
101204de24e6SJonas Devlieghere           m_io_handler_synchronous_mutex);
101344d93782SGreg Clayton 
101444d93782SGreg Clayton       // Remove all input readers that are done from the top of the stack
1015b9c1b51eSKate Stone       while (true) {
10167ce2de2cSJonas Devlieghere         IOHandlerSP top_reader_sp = m_io_handler_stack.Top();
101744d93782SGreg Clayton         if (top_reader_sp && top_reader_sp->GetIsDone())
10184446487dSPavel Labath           PopIOHandler(top_reader_sp);
101930fdc8d8SChris Lattner         else
102030fdc8d8SChris Lattner           break;
102130fdc8d8SChris Lattner       }
102204de24e6SJonas Devlieghere       reader_sp = m_io_handler_stack.Top();
102304de24e6SJonas Devlieghere     }
102430fdc8d8SChris Lattner   }
102544d93782SGreg Clayton   ClearIOHandlers();
102644d93782SGreg Clayton }
102730fdc8d8SChris Lattner 
102804de24e6SJonas Devlieghere void Debugger::RunIOHandlerSync(const IOHandlerSP &reader_sp) {
102904de24e6SJonas Devlieghere   std::lock_guard<std::recursive_mutex> guard(m_io_handler_synchronous_mutex);
103004de24e6SJonas Devlieghere 
103104de24e6SJonas Devlieghere   PushIOHandler(reader_sp);
103204de24e6SJonas Devlieghere   IOHandlerSP top_reader_sp = reader_sp;
103304de24e6SJonas Devlieghere 
103404de24e6SJonas Devlieghere   while (top_reader_sp) {
103504de24e6SJonas Devlieghere     if (!top_reader_sp)
103604de24e6SJonas Devlieghere       break;
103704de24e6SJonas Devlieghere 
103804de24e6SJonas Devlieghere     top_reader_sp->Run();
103904de24e6SJonas Devlieghere 
104004de24e6SJonas Devlieghere     // Don't unwind past the starting point.
104104de24e6SJonas Devlieghere     if (top_reader_sp.get() == reader_sp.get()) {
104204de24e6SJonas Devlieghere       if (PopIOHandler(reader_sp))
104304de24e6SJonas Devlieghere         break;
104404de24e6SJonas Devlieghere     }
104504de24e6SJonas Devlieghere 
104604de24e6SJonas Devlieghere     // If we pushed new IO handlers, pop them if they're done or restart the
104704de24e6SJonas Devlieghere     // loop to run them if they're not.
104804de24e6SJonas Devlieghere     while (true) {
104904de24e6SJonas Devlieghere       top_reader_sp = m_io_handler_stack.Top();
105004de24e6SJonas Devlieghere       if (top_reader_sp && top_reader_sp->GetIsDone()) {
105104de24e6SJonas Devlieghere         PopIOHandler(top_reader_sp);
105204de24e6SJonas Devlieghere         // Don't unwind past the starting point.
105304de24e6SJonas Devlieghere         if (top_reader_sp.get() == reader_sp.get())
105404de24e6SJonas Devlieghere           return;
105504de24e6SJonas Devlieghere       } else {
105604de24e6SJonas Devlieghere         break;
105704de24e6SJonas Devlieghere       }
105804de24e6SJonas Devlieghere     }
105904de24e6SJonas Devlieghere   }
106004de24e6SJonas Devlieghere }
106104de24e6SJonas Devlieghere 
1062b9c1b51eSKate Stone bool Debugger::IsTopIOHandler(const lldb::IOHandlerSP &reader_sp) {
10637ce2de2cSJonas Devlieghere   return m_io_handler_stack.IsTop(reader_sp);
106444d93782SGreg Clayton }
106530fdc8d8SChris Lattner 
1066b9c1b51eSKate Stone bool Debugger::CheckTopIOHandlerTypes(IOHandler::Type top_type,
1067b9c1b51eSKate Stone                                       IOHandler::Type second_top_type) {
10687ce2de2cSJonas Devlieghere   return m_io_handler_stack.CheckTopIOHandlerTypes(top_type, second_top_type);
10696681041dSSean Callanan }
10706681041dSSean Callanan 
1071b9c1b51eSKate Stone void Debugger::PrintAsync(const char *s, size_t len, bool is_stdout) {
10722436c570SJonas Devlieghere   bool printed = m_io_handler_stack.PrintAsync(s, len, is_stdout);
10732436c570SJonas Devlieghere   if (!printed) {
10742436c570SJonas Devlieghere     lldb::StreamFileSP stream =
10752436c570SJonas Devlieghere         is_stdout ? m_output_stream_sp : m_error_stream_sp;
10762436c570SJonas Devlieghere     stream->Write(s, len);
10772436c570SJonas Devlieghere   }
10784446487dSPavel Labath }
107944d93782SGreg Clayton 
1080b9c1b51eSKate Stone ConstString Debugger::GetTopIOHandlerControlSequence(char ch) {
10817ce2de2cSJonas Devlieghere   return m_io_handler_stack.GetTopIOHandlerControlSequence(ch);
108230fdc8d8SChris Lattner }
108330fdc8d8SChris Lattner 
1084b9c1b51eSKate Stone const char *Debugger::GetIOHandlerCommandPrefix() {
10857ce2de2cSJonas Devlieghere   return m_io_handler_stack.GetTopIOHandlerCommandPrefix();
1086a487aa4cSKate Stone }
1087a487aa4cSKate Stone 
1088b9c1b51eSKate Stone const char *Debugger::GetIOHandlerHelpPrologue() {
10897ce2de2cSJonas Devlieghere   return m_io_handler_stack.GetTopIOHandlerHelpPrologue();
1090a487aa4cSKate Stone }
1091a487aa4cSKate Stone 
10927ce2de2cSJonas Devlieghere bool Debugger::RemoveIOHandler(const IOHandlerSP &reader_sp) {
10937ce2de2cSJonas Devlieghere   return PopIOHandler(reader_sp);
10947ce2de2cSJonas Devlieghere }
10957ce2de2cSJonas Devlieghere 
10967ce2de2cSJonas Devlieghere void Debugger::RunIOHandlerAsync(const IOHandlerSP &reader_sp,
10977ce2de2cSJonas Devlieghere                                  bool cancel_top_handler) {
10987ce2de2cSJonas Devlieghere   PushIOHandler(reader_sp, cancel_top_handler);
10997ce2de2cSJonas Devlieghere }
11007ce2de2cSJonas Devlieghere 
11017ca15ba7SLawrence D'Anna void Debugger::AdoptTopIOHandlerFilesIfInvalid(FileSP &in, StreamFileSP &out,
1102b9c1b51eSKate Stone                                                StreamFileSP &err) {
110305097246SAdrian Prantl   // Before an IOHandler runs, it must have in/out/err streams. This function
110405097246SAdrian Prantl   // is called when one ore more of the streams are nullptr. We use the top
110505097246SAdrian Prantl   // input reader's in/out/err streams, or fall back to the debugger file
110605097246SAdrian Prantl   // handles, or we fall back onto stdin/stdout/stderr as a last resort.
110744d93782SGreg Clayton 
11087ce2de2cSJonas Devlieghere   std::lock_guard<std::recursive_mutex> guard(m_io_handler_stack.GetMutex());
11097ce2de2cSJonas Devlieghere   IOHandlerSP top_reader_sp(m_io_handler_stack.Top());
111044d93782SGreg Clayton   // If no STDIN has been set, then set it appropriately
1111b07823f3SLawrence D'Anna   if (!in || !in->IsValid()) {
111244d93782SGreg Clayton     if (top_reader_sp)
11137ca15ba7SLawrence D'Anna       in = top_reader_sp->GetInputFileSP();
111444d93782SGreg Clayton     else
11157ca15ba7SLawrence D'Anna       in = GetInputFileSP();
111644d93782SGreg Clayton     // If there is nothing, use stdin
111744d93782SGreg Clayton     if (!in)
1118f913fd6eSLawrence D'Anna       in = std::make_shared<NativeFile>(stdin, false);
111944d93782SGreg Clayton   }
112044d93782SGreg Clayton   // If no STDOUT has been set, then set it appropriately
1121b07823f3SLawrence D'Anna   if (!out || !out->GetFile().IsValid()) {
112244d93782SGreg Clayton     if (top_reader_sp)
11237ca15ba7SLawrence D'Anna       out = top_reader_sp->GetOutputStreamFileSP();
112444d93782SGreg Clayton     else
11257ca15ba7SLawrence D'Anna       out = GetOutputStreamSP();
112644d93782SGreg Clayton     // If there is nothing, use stdout
112744d93782SGreg Clayton     if (!out)
11282f3df613SZachary Turner       out = std::make_shared<StreamFile>(stdout, false);
112944d93782SGreg Clayton   }
113044d93782SGreg Clayton   // If no STDERR has been set, then set it appropriately
1131b07823f3SLawrence D'Anna   if (!err || !err->GetFile().IsValid()) {
113244d93782SGreg Clayton     if (top_reader_sp)
11337ca15ba7SLawrence D'Anna       err = top_reader_sp->GetErrorStreamFileSP();
113444d93782SGreg Clayton     else
11357ca15ba7SLawrence D'Anna       err = GetErrorStreamSP();
113644d93782SGreg Clayton     // If there is nothing, use stderr
113744d93782SGreg Clayton     if (!err)
11387ca15ba7SLawrence D'Anna       err = std::make_shared<StreamFile>(stderr, false);
113944d93782SGreg Clayton   }
114044d93782SGreg Clayton }
114144d93782SGreg Clayton 
1142c01783a8SRaphael Isemann void Debugger::PushIOHandler(const IOHandlerSP &reader_sp,
1143c01783a8SRaphael Isemann                              bool cancel_top_handler) {
114430fdc8d8SChris Lattner   if (!reader_sp)
114530fdc8d8SChris Lattner     return;
1146b44880caSCaroline Tice 
11477ce2de2cSJonas Devlieghere   std::lock_guard<std::recursive_mutex> guard(m_io_handler_stack.GetMutex());
11484446487dSPavel Labath 
11494446487dSPavel Labath   // Get the current top input reader...
11507ce2de2cSJonas Devlieghere   IOHandlerSP top_reader_sp(m_io_handler_stack.Top());
1151b44880caSCaroline Tice 
1152b4874f1aSGreg Clayton   // Don't push the same IO handler twice...
11534446487dSPavel Labath   if (reader_sp == top_reader_sp)
11544446487dSPavel Labath     return;
11554446487dSPavel Labath 
115644d93782SGreg Clayton   // Push our new input reader
11577ce2de2cSJonas Devlieghere   m_io_handler_stack.Push(reader_sp);
11584446487dSPavel Labath   reader_sp->Activate();
115944d93782SGreg Clayton 
116005097246SAdrian Prantl   // Interrupt the top input reader to it will exit its Run() function and let
116105097246SAdrian Prantl   // this new input reader take over
1162b9c1b51eSKate Stone   if (top_reader_sp) {
116344d93782SGreg Clayton     top_reader_sp->Deactivate();
1164c01783a8SRaphael Isemann     if (cancel_top_handler)
11654446487dSPavel Labath       top_reader_sp->Cancel();
116630fdc8d8SChris Lattner   }
1167b4874f1aSGreg Clayton }
116830fdc8d8SChris Lattner 
1169b9c1b51eSKate Stone bool Debugger::PopIOHandler(const IOHandlerSP &pop_reader_sp) {
11704446487dSPavel Labath   if (!pop_reader_sp)
11714446487dSPavel Labath     return false;
117230fdc8d8SChris Lattner 
11737ce2de2cSJonas Devlieghere   std::lock_guard<std::recursive_mutex> guard(m_io_handler_stack.GetMutex());
117444d93782SGreg Clayton 
117505097246SAdrian Prantl   // The reader on the stop of the stack is done, so let the next read on the
117605097246SAdrian Prantl   // stack refresh its prompt and if there is one...
11777ce2de2cSJonas Devlieghere   if (m_io_handler_stack.IsEmpty())
11784446487dSPavel Labath     return false;
11794446487dSPavel Labath 
11807ce2de2cSJonas Devlieghere   IOHandlerSP reader_sp(m_io_handler_stack.Top());
118130fdc8d8SChris Lattner 
11824446487dSPavel Labath   if (pop_reader_sp != reader_sp)
11834446487dSPavel Labath     return false;
11844446487dSPavel Labath 
118544d93782SGreg Clayton   reader_sp->Deactivate();
1186b4874f1aSGreg Clayton   reader_sp->Cancel();
11877ce2de2cSJonas Devlieghere   m_io_handler_stack.Pop();
118830fdc8d8SChris Lattner 
11897ce2de2cSJonas Devlieghere   reader_sp = m_io_handler_stack.Top();
119030fdc8d8SChris Lattner   if (reader_sp)
119144d93782SGreg Clayton     reader_sp->Activate();
119244d93782SGreg Clayton 
119344d93782SGreg Clayton   return true;
119430fdc8d8SChris Lattner }
11956611103cSGreg Clayton 
1196b9c1b51eSKate Stone StreamSP Debugger::GetAsyncOutputStream() {
11972f3df613SZachary Turner   return std::make_shared<StreamAsynchronousIO>(*this, true);
11985b52f0c7SJim Ingham }
11995b52f0c7SJim Ingham 
1200b9c1b51eSKate Stone StreamSP Debugger::GetAsyncErrorStream() {
12012f3df613SZachary Turner   return std::make_shared<StreamAsynchronousIO>(*this, false);
12025b52f0c7SJim Ingham }
12035b52f0c7SJim Ingham 
1204b9c1b51eSKate Stone size_t Debugger::GetNumDebuggers() {
1205b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
12066c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
12076c42e063SGreg Clayton     return g_debugger_list_ptr->size();
1208061858ceSEnrico Granata   }
1209c15f55e2SGreg Clayton   return 0;
1210c15f55e2SGreg Clayton }
1211061858ceSEnrico Granata 
1212b9c1b51eSKate Stone lldb::DebuggerSP Debugger::GetDebuggerAtIndex(size_t index) {
1213061858ceSEnrico Granata   DebuggerSP debugger_sp;
1214061858ceSEnrico Granata 
1215b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
12166c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
12176c42e063SGreg Clayton     if (index < g_debugger_list_ptr->size())
12186c42e063SGreg Clayton       debugger_sp = g_debugger_list_ptr->at(index);
1219c15f55e2SGreg Clayton   }
1220061858ceSEnrico Granata 
1221061858ceSEnrico Granata   return debugger_sp;
1222061858ceSEnrico Granata }
1223061858ceSEnrico Granata 
1224b9c1b51eSKate Stone DebuggerSP Debugger::FindDebuggerWithID(lldb::user_id_t id) {
12254d122c40SGreg Clayton   DebuggerSP debugger_sp;
1226ebc1bb27SCaroline Tice 
1227b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
12286c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
12296c42e063SGreg Clayton     DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
1230b9c1b51eSKate Stone     for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
1231b9c1b51eSKate Stone       if ((*pos)->GetID() == id) {
1232ebc1bb27SCaroline Tice         debugger_sp = *pos;
1233ebc1bb27SCaroline Tice         break;
1234ebc1bb27SCaroline Tice       }
1235ebc1bb27SCaroline Tice     }
1236c15f55e2SGreg Clayton   }
1237ebc1bb27SCaroline Tice   return debugger_sp;
1238ebc1bb27SCaroline Tice }
12393df9a8dfSCaroline Tice 
1240b9c1b51eSKate Stone bool Debugger::FormatDisassemblerAddress(const FormatEntity::Entry *format,
1241aff1b357SJason Molenda                                          const SymbolContext *sc,
1242aff1b357SJason Molenda                                          const SymbolContext *prev_sc,
1243aff1b357SJason Molenda                                          const ExecutionContext *exe_ctx,
1244b9c1b51eSKate Stone                                          const Address *addr, Stream &s) {
1245554f68d3SGreg Clayton   FormatEntity::Entry format_entry;
1246554f68d3SGreg Clayton 
1247b9c1b51eSKate Stone   if (format == nullptr) {
1248df370550SEugene Zelenko     if (exe_ctx != nullptr && exe_ctx->HasTargetScope())
1249aff1b357SJason Molenda       format = exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat();
1250b9c1b51eSKate Stone     if (format == nullptr) {
1251554f68d3SGreg Clayton       FormatEntity::Parse("${addr}: ", format_entry);
1252554f68d3SGreg Clayton       format = &format_entry;
1253554f68d3SGreg Clayton     }
1254aff1b357SJason Molenda   }
1255aff1b357SJason Molenda   bool function_changed = false;
1256aff1b357SJason Molenda   bool initial_function = false;
1257b9c1b51eSKate Stone   if (prev_sc && (prev_sc->function || prev_sc->symbol)) {
1258b9c1b51eSKate Stone     if (sc && (sc->function || sc->symbol)) {
1259b9c1b51eSKate Stone       if (prev_sc->symbol && sc->symbol) {
1260b9c1b51eSKate Stone         if (!sc->symbol->Compare(prev_sc->symbol->GetName(),
1261b9c1b51eSKate Stone                                  prev_sc->symbol->GetType())) {
1262aff1b357SJason Molenda           function_changed = true;
1263aff1b357SJason Molenda         }
1264b9c1b51eSKate Stone       } else if (prev_sc->function && sc->function) {
1265b9c1b51eSKate Stone         if (prev_sc->function->GetMangled() != sc->function->GetMangled()) {
1266aff1b357SJason Molenda           function_changed = true;
1267aff1b357SJason Molenda         }
1268aff1b357SJason Molenda       }
1269aff1b357SJason Molenda     }
1270aff1b357SJason Molenda   }
127105097246SAdrian Prantl   // The first context on a list of instructions will have a prev_sc that has
127205097246SAdrian Prantl   // no Function or Symbol -- if SymbolContext had an IsValid() method, it
1273aff1b357SJason Molenda   // would return false.  But we do get a prev_sc pointer.
1274b9c1b51eSKate Stone   if ((sc && (sc->function || sc->symbol)) && prev_sc &&
1275b9c1b51eSKate Stone       (prev_sc->function == nullptr && prev_sc->symbol == nullptr)) {
1276aff1b357SJason Molenda     initial_function = true;
1277aff1b357SJason Molenda   }
1278b9c1b51eSKate Stone   return FormatEntity::Format(*format, s, sc, exe_ctx, addr, nullptr,
1279b9c1b51eSKate Stone                               function_changed, initial_function);
1280aff1b357SJason Molenda }
1281aff1b357SJason Molenda 
1282b9c1b51eSKate Stone void Debugger::SetLoggingCallback(lldb::LogOutputCallback log_callback,
1283b9c1b51eSKate Stone                                   void *baton) {
12844f02b22dSJim Ingham   // For simplicity's sake, I am not going to deal with how to close down any
12854f02b22dSJim Ingham   // open logging streams, I just redirect everything from here on out to the
12864f02b22dSJim Ingham   // callback.
12872f3df613SZachary Turner   m_log_callback_stream_sp =
12882f3df613SZachary Turner       std::make_shared<StreamCallback>(log_callback, baton);
1289228063cdSJim Ingham }
1290228063cdSJim Ingham 
1291e122877fSGreg Clayton static void PrivateReportProgress(Debugger &debugger, uint64_t progress_id,
1292e122877fSGreg Clayton                                   const std::string &message,
1293e122877fSGreg Clayton                                   uint64_t completed, uint64_t total,
1294e122877fSGreg Clayton                                   bool is_debugger_specific) {
1295e122877fSGreg Clayton   // Only deliver progress events if we have any progress listeners.
1296e122877fSGreg Clayton   const uint32_t event_type = Debugger::eBroadcastBitProgress;
1297e122877fSGreg Clayton   if (!debugger.GetBroadcaster().EventTypeHasListeners(event_type))
1298e122877fSGreg Clayton     return;
12995e65e79bSJonas Devlieghere   EventSP event_sp(new Event(
13005e65e79bSJonas Devlieghere       event_type, new ProgressEventData(progress_id, message, completed, total,
13015e65e79bSJonas Devlieghere                                         is_debugger_specific)));
1302e122877fSGreg Clayton   debugger.GetBroadcaster().BroadcastEvent(event_sp);
1303e122877fSGreg Clayton }
1304e122877fSGreg Clayton 
1305e122877fSGreg Clayton void Debugger::ReportProgress(uint64_t progress_id, const std::string &message,
1306e122877fSGreg Clayton                               uint64_t completed, uint64_t total,
1307e122877fSGreg Clayton                               llvm::Optional<lldb::user_id_t> debugger_id) {
1308e122877fSGreg Clayton   // Check if this progress is for a specific debugger.
1309e122877fSGreg Clayton   if (debugger_id.hasValue()) {
1310e122877fSGreg Clayton     // It is debugger specific, grab it and deliver the event if the debugger
1311e122877fSGreg Clayton     // still exists.
1312e122877fSGreg Clayton     DebuggerSP debugger_sp = FindDebuggerWithID(*debugger_id);
1313e122877fSGreg Clayton     if (debugger_sp)
1314e122877fSGreg Clayton       PrivateReportProgress(*debugger_sp, progress_id, message, completed,
1315e122877fSGreg Clayton                             total, /*is_debugger_specific*/ true);
1316e122877fSGreg Clayton     return;
1317e122877fSGreg Clayton   }
1318e122877fSGreg Clayton   // The progress event is not debugger specific, iterate over all debuggers
1319e122877fSGreg Clayton   // and deliver a progress event to each one.
1320e122877fSGreg Clayton   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
1321e122877fSGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
1322e122877fSGreg Clayton     DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
1323e122877fSGreg Clayton     for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos)
1324e122877fSGreg Clayton       PrivateReportProgress(*(*pos), progress_id, message, completed, total,
1325e122877fSGreg Clayton                             /*is_debugger_specific*/ false);
1326e122877fSGreg Clayton   }
1327e122877fSGreg Clayton }
1328e122877fSGreg Clayton 
1329*2fc38b2bSJonas Devlieghere static void PrivateReportDiagnostic(Debugger &debugger,
1330*2fc38b2bSJonas Devlieghere                                     DiagnosticEventData::Type type,
1331*2fc38b2bSJonas Devlieghere                                     std::string message,
1332*2fc38b2bSJonas Devlieghere                                     bool debugger_specific) {
1333*2fc38b2bSJonas Devlieghere   uint32_t event_type = 0;
1334*2fc38b2bSJonas Devlieghere   switch (type) {
1335*2fc38b2bSJonas Devlieghere   case DiagnosticEventData::Type::Warning:
1336*2fc38b2bSJonas Devlieghere     event_type = Debugger::eBroadcastBitWarning;
1337*2fc38b2bSJonas Devlieghere     break;
1338*2fc38b2bSJonas Devlieghere   case DiagnosticEventData::Type::Error:
1339*2fc38b2bSJonas Devlieghere     event_type = Debugger::eBroadcastBitError;
1340*2fc38b2bSJonas Devlieghere     break;
1341*2fc38b2bSJonas Devlieghere   }
1342*2fc38b2bSJonas Devlieghere 
1343*2fc38b2bSJonas Devlieghere   Broadcaster &broadcaster = debugger.GetBroadcaster();
1344*2fc38b2bSJonas Devlieghere   if (!broadcaster.EventTypeHasListeners(event_type)) {
1345*2fc38b2bSJonas Devlieghere     // Diagnostics are too important to drop. If nobody is listening, print the
1346*2fc38b2bSJonas Devlieghere     // diagnostic directly to the debugger's error stream.
1347*2fc38b2bSJonas Devlieghere     DiagnosticEventData event_data(type, std::move(message), debugger_specific);
1348*2fc38b2bSJonas Devlieghere     StreamSP stream = debugger.GetAsyncErrorStream();
1349*2fc38b2bSJonas Devlieghere     event_data.Dump(stream.get());
1350*2fc38b2bSJonas Devlieghere     return;
1351*2fc38b2bSJonas Devlieghere   }
1352*2fc38b2bSJonas Devlieghere   EventSP event_sp = std::make_shared<Event>(
1353*2fc38b2bSJonas Devlieghere       event_type,
1354*2fc38b2bSJonas Devlieghere       new DiagnosticEventData(type, std::move(message), debugger_specific));
1355*2fc38b2bSJonas Devlieghere   broadcaster.BroadcastEvent(event_sp);
1356*2fc38b2bSJonas Devlieghere }
1357*2fc38b2bSJonas Devlieghere 
1358*2fc38b2bSJonas Devlieghere void Debugger::ReportDiagnosticImpl(DiagnosticEventData::Type type,
1359*2fc38b2bSJonas Devlieghere                                     std::string message,
1360*2fc38b2bSJonas Devlieghere                                     llvm::Optional<lldb::user_id_t> debugger_id,
1361*2fc38b2bSJonas Devlieghere                                     std::once_flag *once) {
1362*2fc38b2bSJonas Devlieghere   auto ReportDiagnosticLambda = [&]() {
1363*2fc38b2bSJonas Devlieghere     // Check if this progress is for a specific debugger.
1364*2fc38b2bSJonas Devlieghere     if (debugger_id) {
1365*2fc38b2bSJonas Devlieghere       // It is debugger specific, grab it and deliver the event if the debugger
1366*2fc38b2bSJonas Devlieghere       // still exists.
1367*2fc38b2bSJonas Devlieghere       DebuggerSP debugger_sp = FindDebuggerWithID(*debugger_id);
1368*2fc38b2bSJonas Devlieghere       if (debugger_sp)
1369*2fc38b2bSJonas Devlieghere         PrivateReportDiagnostic(*debugger_sp, type, std::move(message), true);
1370*2fc38b2bSJonas Devlieghere       return;
1371*2fc38b2bSJonas Devlieghere     }
1372*2fc38b2bSJonas Devlieghere     // The progress event is not debugger specific, iterate over all debuggers
1373*2fc38b2bSJonas Devlieghere     // and deliver a progress event to each one.
1374*2fc38b2bSJonas Devlieghere     if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
1375*2fc38b2bSJonas Devlieghere       std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
1376*2fc38b2bSJonas Devlieghere       for (const auto &debugger : *g_debugger_list_ptr)
1377*2fc38b2bSJonas Devlieghere         PrivateReportDiagnostic(*debugger, type, message, false);
1378*2fc38b2bSJonas Devlieghere     }
1379*2fc38b2bSJonas Devlieghere   };
1380*2fc38b2bSJonas Devlieghere 
1381*2fc38b2bSJonas Devlieghere   if (once)
1382*2fc38b2bSJonas Devlieghere     std::call_once(*once, ReportDiagnosticLambda);
1383*2fc38b2bSJonas Devlieghere   else
1384*2fc38b2bSJonas Devlieghere     ReportDiagnosticLambda();
1385*2fc38b2bSJonas Devlieghere }
1386*2fc38b2bSJonas Devlieghere 
1387*2fc38b2bSJonas Devlieghere void Debugger::ReportWarning(std::string message,
1388*2fc38b2bSJonas Devlieghere                              llvm::Optional<lldb::user_id_t> debugger_id,
1389*2fc38b2bSJonas Devlieghere                              std::once_flag *once) {
1390*2fc38b2bSJonas Devlieghere   ReportDiagnosticImpl(DiagnosticEventData::Type::Warning, std::move(message),
1391*2fc38b2bSJonas Devlieghere                        debugger_id, once);
1392*2fc38b2bSJonas Devlieghere }
1393*2fc38b2bSJonas Devlieghere 
1394*2fc38b2bSJonas Devlieghere void Debugger::ReportError(std::string message,
1395*2fc38b2bSJonas Devlieghere                            llvm::Optional<lldb::user_id_t> debugger_id,
1396*2fc38b2bSJonas Devlieghere                            std::once_flag *once) {
1397*2fc38b2bSJonas Devlieghere 
1398*2fc38b2bSJonas Devlieghere   ReportDiagnosticImpl(DiagnosticEventData::Type::Error, std::move(message),
1399*2fc38b2bSJonas Devlieghere                        debugger_id, once);
1400*2fc38b2bSJonas Devlieghere }
1401*2fc38b2bSJonas Devlieghere 
14025e336903SPavel Labath bool Debugger::EnableLog(llvm::StringRef channel,
14035e336903SPavel Labath                          llvm::ArrayRef<const char *> categories,
14045e336903SPavel Labath                          llvm::StringRef log_file, uint32_t log_options,
1405775588c0SPavel Labath                          llvm::raw_ostream &error_stream) {
14065fae71c5SPavel Labath   const bool should_close = true;
14075fae71c5SPavel Labath   const bool unbuffered = true;
14085fae71c5SPavel Labath 
14095fae71c5SPavel Labath   std::shared_ptr<llvm::raw_ostream> log_stream_sp;
1410b9c1b51eSKate Stone   if (m_log_callback_stream_sp) {
1411228063cdSJim Ingham     log_stream_sp = m_log_callback_stream_sp;
1412228063cdSJim Ingham     // For now when using the callback mode you always get thread & timestamp.
1413b9c1b51eSKate Stone     log_options |=
1414b9c1b51eSKate Stone         LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_THREAD_NAME;
14155e336903SPavel Labath   } else if (log_file.empty()) {
14165fae71c5SPavel Labath     log_stream_sp = std::make_shared<llvm::raw_fd_ostream>(
14177ca15ba7SLawrence D'Anna         GetOutputFile().GetDescriptor(), !should_close, unbuffered);
1418b9c1b51eSKate Stone   } else {
14195fae71c5SPavel Labath     auto pos = m_log_streams.find(log_file);
1420c1b2ccfdSGreg Clayton     if (pos != m_log_streams.end())
1421c1b2ccfdSGreg Clayton       log_stream_sp = pos->second.lock();
1422b9c1b51eSKate Stone     if (!log_stream_sp) {
14236b2e6765SJonas Devlieghere       File::OpenOptions flags =
142414735cabSMichał Górny           File::eOpenOptionWriteOnly | File::eOpenOptionCanCreate;
14255fae71c5SPavel Labath       if (log_options & LLDB_LOG_OPTION_APPEND)
14266b2e6765SJonas Devlieghere         flags |= File::eOpenOptionAppend;
14276b2e6765SJonas Devlieghere       else
14286b2e6765SJonas Devlieghere         flags |= File::eOpenOptionTruncate;
1429867c347cSRaphael Isemann       llvm::Expected<FileUP> file = FileSystem::Instance().Open(
14306b2e6765SJonas Devlieghere           FileSpec(log_file), flags, lldb::eFilePermissionsFileDefault, false);
14316b2e6765SJonas Devlieghere       if (!file) {
1432867c347cSRaphael Isemann         error_stream << "Unable to open log file '" << log_file
1433867c347cSRaphael Isemann                      << "': " << llvm::toString(file.takeError()) << "\n";
14345fae71c5SPavel Labath         return false;
14355fae71c5SPavel Labath       }
14366b2e6765SJonas Devlieghere 
14376b2e6765SJonas Devlieghere       log_stream_sp = std::make_shared<llvm::raw_fd_ostream>(
14386b2e6765SJonas Devlieghere           (*file)->GetDescriptor(), should_close, unbuffered);
1439228063cdSJim Ingham       m_log_streams[log_file] = log_stream_sp;
1440228063cdSJim Ingham     }
1441228063cdSJim Ingham   }
1442df370550SEugene Zelenko   assert(log_stream_sp);
1443228063cdSJim Ingham 
1444228063cdSJim Ingham   if (log_options == 0)
1445b9c1b51eSKate Stone     log_options =
1446b9c1b51eSKate Stone         LLDB_LOG_OPTION_PREPEND_THREAD_NAME | LLDB_LOG_OPTION_THREADSAFE;
1447228063cdSJim Ingham 
1448b9c1b51eSKate Stone   return Log::EnableLogChannel(log_stream_sp, log_options, channel, categories,
1449b9c1b51eSKate Stone                                error_stream);
1450228063cdSJim Ingham }
1451228063cdSJim Ingham 
1452bbf70c04SJonas Devlieghere ScriptInterpreter *
1453bbf70c04SJonas Devlieghere Debugger::GetScriptInterpreter(bool can_create,
1454bbf70c04SJonas Devlieghere                                llvm::Optional<lldb::ScriptLanguage> language) {
14552b29b432SJonas Devlieghere   std::lock_guard<std::recursive_mutex> locker(m_script_interpreter_mutex);
1456bbf70c04SJonas Devlieghere   lldb::ScriptLanguage script_language =
1457bbf70c04SJonas Devlieghere       language ? *language : GetScriptLanguage();
14582b29b432SJonas Devlieghere 
1459bbf70c04SJonas Devlieghere   if (!m_script_interpreters[script_language]) {
14602b29b432SJonas Devlieghere     if (!can_create)
14612b29b432SJonas Devlieghere       return nullptr;
1462bbf70c04SJonas Devlieghere     m_script_interpreters[script_language] =
1463bbf70c04SJonas Devlieghere         PluginManager::GetScriptInterpreterForLanguage(script_language, *this);
14642b29b432SJonas Devlieghere   }
14652b29b432SJonas Devlieghere 
1466bbf70c04SJonas Devlieghere   return m_script_interpreters[script_language].get();
14672b29b432SJonas Devlieghere }
14682b29b432SJonas Devlieghere 
1469b9c1b51eSKate Stone SourceManager &Debugger::GetSourceManager() {
1470d5b44036SJonas Devlieghere   if (!m_source_manager_up)
1471a8f3ae7cSJonas Devlieghere     m_source_manager_up = std::make_unique<SourceManager>(shared_from_this());
1472d5b44036SJonas Devlieghere   return *m_source_manager_up;
14739585fbfcSGreg Clayton }
14749585fbfcSGreg Clayton 
147544d93782SGreg Clayton // This function handles events that were broadcast by the process.
1476b9c1b51eSKate Stone void Debugger::HandleBreakpointEvent(const EventSP &event_sp) {
147744d93782SGreg Clayton   using namespace lldb;
1478b9c1b51eSKate Stone   const uint32_t event_type =
1479b9c1b51eSKate Stone       Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent(
1480b9c1b51eSKate Stone           event_sp);
148144d93782SGreg Clayton 
148244d93782SGreg Clayton   //    if (event_type & eBreakpointEventTypeAdded
148344d93782SGreg Clayton   //        || event_type & eBreakpointEventTypeRemoved
148444d93782SGreg Clayton   //        || event_type & eBreakpointEventTypeEnabled
148544d93782SGreg Clayton   //        || event_type & eBreakpointEventTypeDisabled
148644d93782SGreg Clayton   //        || event_type & eBreakpointEventTypeCommandChanged
148744d93782SGreg Clayton   //        || event_type & eBreakpointEventTypeConditionChanged
148844d93782SGreg Clayton   //        || event_type & eBreakpointEventTypeIgnoreChanged
148944d93782SGreg Clayton   //        || event_type & eBreakpointEventTypeLocationsResolved)
149044d93782SGreg Clayton   //    {
1491b9c1b51eSKate Stone   //        // Don't do anything about these events, since the breakpoint
1492b9c1b51eSKate Stone   //        commands already echo these actions.
149344d93782SGreg Clayton   //    }
149444d93782SGreg Clayton   //
1495b9c1b51eSKate Stone   if (event_type & eBreakpointEventTypeLocationsAdded) {
1496b9c1b51eSKate Stone     uint32_t num_new_locations =
1497b9c1b51eSKate Stone         Breakpoint::BreakpointEventData::GetNumBreakpointLocationsFromEvent(
1498b9c1b51eSKate Stone             event_sp);
1499b9c1b51eSKate Stone     if (num_new_locations > 0) {
1500b9c1b51eSKate Stone       BreakpointSP breakpoint =
1501b9c1b51eSKate Stone           Breakpoint::BreakpointEventData::GetBreakpointFromEvent(event_sp);
15024446487dSPavel Labath       StreamSP output_sp(GetAsyncOutputStream());
1503b9c1b51eSKate Stone       if (output_sp) {
150444d93782SGreg Clayton         output_sp->Printf("%d location%s added to breakpoint %d\n",
1505b9c1b51eSKate Stone                           num_new_locations, num_new_locations == 1 ? "" : "s",
150644d93782SGreg Clayton                           breakpoint->GetID());
15074446487dSPavel Labath         output_sp->Flush();
150844d93782SGreg Clayton       }
150944d93782SGreg Clayton     }
151044d93782SGreg Clayton   }
151144d93782SGreg Clayton   //    else if (event_type & eBreakpointEventTypeLocationsRemoved)
151244d93782SGreg Clayton   //    {
1513b9c1b51eSKate Stone   //        // These locations just get disabled, not sure it is worth spamming
1514b9c1b51eSKate Stone   //        folks about this on the command line.
151544d93782SGreg Clayton   //    }
151644d93782SGreg Clayton   //    else if (event_type & eBreakpointEventTypeLocationsResolved)
151744d93782SGreg Clayton   //    {
1518b9c1b51eSKate Stone   //        // This might be an interesting thing to note, but I'm going to
1519b9c1b51eSKate Stone   //        leave it quiet for now, it just looked noisy.
152044d93782SGreg Clayton   //    }
152144d93782SGreg Clayton }
152244d93782SGreg Clayton 
1523a9d58436SPavel Labath void Debugger::FlushProcessOutput(Process &process, bool flush_stdout,
1524a9d58436SPavel Labath                                   bool flush_stderr) {
1525a9d58436SPavel Labath   const auto &flush = [&](Stream &stream,
1526a9d58436SPavel Labath                           size_t (Process::*get)(char *, size_t, Status &)) {
152797206d57SZachary Turner     Status error;
152844d93782SGreg Clayton     size_t len;
1529a9d58436SPavel Labath     char buffer[1024];
1530a9d58436SPavel Labath     while ((len = (process.*get)(buffer, sizeof(buffer), error)) > 0)
1531a9d58436SPavel Labath       stream.Write(buffer, len);
1532a9d58436SPavel Labath     stream.Flush();
1533a9d58436SPavel Labath   };
153444d93782SGreg Clayton 
1535a9d58436SPavel Labath   std::lock_guard<std::mutex> guard(m_output_flush_mutex);
1536a9d58436SPavel Labath   if (flush_stdout)
1537a9d58436SPavel Labath     flush(*GetAsyncOutputStream(), &Process::GetSTDOUT);
1538a9d58436SPavel Labath   if (flush_stderr)
1539a9d58436SPavel Labath     flush(*GetAsyncErrorStream(), &Process::GetSTDERR);
154044d93782SGreg Clayton }
154144d93782SGreg Clayton 
154244d93782SGreg Clayton // This function handles events that were broadcast by the process.
1543b9c1b51eSKate Stone void Debugger::HandleProcessEvent(const EventSP &event_sp) {
154444d93782SGreg Clayton   using namespace lldb;
154544d93782SGreg Clayton   const uint32_t event_type = event_sp->GetType();
1546b9c1b51eSKate Stone   ProcessSP process_sp =
1547b9c1b51eSKate Stone       (event_type == Process::eBroadcastBitStructuredData)
154875930019STodd Fiala           ? EventDataStructuredData::GetProcessFromEvent(event_sp.get())
154975930019STodd Fiala           : Process::ProcessEventData::GetProcessFromEvent(event_sp.get());
155044d93782SGreg Clayton 
15514446487dSPavel Labath   StreamSP output_stream_sp = GetAsyncOutputStream();
15524446487dSPavel Labath   StreamSP error_stream_sp = GetAsyncErrorStream();
155344d93782SGreg Clayton   const bool gui_enabled = IsForwardingEvents();
155444d93782SGreg Clayton 
1555b9c1b51eSKate Stone   if (!gui_enabled) {
1556b4874f1aSGreg Clayton     bool pop_process_io_handler = false;
155744d93782SGreg Clayton     assert(process_sp);
155844d93782SGreg Clayton 
15594446487dSPavel Labath     bool state_is_stopped = false;
1560b9c1b51eSKate Stone     const bool got_state_changed =
1561b9c1b51eSKate Stone         (event_type & Process::eBroadcastBitStateChanged) != 0;
15624446487dSPavel Labath     const bool got_stdout = (event_type & Process::eBroadcastBitSTDOUT) != 0;
15634446487dSPavel Labath     const bool got_stderr = (event_type & Process::eBroadcastBitSTDERR) != 0;
1564b9c1b51eSKate Stone     const bool got_structured_data =
1565b9c1b51eSKate Stone         (event_type & Process::eBroadcastBitStructuredData) != 0;
156675930019STodd Fiala 
1567b9c1b51eSKate Stone     if (got_state_changed) {
1568b9c1b51eSKate Stone       StateType event_state =
1569b9c1b51eSKate Stone           Process::ProcessEventData::GetStateFromEvent(event_sp.get());
15704446487dSPavel Labath       state_is_stopped = StateIsStoppedState(event_state, false);
157144d93782SGreg Clayton     }
1572b4874f1aSGreg Clayton 
15734446487dSPavel Labath     // Display running state changes first before any STDIO
1574b9c1b51eSKate Stone     if (got_state_changed && !state_is_stopped) {
1575b9c1b51eSKate Stone       Process::HandleProcessStateChangedEvent(event_sp, output_stream_sp.get(),
1576b9c1b51eSKate Stone                                               pop_process_io_handler);
157744d93782SGreg Clayton     }
1578b4874f1aSGreg Clayton 
1579a9d58436SPavel Labath     // Now display STDOUT and STDERR
1580a9d58436SPavel Labath     FlushProcessOutput(*process_sp, got_stdout || got_state_changed,
1581a9d58436SPavel Labath                        got_stderr || got_state_changed);
1582b4874f1aSGreg Clayton 
158375930019STodd Fiala     // Give structured data events an opportunity to display.
1584b9c1b51eSKate Stone     if (got_structured_data) {
158575930019STodd Fiala       StructuredDataPluginSP plugin_sp =
158675930019STodd Fiala           EventDataStructuredData::GetPluginFromEvent(event_sp.get());
1587b9c1b51eSKate Stone       if (plugin_sp) {
158875930019STodd Fiala         auto structured_data_sp =
158975930019STodd Fiala             EventDataStructuredData::GetObjectFromEvent(event_sp.get());
1590b9c1b51eSKate Stone         if (output_stream_sp) {
159175930019STodd Fiala           StreamString content_stream;
159297206d57SZachary Turner           Status error =
1593b9c1b51eSKate Stone               plugin_sp->GetDescription(structured_data_sp, content_stream);
1594b9c1b51eSKate Stone           if (error.Success()) {
1595b9c1b51eSKate Stone             if (!content_stream.GetString().empty()) {
159675930019STodd Fiala               // Add newline.
159775930019STodd Fiala               content_stream.PutChar('\n');
159875930019STodd Fiala               content_stream.Flush();
159975930019STodd Fiala 
160075930019STodd Fiala               // Print it.
1601771ef6d4SMalcolm Parsons               output_stream_sp->PutCString(content_stream.GetString());
160275930019STodd Fiala             }
1603b9c1b51eSKate Stone           } else {
1604a3939e15SPavel Labath             error_stream_sp->Format("Failed to print structured "
1605a3939e15SPavel Labath                                     "data with plugin {0}: {1}",
1606a3939e15SPavel Labath                                     plugin_sp->GetPluginName(), error);
160775930019STodd Fiala           }
160875930019STodd Fiala         }
160975930019STodd Fiala       }
161075930019STodd Fiala     }
161175930019STodd Fiala 
16124446487dSPavel Labath     // Now display any stopped state changes after any STDIO
1613b9c1b51eSKate Stone     if (got_state_changed && state_is_stopped) {
1614b9c1b51eSKate Stone       Process::HandleProcessStateChangedEvent(event_sp, output_stream_sp.get(),
1615b9c1b51eSKate Stone                                               pop_process_io_handler);
161644d93782SGreg Clayton     }
161744d93782SGreg Clayton 
16184446487dSPavel Labath     output_stream_sp->Flush();
16194446487dSPavel Labath     error_stream_sp->Flush();
162044d93782SGreg Clayton 
1621b4874f1aSGreg Clayton     if (pop_process_io_handler)
1622b4874f1aSGreg Clayton       process_sp->PopProcessIOHandler();
1623b4874f1aSGreg Clayton   }
1624b4874f1aSGreg Clayton }
1625b4874f1aSGreg Clayton 
1626b9c1b51eSKate Stone void Debugger::HandleThreadEvent(const EventSP &event_sp) {
162705097246SAdrian Prantl   // At present the only thread event we handle is the Frame Changed event, and
162805097246SAdrian Prantl   // all we do for that is just reprint the thread status for that thread.
162944d93782SGreg Clayton   using namespace lldb;
163044d93782SGreg Clayton   const uint32_t event_type = event_sp->GetType();
16316a9767c7SJim Ingham   const bool stop_format = true;
163244d93782SGreg Clayton   if (event_type == Thread::eBroadcastBitStackChanged ||
1633b9c1b51eSKate Stone       event_type == Thread::eBroadcastBitThreadSelected) {
1634b9c1b51eSKate Stone     ThreadSP thread_sp(
1635b9c1b51eSKate Stone         Thread::ThreadEventData::GetThreadFromEvent(event_sp.get()));
1636b9c1b51eSKate Stone     if (thread_sp) {
16376a9767c7SJim Ingham       thread_sp->GetStatus(*GetAsyncOutputStream(), 0, 1, 1, stop_format);
163844d93782SGreg Clayton     }
163944d93782SGreg Clayton   }
164044d93782SGreg Clayton }
164144d93782SGreg Clayton 
1642b9c1b51eSKate Stone bool Debugger::IsForwardingEvents() { return (bool)m_forward_listener_sp; }
164344d93782SGreg Clayton 
1644b9c1b51eSKate Stone void Debugger::EnableForwardEvents(const ListenerSP &listener_sp) {
164544d93782SGreg Clayton   m_forward_listener_sp = listener_sp;
164644d93782SGreg Clayton }
164744d93782SGreg Clayton 
1648b9c1b51eSKate Stone void Debugger::CancelForwardEvents(const ListenerSP &listener_sp) {
164944d93782SGreg Clayton   m_forward_listener_sp.reset();
165044d93782SGreg Clayton }
165144d93782SGreg Clayton 
1652d0810779SPavel Labath lldb::thread_result_t Debugger::DefaultEventHandler() {
1653583bbb1dSJim Ingham   ListenerSP listener_sp(GetListener());
165444d93782SGreg Clayton   ConstString broadcaster_class_target(Target::GetStaticBroadcasterClass());
165544d93782SGreg Clayton   ConstString broadcaster_class_process(Process::GetStaticBroadcasterClass());
165644d93782SGreg Clayton   ConstString broadcaster_class_thread(Thread::GetStaticBroadcasterClass());
165744d93782SGreg Clayton   BroadcastEventSpec target_event_spec(broadcaster_class_target,
165844d93782SGreg Clayton                                        Target::eBroadcastBitBreakpointChanged);
165944d93782SGreg Clayton 
1660b9c1b51eSKate Stone   BroadcastEventSpec process_event_spec(
1661b9c1b51eSKate Stone       broadcaster_class_process,
1662b9c1b51eSKate Stone       Process::eBroadcastBitStateChanged | Process::eBroadcastBitSTDOUT |
1663b9c1b51eSKate Stone           Process::eBroadcastBitSTDERR | Process::eBroadcastBitStructuredData);
166444d93782SGreg Clayton 
166544d93782SGreg Clayton   BroadcastEventSpec thread_event_spec(broadcaster_class_thread,
166644d93782SGreg Clayton                                        Thread::eBroadcastBitStackChanged |
166744d93782SGreg Clayton                                            Thread::eBroadcastBitThreadSelected);
166844d93782SGreg Clayton 
1669b9c1b51eSKate Stone   listener_sp->StartListeningForEventSpec(m_broadcaster_manager_sp,
1670b9c1b51eSKate Stone                                           target_event_spec);
1671b9c1b51eSKate Stone   listener_sp->StartListeningForEventSpec(m_broadcaster_manager_sp,
1672b9c1b51eSKate Stone                                           process_event_spec);
1673b9c1b51eSKate Stone   listener_sp->StartListeningForEventSpec(m_broadcaster_manager_sp,
1674b9c1b51eSKate Stone                                           thread_event_spec);
1675b9c1b51eSKate Stone   listener_sp->StartListeningForEvents(
1676d5b44036SJonas Devlieghere       m_command_interpreter_up.get(),
167744d93782SGreg Clayton       CommandInterpreter::eBroadcastBitQuitCommandReceived |
167844d93782SGreg Clayton           CommandInterpreter::eBroadcastBitAsynchronousOutputData |
167944d93782SGreg Clayton           CommandInterpreter::eBroadcastBitAsynchronousErrorData);
168044d93782SGreg Clayton 
1681*2fc38b2bSJonas Devlieghere   listener_sp->StartListeningForEvents(
1682*2fc38b2bSJonas Devlieghere       &m_broadcaster,
1683*2fc38b2bSJonas Devlieghere       eBroadcastBitProgress | eBroadcastBitWarning | eBroadcastBitError);
16845a27b998SJonas Devlieghere 
168505097246SAdrian Prantl   // Let the thread that spawned us know that we have started up and that we
168605097246SAdrian Prantl   // are now listening to all required events so no events get missed
1687afa91e33SGreg Clayton   m_sync_broadcaster.BroadcastEvent(eBroadcastBitEventThreadIsListening);
1688afa91e33SGreg Clayton 
168944d93782SGreg Clayton   bool done = false;
1690b9c1b51eSKate Stone   while (!done) {
169144d93782SGreg Clayton     EventSP event_sp;
1692d35031e1SPavel Labath     if (listener_sp->GetEvent(event_sp, llvm::None)) {
1693b9c1b51eSKate Stone       if (event_sp) {
169444d93782SGreg Clayton         Broadcaster *broadcaster = event_sp->GetBroadcaster();
1695b9c1b51eSKate Stone         if (broadcaster) {
169644d93782SGreg Clayton           uint32_t event_type = event_sp->GetType();
169744d93782SGreg Clayton           ConstString broadcaster_class(broadcaster->GetBroadcasterClass());
1698b9c1b51eSKate Stone           if (broadcaster_class == broadcaster_class_process) {
169944d93782SGreg Clayton             HandleProcessEvent(event_sp);
1700b9c1b51eSKate Stone           } else if (broadcaster_class == broadcaster_class_target) {
1701b9c1b51eSKate Stone             if (Breakpoint::BreakpointEventData::GetEventDataFromEvent(
1702b9c1b51eSKate Stone                     event_sp.get())) {
170344d93782SGreg Clayton               HandleBreakpointEvent(event_sp);
170444d93782SGreg Clayton             }
1705b9c1b51eSKate Stone           } else if (broadcaster_class == broadcaster_class_thread) {
170644d93782SGreg Clayton             HandleThreadEvent(event_sp);
1707d5b44036SJonas Devlieghere           } else if (broadcaster == m_command_interpreter_up.get()) {
1708b9c1b51eSKate Stone             if (event_type &
1709b9c1b51eSKate Stone                 CommandInterpreter::eBroadcastBitQuitCommandReceived) {
171044d93782SGreg Clayton               done = true;
1711b9c1b51eSKate Stone             } else if (event_type &
1712b9c1b51eSKate Stone                        CommandInterpreter::eBroadcastBitAsynchronousErrorData) {
171365fdb342SRaphael Isemann               const char *data = static_cast<const char *>(
1714b9c1b51eSKate Stone                   EventDataBytes::GetBytesFromEvent(event_sp.get()));
1715b9c1b51eSKate Stone               if (data && data[0]) {
17164446487dSPavel Labath                 StreamSP error_sp(GetAsyncErrorStream());
1717b9c1b51eSKate Stone                 if (error_sp) {
171844d93782SGreg Clayton                   error_sp->PutCString(data);
171944d93782SGreg Clayton                   error_sp->Flush();
172044d93782SGreg Clayton                 }
172144d93782SGreg Clayton               }
1722b9c1b51eSKate Stone             } else if (event_type & CommandInterpreter::
1723b9c1b51eSKate Stone                                         eBroadcastBitAsynchronousOutputData) {
172465fdb342SRaphael Isemann               const char *data = static_cast<const char *>(
1725b9c1b51eSKate Stone                   EventDataBytes::GetBytesFromEvent(event_sp.get()));
1726b9c1b51eSKate Stone               if (data && data[0]) {
17274446487dSPavel Labath                 StreamSP output_sp(GetAsyncOutputStream());
1728b9c1b51eSKate Stone                 if (output_sp) {
172944d93782SGreg Clayton                   output_sp->PutCString(data);
173044d93782SGreg Clayton                   output_sp->Flush();
173144d93782SGreg Clayton                 }
173244d93782SGreg Clayton               }
173344d93782SGreg Clayton             }
17345a27b998SJonas Devlieghere           } else if (broadcaster == &m_broadcaster) {
17355a27b998SJonas Devlieghere             if (event_type & Debugger::eBroadcastBitProgress)
17365a27b998SJonas Devlieghere               HandleProgressEvent(event_sp);
1737*2fc38b2bSJonas Devlieghere             else if (event_type & Debugger::eBroadcastBitWarning)
1738*2fc38b2bSJonas Devlieghere               HandleDiagnosticEvent(event_sp);
1739*2fc38b2bSJonas Devlieghere             else if (event_type & Debugger::eBroadcastBitError)
1740*2fc38b2bSJonas Devlieghere               HandleDiagnosticEvent(event_sp);
174144d93782SGreg Clayton           }
174244d93782SGreg Clayton         }
174344d93782SGreg Clayton 
174444d93782SGreg Clayton         if (m_forward_listener_sp)
174544d93782SGreg Clayton           m_forward_listener_sp->AddEvent(event_sp);
174644d93782SGreg Clayton       }
174744d93782SGreg Clayton     }
174844d93782SGreg Clayton   }
174985200645SKonrad Kleine   return {};
175044d93782SGreg Clayton }
175144d93782SGreg Clayton 
1752b9c1b51eSKate Stone bool Debugger::StartEventHandlerThread() {
1753b9c1b51eSKate Stone   if (!m_event_handler_thread.IsJoinable()) {
175405097246SAdrian Prantl     // We must synchronize with the DefaultEventHandler() thread to ensure it
175505097246SAdrian Prantl     // is up and running and listening to events before we return from this
175605097246SAdrian Prantl     // function. We do this by listening to events for the
1757afa91e33SGreg Clayton     // eBroadcastBitEventThreadIsListening from the m_sync_broadcaster
17581a728f66STatyana Krasnukha     ConstString full_name("lldb.debugger.event-handler");
17591a728f66STatyana Krasnukha     ListenerSP listener_sp(Listener::MakeListener(full_name.AsCString()));
1760b9c1b51eSKate Stone     listener_sp->StartListeningForEvents(&m_sync_broadcaster,
1761b9c1b51eSKate Stone                                          eBroadcastBitEventThreadIsListening);
1762afa91e33SGreg Clayton 
1763642bc15dSRaphael Isemann     llvm::StringRef thread_name =
1764e063ecccSJonas Devlieghere         full_name.GetLength() < llvm::get_max_thread_name_length()
1765642bc15dSRaphael Isemann             ? full_name.GetStringRef()
1766e063ecccSJonas Devlieghere             : "dbg.evt-handler";
17671a728f66STatyana Krasnukha 
17687c2896a2SZachary Turner     // Use larger 8MB stack for this thread
1769f39c2e18SJonas Devlieghere     llvm::Expected<HostThread> event_handler_thread =
1770d0810779SPavel Labath         ThreadLauncher::LaunchThread(
1771d0810779SPavel Labath             thread_name, [this] { return DefaultEventHandler(); },
1772f39c2e18SJonas Devlieghere             g_debugger_event_thread_stack_bytes);
1773f39c2e18SJonas Devlieghere 
1774f39c2e18SJonas Devlieghere     if (event_handler_thread) {
1775f39c2e18SJonas Devlieghere       m_event_handler_thread = *event_handler_thread;
1776f39c2e18SJonas Devlieghere     } else {
1777a007a6d8SPavel Labath       LLDB_LOG(GetLog(LLDBLog::Host), "failed to launch host thread: {}",
1778f39c2e18SJonas Devlieghere                llvm::toString(event_handler_thread.takeError()));
1779f39c2e18SJonas Devlieghere     }
1780afa91e33SGreg Clayton 
178105097246SAdrian Prantl     // Make sure DefaultEventHandler() is running and listening to events
178205097246SAdrian Prantl     // before we return from this function. We are only listening for events of
178305097246SAdrian Prantl     // type eBroadcastBitEventThreadIsListening so we don't need to check the
178405097246SAdrian Prantl     // event, we just need to wait an infinite amount of time for it (nullptr
178505097246SAdrian Prantl     // timeout as the first parameter)
1786afa91e33SGreg Clayton     lldb::EventSP event_sp;
1787d35031e1SPavel Labath     listener_sp->GetEvent(event_sp, llvm::None);
1788807b6b32SGreg Clayton   }
1789acee96aeSZachary Turner   return m_event_handler_thread.IsJoinable();
179044d93782SGreg Clayton }
179144d93782SGreg Clayton 
1792b9c1b51eSKate Stone void Debugger::StopEventHandlerThread() {
1793b9c1b51eSKate Stone   if (m_event_handler_thread.IsJoinable()) {
1794b9c1b51eSKate Stone     GetCommandInterpreter().BroadcastEvent(
1795b9c1b51eSKate Stone         CommandInterpreter::eBroadcastBitQuitCommandReceived);
179639de3110SZachary Turner     m_event_handler_thread.Join(nullptr);
179744d93782SGreg Clayton   }
179844d93782SGreg Clayton }
179944d93782SGreg Clayton 
1800d0810779SPavel Labath lldb::thread_result_t Debugger::IOHandlerThread() {
1801d0810779SPavel Labath   RunIOHandlers();
1802d0810779SPavel Labath   StopEventHandlerThread();
180385200645SKonrad Kleine   return {};
180444d93782SGreg Clayton }
180544d93782SGreg Clayton 
18065a27b998SJonas Devlieghere void Debugger::HandleProgressEvent(const lldb::EventSP &event_sp) {
18075e65e79bSJonas Devlieghere   auto *data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
18085a27b998SJonas Devlieghere   if (!data)
18095a27b998SJonas Devlieghere     return;
18105a27b998SJonas Devlieghere 
18115a27b998SJonas Devlieghere   // Do some bookkeeping for the current event, regardless of whether we're
18125a27b998SJonas Devlieghere   // going to show the progress.
18135a27b998SJonas Devlieghere   const uint64_t id = data->GetID();
18145a27b998SJonas Devlieghere   if (m_current_event_id) {
18155a27b998SJonas Devlieghere     if (id != *m_current_event_id)
18165a27b998SJonas Devlieghere       return;
18175a27b998SJonas Devlieghere     if (data->GetCompleted())
18185a27b998SJonas Devlieghere       m_current_event_id.reset();
18195a27b998SJonas Devlieghere   } else {
18205a27b998SJonas Devlieghere     m_current_event_id = id;
18215a27b998SJonas Devlieghere   }
18225a27b998SJonas Devlieghere 
18235a27b998SJonas Devlieghere   // Decide whether we actually are going to show the progress. This decision
18245a27b998SJonas Devlieghere   // can change between iterations so check it inside the loop.
18255a27b998SJonas Devlieghere   if (!GetShowProgress())
18265a27b998SJonas Devlieghere     return;
18275a27b998SJonas Devlieghere 
18285a27b998SJonas Devlieghere   // Determine whether the current output file is an interactive terminal with
18295a27b998SJonas Devlieghere   // color support. We assume that if we support ANSI escape codes we support
18305a27b998SJonas Devlieghere   // vt100 escape codes.
1831c231deb7SJonas Devlieghere   File &file = GetOutputFile();
1832c231deb7SJonas Devlieghere   if (!file.GetIsInteractive() || !file.GetIsTerminalWithColors())
18335a27b998SJonas Devlieghere     return;
18345a27b998SJonas Devlieghere 
1835c231deb7SJonas Devlieghere   StreamSP output = GetAsyncOutputStream();
1836c231deb7SJonas Devlieghere 
1837e618eb87SJonas Devlieghere   // Print over previous line, if any.
1838c231deb7SJonas Devlieghere   output->Printf("\r");
1839e618eb87SJonas Devlieghere 
18405a27b998SJonas Devlieghere   if (data->GetCompleted()) {
18415a27b998SJonas Devlieghere     // Clear the current line.
1842c231deb7SJonas Devlieghere     output->Printf("\x1B[2K");
1843c231deb7SJonas Devlieghere     output->Flush();
18445a27b998SJonas Devlieghere     return;
18455a27b998SJonas Devlieghere   }
18465a27b998SJonas Devlieghere 
1847097d46f4SJonas Devlieghere   const bool use_color = GetUseColor();
1848097d46f4SJonas Devlieghere   llvm::StringRef ansi_prefix = GetShowProgressAnsiPrefix();
1849097d46f4SJonas Devlieghere   if (!ansi_prefix.empty())
1850c231deb7SJonas Devlieghere     output->Printf(
1851097d46f4SJonas Devlieghere         "%s", ansi::FormatAnsiTerminalCodes(ansi_prefix, use_color).c_str());
1852097d46f4SJonas Devlieghere 
18535a27b998SJonas Devlieghere   // Print the progress message.
18545a27b998SJonas Devlieghere   std::string message = data->GetMessage();
18555a27b998SJonas Devlieghere   if (data->GetTotal() != UINT64_MAX) {
1856c231deb7SJonas Devlieghere     output->Printf("[%" PRIu64 "/%" PRIu64 "] %s...", data->GetCompleted(),
1857c231deb7SJonas Devlieghere                    data->GetTotal(), message.c_str());
18585a27b998SJonas Devlieghere   } else {
1859c231deb7SJonas Devlieghere     output->Printf("%s...", message.c_str());
18605a27b998SJonas Devlieghere   }
18615a27b998SJonas Devlieghere 
1862097d46f4SJonas Devlieghere   llvm::StringRef ansi_suffix = GetShowProgressAnsiSuffix();
1863097d46f4SJonas Devlieghere   if (!ansi_suffix.empty())
1864c231deb7SJonas Devlieghere     output->Printf(
1865097d46f4SJonas Devlieghere         "%s", ansi::FormatAnsiTerminalCodes(ansi_suffix, use_color).c_str());
1866097d46f4SJonas Devlieghere 
18675a27b998SJonas Devlieghere   // Clear until the end of the line.
1868c231deb7SJonas Devlieghere   output->Printf("\x1B[K\r");
18695a27b998SJonas Devlieghere 
18705a27b998SJonas Devlieghere   // Flush the output.
1871c231deb7SJonas Devlieghere   output->Flush();
18725a27b998SJonas Devlieghere }
18735a27b998SJonas Devlieghere 
1874*2fc38b2bSJonas Devlieghere void Debugger::HandleDiagnosticEvent(const lldb::EventSP &event_sp) {
1875*2fc38b2bSJonas Devlieghere   auto *data = DiagnosticEventData::GetEventDataFromEvent(event_sp.get());
1876*2fc38b2bSJonas Devlieghere   if (!data)
1877*2fc38b2bSJonas Devlieghere     return;
1878*2fc38b2bSJonas Devlieghere 
1879*2fc38b2bSJonas Devlieghere   StreamSP stream = GetAsyncErrorStream();
1880*2fc38b2bSJonas Devlieghere   data->Dump(stream.get());
1881*2fc38b2bSJonas Devlieghere }
1882*2fc38b2bSJonas Devlieghere 
1883b9c1b51eSKate Stone bool Debugger::HasIOHandlerThread() { return m_io_handler_thread.IsJoinable(); }
18846681041dSSean Callanan 
1885b9c1b51eSKate Stone bool Debugger::StartIOHandlerThread() {
1886f39c2e18SJonas Devlieghere   if (!m_io_handler_thread.IsJoinable()) {
1887f39c2e18SJonas Devlieghere     llvm::Expected<HostThread> io_handler_thread = ThreadLauncher::LaunchThread(
1888d0810779SPavel Labath         "lldb.debugger.io-handler", [this] { return IOHandlerThread(); },
1889807b6b32SGreg Clayton         8 * 1024 * 1024); // Use larger 8MB stack for this thread
1890f39c2e18SJonas Devlieghere     if (io_handler_thread) {
1891f39c2e18SJonas Devlieghere       m_io_handler_thread = *io_handler_thread;
1892f39c2e18SJonas Devlieghere     } else {
1893a007a6d8SPavel Labath       LLDB_LOG(GetLog(LLDBLog::Host), "failed to launch host thread: {}",
1894f39c2e18SJonas Devlieghere                llvm::toString(io_handler_thread.takeError()));
1895f39c2e18SJonas Devlieghere     }
1896f39c2e18SJonas Devlieghere   }
1897acee96aeSZachary Turner   return m_io_handler_thread.IsJoinable();
189844d93782SGreg Clayton }
189944d93782SGreg Clayton 
1900b9c1b51eSKate Stone void Debugger::StopIOHandlerThread() {
1901b9c1b51eSKate Stone   if (m_io_handler_thread.IsJoinable()) {
19027ca15ba7SLawrence D'Anna     GetInputFile().Close();
190339de3110SZachary Turner     m_io_handler_thread.Join(nullptr);
190444d93782SGreg Clayton   }
190544d93782SGreg Clayton }
190644d93782SGreg Clayton 
1907b9c1b51eSKate Stone void Debugger::JoinIOHandlerThread() {
1908b9c1b51eSKate Stone   if (HasIOHandlerThread()) {
19096681041dSSean Callanan     thread_result_t result;
19106681041dSSean Callanan     m_io_handler_thread.Join(&result);
19116681041dSSean Callanan     m_io_handler_thread = LLDB_INVALID_HOST_THREAD;
19126681041dSSean Callanan   }
19136681041dSSean Callanan }
19146681041dSSean Callanan 
1915b2fa3b92SJonas Devlieghere Target &Debugger::GetSelectedOrDummyTarget(bool prefer_dummy) {
1916b9c1b51eSKate Stone   if (!prefer_dummy) {
1917b2fa3b92SJonas Devlieghere     if (TargetSP target = m_target_list.GetSelectedTarget())
1918b2fa3b92SJonas Devlieghere       return *target;
191933df7cd3SJim Ingham   }
1920893c932aSJim Ingham   return GetDummyTarget();
1921893c932aSJim Ingham }
192244d93782SGreg Clayton 
192397206d57SZachary Turner Status Debugger::RunREPL(LanguageType language, const char *repl_options) {
192497206d57SZachary Turner   Status err;
19253e7e915dSSean Callanan   FileSpec repl_executable;
19263e7e915dSSean Callanan 
192746a28a95SJonas Devlieghere   if (language == eLanguageTypeUnknown)
192846a28a95SJonas Devlieghere     language = GetREPLLanguage();
192946a28a95SJonas Devlieghere 
1930b9c1b51eSKate Stone   if (language == eLanguageTypeUnknown) {
1931aa97a89dSAdrian Prantl     LanguageSet repl_languages = Language::GetLanguagesSupportingREPLs();
193297f84e87SSean Callanan 
1933aa97a89dSAdrian Prantl     if (auto single_lang = repl_languages.GetSingularLanguage()) {
1934aa97a89dSAdrian Prantl       language = *single_lang;
1935aa97a89dSAdrian Prantl     } else if (repl_languages.Empty()) {
193646a28a95SJonas Devlieghere       err.SetErrorString(
1937b9c1b51eSKate Stone           "LLDB isn't configured with REPL support for any languages.");
193897f84e87SSean Callanan       return err;
1939b9c1b51eSKate Stone     } else {
194046a28a95SJonas Devlieghere       err.SetErrorString(
1941b9c1b51eSKate Stone           "Multiple possible REPL languages.  Please specify a language.");
194297f84e87SSean Callanan       return err;
194397f84e87SSean Callanan     }
194497f84e87SSean Callanan   }
194597f84e87SSean Callanan 
1946b9c1b51eSKate Stone   Target *const target =
1947b9c1b51eSKate Stone       nullptr; // passing in an empty target means the REPL must create one
19483e7e915dSSean Callanan 
19493b682de6SSean Callanan   REPLSP repl_sp(REPL::Create(err, language, this, target, repl_options));
19503e7e915dSSean Callanan 
1951b9c1b51eSKate Stone   if (!err.Success()) {
19523e7e915dSSean Callanan     return err;
19533e7e915dSSean Callanan   }
19543e7e915dSSean Callanan 
1955b9c1b51eSKate Stone   if (!repl_sp) {
1956b9c1b51eSKate Stone     err.SetErrorStringWithFormat("couldn't find a REPL for %s",
1957b9c1b51eSKate Stone                                  Language::GetNameForLanguageType(language));
19583e7e915dSSean Callanan     return err;
19593e7e915dSSean Callanan   }
19603e7e915dSSean Callanan 
19613e7e915dSSean Callanan   repl_sp->SetCompilerOptions(repl_options);
19623e7e915dSSean Callanan   repl_sp->RunLoop();
19633e7e915dSSean Callanan 
19643e7e915dSSean Callanan   return err;
19653e7e915dSSean Callanan }
1966