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"
54bf9a7730SZachary Turner #include "lldb/Utility/StreamString.h"
552f3df613SZachary Turner 
56b1cb0b79SNico Weber #if defined(_WIN32)
57672d2c12SJonas Devlieghere #include "lldb/Host/windows/PosixApi.h"
588aa23614SDavid Bolvansky #include "lldb/Host/windows/windows.h"
592f3df613SZachary Turner #endif
602f3df613SZachary Turner 
61672d2c12SJonas Devlieghere #include "llvm/ADT/None.h"
62672d2c12SJonas Devlieghere #include "llvm/ADT/STLExtras.h"
632f3df613SZachary Turner #include "llvm/ADT/StringRef.h"
64672d2c12SJonas Devlieghere #include "llvm/ADT/iterator.h"
652f3df613SZachary Turner #include "llvm/Support/DynamicLibrary.h"
662f3df613SZachary Turner #include "llvm/Support/FileSystem.h"
678aa23614SDavid Bolvansky #include "llvm/Support/Process.h"
6820048f31SLuboš Luňák #include "llvm/Support/ThreadPool.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 
SetPropertyValue(const ExecutionContext * exe_ctx,VarSetOperationType op,llvm::StringRef property_path,llvm::StringRef value)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 
GetAutoConfirm() const253b9c1b51eSKate 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 
GetDisassemblyFormat() const259b9c1b51eSKate 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 
GetFrameFormat() const264b9c1b51eSKate 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 
GetFrameFormatUnique() const2697f1c1211SPavel 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 
GetStopDisassemblyMaxSize() const274b889ef42SMed 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 
GetNotifyVoid() const280b9c1b51eSKate 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 
GetPrompt() const286514d8cd8SZachary 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 
SetPrompt(llvm::StringRef p)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 
GetReproducerPath() const3039e046f02SJonas Devlieghere llvm::StringRef Debugger::GetReproducerPath() const {
3049e046f02SJonas Devlieghere   auto &r = repro::Reproducer::Instance();
305*1b4b12a3SNico Weber   return r.GetReproducerPath().GetCString();
3069e046f02SJonas Devlieghere }
3079e046f02SJonas Devlieghere 
GetThreadFormat() const308b9c1b51eSKate 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 
GetThreadStopFormat() const3136a9767c7SJim 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 
GetScriptLanguage() const318b9c1b51eSKate 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 
SetScriptLanguage(lldb::ScriptLanguage script_lang)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 
GetREPLLanguage() const33046a28a95SJonas 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 
SetREPLLanguage(lldb::LanguageType repl_lang)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 
GetTerminalWidth() const344b9c1b51eSKate 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 
SetTerminalWidth(uint32_t term_width)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 
GetUseExternalEditor() const358b9c1b51eSKate 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 
SetUseExternalEditor(bool b)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 
GetUseColor() const369b9c1b51eSKate 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 
SetUseColor(bool b)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 
GetShowProgress() const3825a27b998SJonas 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 
SetShowProgress(bool show_progress)388cbcb3bceSJonas Devlieghere bool Debugger::SetShowProgress(bool show_progress) {
389cbcb3bceSJonas Devlieghere   const uint32_t idx = ePropertyShowProgress;
390cbcb3bceSJonas Devlieghere   return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx,
391cbcb3bceSJonas Devlieghere                                                       show_progress);
392cbcb3bceSJonas Devlieghere }
393cbcb3bceSJonas Devlieghere 
GetShowProgressAnsiPrefix() const394097d46f4SJonas Devlieghere llvm::StringRef Debugger::GetShowProgressAnsiPrefix() const {
395097d46f4SJonas Devlieghere   const uint32_t idx = ePropertyShowProgressAnsiPrefix;
396097d46f4SJonas Devlieghere   return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, "");
397097d46f4SJonas Devlieghere }
398097d46f4SJonas Devlieghere 
GetShowProgressAnsiSuffix() const399097d46f4SJonas Devlieghere llvm::StringRef Debugger::GetShowProgressAnsiSuffix() const {
400097d46f4SJonas Devlieghere   const uint32_t idx = ePropertyShowProgressAnsiSuffix;
401097d46f4SJonas Devlieghere   return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, "");
402097d46f4SJonas Devlieghere }
403097d46f4SJonas Devlieghere 
GetUseAutosuggestion() const404de9e8502SShu Anzai bool Debugger::GetUseAutosuggestion() const {
405de9e8502SShu Anzai   const uint32_t idx = ePropertyShowAutosuggestion;
406de9e8502SShu Anzai   return m_collection_sp->GetPropertyAtIndexAsBoolean(
407de9e8502SShu Anzai       nullptr, idx, g_debugger_properties[idx].default_uint_value != 0);
408de9e8502SShu Anzai }
409de9e8502SShu Anzai 
GetAutosuggestionAnsiPrefix() const410080635efSJonas Devlieghere llvm::StringRef Debugger::GetAutosuggestionAnsiPrefix() const {
411080635efSJonas Devlieghere   const uint32_t idx = ePropertyShowAutosuggestionAnsiPrefix;
412080635efSJonas Devlieghere   return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, "");
413080635efSJonas Devlieghere }
414080635efSJonas Devlieghere 
GetAutosuggestionAnsiSuffix() const415080635efSJonas Devlieghere llvm::StringRef Debugger::GetAutosuggestionAnsiSuffix() const {
416080635efSJonas Devlieghere   const uint32_t idx = ePropertyShowAutosuggestionAnsiSuffix;
417080635efSJonas Devlieghere   return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, "");
418080635efSJonas Devlieghere }
419080635efSJonas Devlieghere 
GetUseSourceCache() const420acae69d0SEmre Kultursay bool Debugger::GetUseSourceCache() const {
421acae69d0SEmre Kultursay   const uint32_t idx = ePropertyUseSourceCache;
422acae69d0SEmre Kultursay   return m_collection_sp->GetPropertyAtIndexAsBoolean(
423acae69d0SEmre Kultursay       nullptr, idx, g_debugger_properties[idx].default_uint_value != 0);
424acae69d0SEmre Kultursay }
425acae69d0SEmre Kultursay 
SetUseSourceCache(bool b)426acae69d0SEmre Kultursay bool Debugger::SetUseSourceCache(bool b) {
427acae69d0SEmre Kultursay   const uint32_t idx = ePropertyUseSourceCache;
428acae69d0SEmre Kultursay   bool ret = m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
429acae69d0SEmre Kultursay   if (!ret) {
430acae69d0SEmre Kultursay     m_source_file_cache.Clear();
431acae69d0SEmre Kultursay   }
432acae69d0SEmre Kultursay   return ret;
433acae69d0SEmre Kultursay }
GetHighlightSource() const434566afa0aSRaphael Isemann bool Debugger::GetHighlightSource() const {
435566afa0aSRaphael Isemann   const uint32_t idx = ePropertyHighlightSource;
436566afa0aSRaphael Isemann   return m_collection_sp->GetPropertyAtIndexAsBoolean(
437a8ea5955SJonas Devlieghere       nullptr, idx, g_debugger_properties[idx].default_uint_value);
438566afa0aSRaphael Isemann }
439566afa0aSRaphael Isemann 
GetStopShowColumn() const4409666ba75STodd Fiala StopShowColumn Debugger::GetStopShowColumn() const {
4419666ba75STodd Fiala   const uint32_t idx = ePropertyStopShowColumn;
4429666ba75STodd Fiala   return (lldb::StopShowColumn)m_collection_sp->GetPropertyAtIndexAsEnumeration(
443a8ea5955SJonas Devlieghere       nullptr, idx, g_debugger_properties[idx].default_uint_value);
4449666ba75STodd Fiala }
4459666ba75STodd Fiala 
GetStopShowColumnAnsiPrefix() const44620786326SRaphael Isemann llvm::StringRef Debugger::GetStopShowColumnAnsiPrefix() const {
4479666ba75STodd Fiala   const uint32_t idx = ePropertyStopShowColumnAnsiPrefix;
44820786326SRaphael Isemann   return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, "");
4499666ba75STodd Fiala }
4509666ba75STodd Fiala 
GetStopShowColumnAnsiSuffix() const45120786326SRaphael Isemann llvm::StringRef Debugger::GetStopShowColumnAnsiSuffix() const {
4529666ba75STodd Fiala   const uint32_t idx = ePropertyStopShowColumnAnsiSuffix;
45320786326SRaphael Isemann   return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, "");
4549666ba75STodd Fiala }
4559666ba75STodd Fiala 
GetStopShowLineMarkerAnsiPrefix() const456841be985SJonas Devlieghere llvm::StringRef Debugger::GetStopShowLineMarkerAnsiPrefix() const {
457841be985SJonas Devlieghere   const uint32_t idx = ePropertyStopShowLineMarkerAnsiPrefix;
458841be985SJonas Devlieghere   return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, "");
459841be985SJonas Devlieghere }
460841be985SJonas Devlieghere 
GetStopShowLineMarkerAnsiSuffix() const461841be985SJonas Devlieghere llvm::StringRef Debugger::GetStopShowLineMarkerAnsiSuffix() const {
462841be985SJonas Devlieghere   const uint32_t idx = ePropertyStopShowLineMarkerAnsiSuffix;
463841be985SJonas Devlieghere   return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, "");
464841be985SJonas Devlieghere }
465841be985SJonas Devlieghere 
GetStopSourceLineCount(bool before) const466b9c1b51eSKate Stone uint32_t Debugger::GetStopSourceLineCount(bool before) const {
467b9c1b51eSKate Stone   const uint32_t idx =
468b9c1b51eSKate Stone       before ? ePropertyStopLineCountBefore : ePropertyStopLineCountAfter;
469b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsSInt64(
470a8ea5955SJonas Devlieghere       nullptr, idx, g_debugger_properties[idx].default_uint_value);
47167cc0636SGreg Clayton }
47267cc0636SGreg Clayton 
GetStopDisassemblyDisplay() const473b9c1b51eSKate Stone Debugger::StopDisassemblyType Debugger::GetStopDisassemblyDisplay() const {
47467cc0636SGreg Clayton   const uint32_t idx = ePropertyStopDisassemblyDisplay;
475b9c1b51eSKate Stone   return (Debugger::StopDisassemblyType)
476b9c1b51eSKate Stone       m_collection_sp->GetPropertyAtIndexAsEnumeration(
477a8ea5955SJonas Devlieghere           nullptr, idx, g_debugger_properties[idx].default_uint_value);
47867cc0636SGreg Clayton }
47967cc0636SGreg Clayton 
GetDisassemblyLineCount() const480b9c1b51eSKate Stone uint32_t Debugger::GetDisassemblyLineCount() const {
48167cc0636SGreg Clayton   const uint32_t idx = ePropertyStopDisassemblyCount;
482b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsSInt64(
483a8ea5955SJonas Devlieghere       nullptr, idx, g_debugger_properties[idx].default_uint_value);
48467cc0636SGreg Clayton }
485e372b98dSGreg Clayton 
GetAutoOneLineSummaries() const486b9c1b51eSKate Stone bool Debugger::GetAutoOneLineSummaries() const {
48790a8db30SEnrico Granata   const uint32_t idx = ePropertyAutoOneLineSummaries;
488df370550SEugene Zelenko   return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true);
489ebdc1ac0SEnrico Granata }
490553fad5cSEnrico Granata 
GetEscapeNonPrintables() const491b9c1b51eSKate Stone bool Debugger::GetEscapeNonPrintables() const {
492ebdc1ac0SEnrico Granata   const uint32_t idx = ePropertyEscapeNonPrintables;
493df370550SEugene Zelenko   return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true);
494553fad5cSEnrico Granata }
495553fad5cSEnrico Granata 
GetAutoIndent() const496b9c1b51eSKate Stone bool Debugger::GetAutoIndent() const {
4976681041dSSean Callanan   const uint32_t idx = ePropertyAutoIndent;
498df370550SEugene Zelenko   return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true);
4996681041dSSean Callanan }
5006681041dSSean Callanan 
SetAutoIndent(bool b)501b9c1b51eSKate Stone bool Debugger::SetAutoIndent(bool b) {
5026681041dSSean Callanan   const uint32_t idx = ePropertyAutoIndent;
503df370550SEugene Zelenko   return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
5046681041dSSean Callanan }
5056681041dSSean Callanan 
GetPrintDecls() const506b9c1b51eSKate Stone bool Debugger::GetPrintDecls() const {
5076681041dSSean Callanan   const uint32_t idx = ePropertyPrintDecls;
508df370550SEugene Zelenko   return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true);
5096681041dSSean Callanan }
5106681041dSSean Callanan 
SetPrintDecls(bool b)511b9c1b51eSKate Stone bool Debugger::SetPrintDecls(bool b) {
5126681041dSSean Callanan   const uint32_t idx = ePropertyPrintDecls;
513df370550SEugene Zelenko   return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
5146681041dSSean Callanan }
5156681041dSSean Callanan 
GetTabSize() const516b9c1b51eSKate Stone uint32_t Debugger::GetTabSize() const {
5176681041dSSean Callanan   const uint32_t idx = ePropertyTabSize;
518b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsUInt64(
519a8ea5955SJonas Devlieghere       nullptr, idx, g_debugger_properties[idx].default_uint_value);
5206681041dSSean Callanan }
5216681041dSSean Callanan 
SetTabSize(uint32_t tab_size)522b9c1b51eSKate Stone bool Debugger::SetTabSize(uint32_t tab_size) {
5236681041dSSean Callanan   const uint32_t idx = ePropertyTabSize;
524df370550SEugene Zelenko   return m_collection_sp->SetPropertyAtIndexAsUInt64(nullptr, idx, tab_size);
5256681041dSSean Callanan }
5266681041dSSean Callanan 
5271b654882SGreg Clayton #pragma mark Debugger
5281b654882SGreg Clayton 
52967cc0636SGreg Clayton // const DebuggerPropertiesSP &
53067cc0636SGreg Clayton // Debugger::GetSettings() const
53167cc0636SGreg Clayton //{
53267cc0636SGreg Clayton //    return m_properties_sp;
53367cc0636SGreg Clayton //}
53467cc0636SGreg Clayton //
53599d0faf2SGreg Clayton 
Initialize(LoadPluginCallbackType load_plugin_callback)536b9c1b51eSKate Stone void Debugger::Initialize(LoadPluginCallbackType load_plugin_callback) {
537b9c1b51eSKate Stone   assert(g_debugger_list_ptr == nullptr &&
538b9c1b51eSKate Stone          "Debugger::Initialize called more than once!");
5396c42e063SGreg Clayton   g_debugger_list_mutex_ptr = new std::recursive_mutex();
5406c42e063SGreg Clayton   g_debugger_list_ptr = new DebuggerList();
5415fb8f797SGreg Clayton   g_load_plugin_callback = load_plugin_callback;
54299d0faf2SGreg Clayton }
54330fdc8d8SChris Lattner 
Terminate()544b9c1b51eSKate Stone void Debugger::Terminate() {
545b9c1b51eSKate Stone   assert(g_debugger_list_ptr &&
546b9c1b51eSKate Stone          "Debugger::Terminate called without a matching Debugger::Initialize!");
547e6e2bb38SZachary Turner 
548b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
54995af9d88SQuinn Pham     // Clear our global list of debugger objects
5506c42e063SGreg Clayton     {
5516c42e063SGreg Clayton       std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
5526c42e063SGreg Clayton       for (const auto &debugger : *g_debugger_list_ptr)
553f3cd1819SOleksiy Vyalov         debugger->Clear();
5546c42e063SGreg Clayton       g_debugger_list_ptr->clear();
5556c42e063SGreg Clayton     }
5566c42e063SGreg Clayton   }
55730fdc8d8SChris Lattner }
55830fdc8d8SChris Lattner 
SettingsInitialize()559b9c1b51eSKate Stone void Debugger::SettingsInitialize() { Target::SettingsInitialize(); }
56020bd37f7SCaroline Tice 
SettingsTerminate()561b9c1b51eSKate Stone void Debugger::SettingsTerminate() { Target::SettingsTerminate(); }
56220bd37f7SCaroline Tice 
LoadPlugin(const FileSpec & spec,Status & error)56397206d57SZachary Turner bool Debugger::LoadPlugin(const FileSpec &spec, Status &error) {
564b9c1b51eSKate Stone   if (g_load_plugin_callback) {
565b9c1b51eSKate Stone     llvm::sys::DynamicLibrary dynlib =
566b9c1b51eSKate Stone         g_load_plugin_callback(shared_from_this(), spec, error);
567b9c1b51eSKate Stone     if (dynlib.isValid()) {
56858a559c0SZachary Turner       m_loaded_plugins.push_back(dynlib);
56921dfcd9dSEnrico Granata       return true;
57021dfcd9dSEnrico Granata     }
571b9c1b51eSKate Stone   } else {
57205097246SAdrian Prantl     // The g_load_plugin_callback is registered in SBDebugger::Initialize() and
57305097246SAdrian Prantl     // if the public API layer isn't available (code is linking against all of
57405097246SAdrian Prantl     // the internal LLDB static libraries), then we can't load plugins
5755fb8f797SGreg Clayton     error.SetErrorString("Public API layer is not available");
5765fb8f797SGreg Clayton   }
57721dfcd9dSEnrico Granata   return false;
57821dfcd9dSEnrico Granata }
57921dfcd9dSEnrico Granata 
58035e4c84cSJonas Devlieghere static FileSystem::EnumerateDirectoryResult
LoadPluginCallback(void * baton,llvm::sys::fs::file_type ft,llvm::StringRef path)5817d86ee5aSZachary Turner LoadPluginCallback(void *baton, llvm::sys::fs::file_type ft,
58235e4c84cSJonas Devlieghere                    llvm::StringRef path) {
58397206d57SZachary Turner   Status error;
58421dfcd9dSEnrico Granata 
585ad8d48f9SJonas Devlieghere   static ConstString g_dylibext(".dylib");
586ad8d48f9SJonas Devlieghere   static ConstString g_solibext(".so");
58721dfcd9dSEnrico Granata 
58821dfcd9dSEnrico Granata   if (!baton)
58935e4c84cSJonas Devlieghere     return FileSystem::eEnumerateDirectoryResultQuit;
59021dfcd9dSEnrico Granata 
59121dfcd9dSEnrico Granata   Debugger *debugger = (Debugger *)baton;
59221dfcd9dSEnrico Granata 
5937d86ee5aSZachary Turner   namespace fs = llvm::sys::fs;
59405097246SAdrian Prantl   // If we have a regular file, a symbolic link or unknown file type, try and
59505097246SAdrian Prantl   // process the file. We must handle unknown as sometimes the directory
59621dfcd9dSEnrico Granata   // enumeration might be enumerating a file system that doesn't have correct
59721dfcd9dSEnrico Granata   // file type information.
5987d86ee5aSZachary Turner   if (ft == fs::file_type::regular_file || ft == fs::file_type::symlink_file ||
5997d86ee5aSZachary Turner       ft == fs::file_type::type_unknown) {
6008f3be7a3SJonas Devlieghere     FileSpec plugin_file_spec(path);
6018f3be7a3SJonas Devlieghere     FileSystem::Instance().Resolve(plugin_file_spec);
60221dfcd9dSEnrico Granata 
6033cf443ddSMichael Sartain     if (plugin_file_spec.GetFileNameExtension() != g_dylibext &&
604b9c1b51eSKate Stone         plugin_file_spec.GetFileNameExtension() != g_solibext) {
60535e4c84cSJonas Devlieghere       return FileSystem::eEnumerateDirectoryResultNext;
6063cf443ddSMichael Sartain     }
60721dfcd9dSEnrico Granata 
60897206d57SZachary Turner     Status plugin_load_error;
609e743c782SEnrico Granata     debugger->LoadPlugin(plugin_file_spec, plugin_load_error);
61021dfcd9dSEnrico Granata 
61135e4c84cSJonas Devlieghere     return FileSystem::eEnumerateDirectoryResultNext;
6127d86ee5aSZachary Turner   } else if (ft == fs::file_type::directory_file ||
6137d86ee5aSZachary Turner              ft == fs::file_type::symlink_file ||
6147d86ee5aSZachary Turner              ft == fs::file_type::type_unknown) {
61505097246SAdrian Prantl     // Try and recurse into anything that a directory or symbolic link. We must
61605097246SAdrian Prantl     // also do this for unknown as sometimes the directory enumeration might be
61705097246SAdrian Prantl     // enumerating a file system that doesn't have correct file type
61821dfcd9dSEnrico Granata     // information.
61935e4c84cSJonas Devlieghere     return FileSystem::eEnumerateDirectoryResultEnter;
62021dfcd9dSEnrico Granata   }
62121dfcd9dSEnrico Granata 
62235e4c84cSJonas Devlieghere   return FileSystem::eEnumerateDirectoryResultNext;
62321dfcd9dSEnrico Granata }
62421dfcd9dSEnrico Granata 
InstanceInitialize()625b9c1b51eSKate Stone void Debugger::InstanceInitialize() {
62621dfcd9dSEnrico Granata   const bool find_directories = true;
62721dfcd9dSEnrico Granata   const bool find_files = true;
62821dfcd9dSEnrico Granata   const bool find_other = true;
62921dfcd9dSEnrico Granata   char dir_path[PATH_MAX];
63060f028ffSPavel Labath   if (FileSpec dir_spec = HostInfo::GetSystemPluginDir()) {
631dbd7fabaSJonas Devlieghere     if (FileSystem::Instance().Exists(dir_spec) &&
632dbd7fabaSJonas Devlieghere         dir_spec.GetPath(dir_path, sizeof(dir_path))) {
63335e4c84cSJonas Devlieghere       FileSystem::Instance().EnumerateDirectory(dir_path, find_directories,
63435e4c84cSJonas Devlieghere                                                 find_files, find_other,
63535e4c84cSJonas Devlieghere                                                 LoadPluginCallback, this);
63621dfcd9dSEnrico Granata     }
63721dfcd9dSEnrico Granata   }
63821dfcd9dSEnrico Granata 
63960f028ffSPavel Labath   if (FileSpec dir_spec = HostInfo::GetUserPluginDir()) {
640dbd7fabaSJonas Devlieghere     if (FileSystem::Instance().Exists(dir_spec) &&
641dbd7fabaSJonas Devlieghere         dir_spec.GetPath(dir_path, sizeof(dir_path))) {
64235e4c84cSJonas Devlieghere       FileSystem::Instance().EnumerateDirectory(dir_path, find_directories,
64335e4c84cSJonas Devlieghere                                                 find_files, find_other,
64435e4c84cSJonas Devlieghere                                                 LoadPluginCallback, this);
64521dfcd9dSEnrico Granata     }
64621dfcd9dSEnrico Granata   }
647e8cd0c98SGreg Clayton 
648e8cd0c98SGreg Clayton   PluginManager::DebuggerInitialize(*this);
64921dfcd9dSEnrico Granata }
65021dfcd9dSEnrico Granata 
CreateInstance(lldb::LogOutputCallback log_callback,void * baton)651b9c1b51eSKate Stone DebuggerSP Debugger::CreateInstance(lldb::LogOutputCallback log_callback,
652b9c1b51eSKate Stone                                     void *baton) {
653228063cdSJim Ingham   DebuggerSP debugger_sp(new Debugger(log_callback, baton));
654b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
6556c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
6566c42e063SGreg Clayton     g_debugger_list_ptr->push_back(debugger_sp);
6576611103cSGreg Clayton   }
65821dfcd9dSEnrico Granata   debugger_sp->InstanceInitialize();
6596611103cSGreg Clayton   return debugger_sp;
6606611103cSGreg Clayton }
6616611103cSGreg Clayton 
Destroy(DebuggerSP & debugger_sp)662b9c1b51eSKate Stone void Debugger::Destroy(DebuggerSP &debugger_sp) {
663df370550SEugene Zelenko   if (!debugger_sp)
664e02657b1SCaroline Tice     return;
665e02657b1SCaroline Tice 
666d6b64612SMed Ismail Bennani   CommandInterpreter &cmd_interpreter = debugger_sp->GetCommandInterpreter();
667d6b64612SMed Ismail Bennani 
668d6b64612SMed Ismail Bennani   if (cmd_interpreter.GetSaveSessionOnQuit()) {
669d6b64612SMed Ismail Bennani     CommandReturnObject result(debugger_sp->GetUseColor());
670d6b64612SMed Ismail Bennani     cmd_interpreter.SaveTranscript(result);
671d6b64612SMed Ismail Bennani     if (result.Succeeded())
6723d08c778SJonas Devlieghere       (*debugger_sp->GetAsyncOutputStream()) << result.GetOutputData() << '\n';
673d6b64612SMed Ismail Bennani     else
6743d08c778SJonas Devlieghere       (*debugger_sp->GetAsyncErrorStream()) << result.GetErrorData() << '\n';
675d6b64612SMed Ismail Bennani   }
676d6b64612SMed Ismail Bennani 
6778314c525SJim Ingham   debugger_sp->Clear();
6788314c525SJim Ingham 
679b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
6806c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
6816c42e063SGreg Clayton     DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
682b9c1b51eSKate Stone     for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
683b9c1b51eSKate Stone       if ((*pos).get() == debugger_sp.get()) {
6846c42e063SGreg Clayton         g_debugger_list_ptr->erase(pos);
685e02657b1SCaroline Tice         return;
686e02657b1SCaroline Tice       }
687e02657b1SCaroline Tice     }
688e02657b1SCaroline Tice   }
689c15f55e2SGreg Clayton }
690e02657b1SCaroline Tice 
FindDebuggerWithInstanceName(ConstString instance_name)691e063ecccSJonas Devlieghere DebuggerSP Debugger::FindDebuggerWithInstanceName(ConstString instance_name) {
6924d122c40SGreg Clayton   DebuggerSP debugger_sp;
693b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
6946c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
6956c42e063SGreg Clayton     DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
696b9c1b51eSKate Stone     for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
697b9c1b51eSKate Stone       if ((*pos)->m_instance_name == instance_name) {
6986920b52bSGreg Clayton         debugger_sp = *pos;
6996920b52bSGreg Clayton         break;
7006920b52bSGreg Clayton       }
7016920b52bSGreg Clayton     }
7026920b52bSGreg Clayton   }
7033df9a8dfSCaroline Tice   return debugger_sp;
7043df9a8dfSCaroline Tice }
7056611103cSGreg Clayton 
FindTargetWithProcessID(lldb::pid_t pid)706b9c1b51eSKate Stone TargetSP Debugger::FindTargetWithProcessID(lldb::pid_t pid) {
7074d122c40SGreg Clayton   TargetSP target_sp;
708b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
7096c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
7106c42e063SGreg Clayton     DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
711b9c1b51eSKate Stone     for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
7126611103cSGreg Clayton       target_sp = (*pos)->GetTargetList().FindTargetWithProcessID(pid);
7136611103cSGreg Clayton       if (target_sp)
7146611103cSGreg Clayton         break;
7156611103cSGreg Clayton     }
716c15f55e2SGreg Clayton   }
7176611103cSGreg Clayton   return target_sp;
7186611103cSGreg Clayton }
7196611103cSGreg Clayton 
FindTargetWithProcess(Process * process)720b9c1b51eSKate Stone TargetSP Debugger::FindTargetWithProcess(Process *process) {
721e4e45924SGreg Clayton   TargetSP target_sp;
722b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
7236c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
7246c42e063SGreg Clayton     DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
725b9c1b51eSKate Stone     for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
726e4e45924SGreg Clayton       target_sp = (*pos)->GetTargetList().FindTargetWithProcess(process);
727e4e45924SGreg Clayton       if (target_sp)
728e4e45924SGreg Clayton         break;
729e4e45924SGreg Clayton     }
730c15f55e2SGreg Clayton   }
731e4e45924SGreg Clayton   return target_sp;
732e4e45924SGreg Clayton }
733e4e45924SGreg Clayton 
GetStaticBroadcasterClass()734e122877fSGreg Clayton ConstString Debugger::GetStaticBroadcasterClass() {
735e122877fSGreg Clayton   static ConstString class_name("lldb.debugger");
736e122877fSGreg Clayton   return class_name;
737e122877fSGreg Clayton }
738e122877fSGreg Clayton 
Debugger(lldb::LogOutputCallback log_callback,void * baton)739b9c1b51eSKate Stone Debugger::Debugger(lldb::LogOutputCallback log_callback, void *baton)
740b9c1b51eSKate Stone     : UserID(g_unique_id++),
7412f3df613SZachary Turner       Properties(std::make_shared<OptionValueProperties>()),
742f913fd6eSLawrence D'Anna       m_input_file_sp(std::make_shared<NativeFile>(stdin, false)),
7437ca15ba7SLawrence D'Anna       m_output_stream_sp(std::make_shared<StreamFile>(stdout, false)),
7447ca15ba7SLawrence D'Anna       m_error_stream_sp(std::make_shared<StreamFile>(stderr, false)),
745d77c2e09SJonas Devlieghere       m_input_recorder(nullptr),
746583bbb1dSJim Ingham       m_broadcaster_manager_sp(BroadcasterManager::MakeBroadcasterManager()),
747b9c1b51eSKate Stone       m_terminal_state(), m_target_list(*this), m_platform_list(),
748583bbb1dSJim Ingham       m_listener_sp(Listener::MakeListener("lldb.Debugger")),
749d5b44036SJonas Devlieghere       m_source_manager_up(), m_source_file_cache(),
750f20dd1d5SJonas Devlieghere       m_command_interpreter_up(
751a8f3ae7cSJonas Devlieghere           std::make_unique<CommandInterpreter>(*this, false)),
7527ce2de2cSJonas Devlieghere       m_io_handler_stack(), m_instance_name(), m_loaded_plugins(),
753bbf70c04SJonas Devlieghere       m_event_handler_thread(), m_io_handler_thread(),
7544329fe42SGreg Clayton       m_sync_broadcaster(nullptr, "lldb.debugger.sync"),
755e122877fSGreg Clayton       m_broadcaster(m_broadcaster_manager_sp,
756e122877fSGreg Clayton                     GetStaticBroadcasterClass().AsCString()),
757b9c1b51eSKate Stone       m_forward_listener_sp(), m_clear_once() {
758db203e02SRaphael Isemann   m_instance_name.SetString(llvm::formatv("debugger_{0}", GetID()).str());
759228063cdSJim Ingham   if (log_callback)
760de747565SJonas Devlieghere     m_callback_handler_sp =
761de747565SJonas Devlieghere         std::make_shared<CallbackLogHandler>(log_callback, baton);
762d5b44036SJonas Devlieghere   m_command_interpreter_up->Initialize();
763ded470d3SGreg Clayton   // Always add our default platform to the platform list
764615eb7e6SGreg Clayton   PlatformSP default_platform_sp(Platform::GetHostPlatform());
765df370550SEugene Zelenko   assert(default_platform_sp);
766ded470d3SGreg Clayton   m_platform_list.Append(default_platform_sp, true);
76767cc0636SGreg Clayton 
76816e5a347SVedant Kumar   // Create the dummy target.
76916e5a347SVedant Kumar   {
77016e5a347SVedant Kumar     ArchSpec arch(Target::GetDefaultArchitecture());
77116e5a347SVedant Kumar     if (!arch.IsValid())
77216e5a347SVedant Kumar       arch = HostInfo::GetArchitecture();
77316e5a347SVedant Kumar     assert(arch.IsValid() && "No valid default or host archspec");
77416e5a347SVedant Kumar     const bool is_dummy_target = true;
77516e5a347SVedant Kumar     m_dummy_target_sp.reset(
77616e5a347SVedant Kumar         new Target(*this, arch, default_platform_sp, is_dummy_target));
77716e5a347SVedant Kumar   }
778d43d912bSRaphael Isemann   assert(m_dummy_target_sp.get() && "Couldn't construct dummy target?");
779d43d912bSRaphael Isemann 
780a8ea5955SJonas Devlieghere   m_collection_sp->Initialize(g_debugger_properties);
781b9c1b51eSKate Stone   m_collection_sp->AppendProperty(
782b9c1b51eSKate Stone       ConstString("target"),
783b9c1b51eSKate Stone       ConstString("Settings specify to debugging targets."), true,
7843d7161e3SPavel Labath       Target::GetGlobalProperties().GetValueProperties());
785b9c1b51eSKate Stone   m_collection_sp->AppendProperty(
786b9c1b51eSKate Stone       ConstString("platform"), ConstString("Platform settings."), true,
7873d7161e3SPavel Labath       Platform::GetGlobalPlatformProperties().GetValueProperties());
788235354beSAdrian Prantl   m_collection_sp->AppendProperty(
7893cd29bcfSAdrian Prantl       ConstString("symbols"), ConstString("Symbol lookup and cache settings."),
7903cd29bcfSAdrian Prantl       true, ModuleList::GetGlobalModuleListProperties().GetValueProperties());
791d5b44036SJonas Devlieghere   if (m_command_interpreter_up) {
792b9c1b51eSKate Stone     m_collection_sp->AppendProperty(
793b9c1b51eSKate Stone         ConstString("interpreter"),
794754a9369SGreg Clayton         ConstString("Settings specify to the debugger's command interpreter."),
795d5b44036SJonas Devlieghere         true, m_command_interpreter_up->GetValueProperties());
796754a9369SGreg Clayton   }
797b9c1b51eSKate Stone   OptionValueSInt64 *term_width =
798b9c1b51eSKate Stone       m_collection_sp->GetPropertyAtIndexAsOptionValueSInt64(
799b9c1b51eSKate Stone           nullptr, ePropertyTerminalWidth);
80067cc0636SGreg Clayton   term_width->SetMinimumValue(10);
80167cc0636SGreg Clayton   term_width->SetMaximumValue(1024);
802c3ce7f27SMichael Sartain 
803c3ce7f27SMichael Sartain   // Turn off use-color if this is a dumb terminal.
804c3ce7f27SMichael Sartain   const char *term = getenv("TERM");
805c3ce7f27SMichael Sartain   if (term && !strcmp(term, "dumb"))
806c3ce7f27SMichael Sartain     SetUseColor(false);
807eca9ce14SRaphael Isemann   // Turn off use-color if we don't write to a terminal with color support.
8087ca15ba7SLawrence D'Anna   if (!GetOutputFile().GetIsTerminalWithColors())
809eca9ce14SRaphael Isemann     SetUseColor(false);
8108aa23614SDavid Bolvansky 
8118aa23614SDavid Bolvansky #if defined(_WIN32) && defined(ENABLE_VIRTUAL_TERMINAL_PROCESSING)
8128aa23614SDavid Bolvansky   // Enabling use of ANSI color codes because LLDB is using them to highlight
8138aa23614SDavid Bolvansky   // text.
8148aa23614SDavid Bolvansky   llvm::sys::Process::UseANSIEscapeCodes(true);
8158aa23614SDavid Bolvansky #endif
81630fdc8d8SChris Lattner }
81730fdc8d8SChris Lattner 
~Debugger()818b9c1b51eSKate Stone Debugger::~Debugger() { Clear(); }
8198314c525SJim Ingham 
Clear()820b9c1b51eSKate Stone void Debugger::Clear() {
82105097246SAdrian Prantl   // Make sure we call this function only once. With the C++ global destructor
82205097246SAdrian Prantl   // chain having a list of debuggers and with code that can be running on
82305097246SAdrian Prantl   // other threads, we need to ensure this doesn't happen multiple times.
8244329fe42SGreg Clayton   //
8254329fe42SGreg Clayton   // The following functions call Debugger::Clear():
8264329fe42SGreg Clayton   //     Debugger::~Debugger();
8274329fe42SGreg Clayton   //     static void Debugger::Destroy(lldb::DebuggerSP &debugger_sp);
8284329fe42SGreg Clayton   //     static void Debugger::Terminate();
829c5f28e2aSKamil Rytarowski   llvm::call_once(m_clear_once, [this]() {
83044d93782SGreg Clayton     ClearIOHandlers();
83144d93782SGreg Clayton     StopIOHandlerThread();
83244d93782SGreg Clayton     StopEventHandlerThread();
833583bbb1dSJim Ingham     m_listener_sp->Clear();
834de448c0aSJonas Devlieghere     for (TargetSP target_sp : m_target_list.Targets()) {
835b9c1b51eSKate Stone       if (target_sp) {
836de448c0aSJonas Devlieghere         if (ProcessSP process_sp = target_sp->GetProcessSP())
8371fd07059SJim Ingham           process_sp->Finalize();
838ccbc08e6SGreg Clayton         target_sp->Destroy();
8396611103cSGreg Clayton       }
84030fdc8d8SChris Lattner     }
841583bbb1dSJim Ingham     m_broadcaster_manager_sp->Clear();
84230fdc8d8SChris Lattner 
843b9c1b51eSKate Stone     // Close the input file _before_ we close the input read communications
84405097246SAdrian Prantl     // class as it does NOT own the input file, our m_input_file does.
845c5917d9aSJim Ingham     m_terminal_state.Clear();
8467ca15ba7SLawrence D'Anna     GetInputFile().Close();
8470c4129f2SGreg Clayton 
848d5b44036SJonas Devlieghere     m_command_interpreter_up->Clear();
8494329fe42SGreg Clayton   });
8508314c525SJim Ingham }
85130fdc8d8SChris Lattner 
GetCloseInputOnEOF() const852b9c1b51eSKate Stone bool Debugger::GetCloseInputOnEOF() const {
85344d93782SGreg Clayton   //    return m_input_comm.GetCloseOnEOF();
85444d93782SGreg Clayton   return false;
855fc3f027dSGreg Clayton }
856fc3f027dSGreg Clayton 
SetCloseInputOnEOF(bool b)857b9c1b51eSKate Stone void Debugger::SetCloseInputOnEOF(bool b) {
85844d93782SGreg Clayton   //    m_input_comm.SetCloseOnEOF(b);
859fc3f027dSGreg Clayton }
860fc3f027dSGreg Clayton 
GetAsyncExecution()861b9c1b51eSKate Stone bool Debugger::GetAsyncExecution() {
862d5b44036SJonas Devlieghere   return !m_command_interpreter_up->GetSynchronous();
86330fdc8d8SChris Lattner }
86430fdc8d8SChris Lattner 
SetAsyncExecution(bool async_execution)865b9c1b51eSKate Stone void Debugger::SetAsyncExecution(bool async_execution) {
866d5b44036SJonas Devlieghere   m_command_interpreter_up->SetSynchronous(!async_execution);
86730fdc8d8SChris Lattner }
86830fdc8d8SChris Lattner 
GetInputRecorder()869d77c2e09SJonas Devlieghere repro::DataRecorder *Debugger::GetInputRecorder() { return m_input_recorder; }
870d77c2e09SJonas Devlieghere 
OpenPipe(int fds[2],std::size_t size)871f23b829aSLevon Ter-Grigoryan static inline int OpenPipe(int fds[2], std::size_t size) {
872f23b829aSLevon Ter-Grigoryan #ifdef _WIN32
873f23b829aSLevon Ter-Grigoryan   return _pipe(fds, size, O_BINARY);
874f23b829aSLevon Ter-Grigoryan #else
875f23b829aSLevon Ter-Grigoryan   (void)size;
876f23b829aSLevon Ter-Grigoryan   return pipe(fds);
877f23b829aSLevon Ter-Grigoryan #endif
878f23b829aSLevon Ter-Grigoryan }
879f23b829aSLevon Ter-Grigoryan 
SetInputString(const char * data)880f23b829aSLevon Ter-Grigoryan Status Debugger::SetInputString(const char *data) {
881f23b829aSLevon Ter-Grigoryan   Status result;
882f23b829aSLevon Ter-Grigoryan   enum PIPES { READ, WRITE }; // Indexes for the read and write fds
883f23b829aSLevon Ter-Grigoryan   int fds[2] = {-1, -1};
884f23b829aSLevon Ter-Grigoryan 
885f23b829aSLevon Ter-Grigoryan   if (data == nullptr) {
886f23b829aSLevon Ter-Grigoryan     result.SetErrorString("String data is null");
887f23b829aSLevon Ter-Grigoryan     return result;
888f23b829aSLevon Ter-Grigoryan   }
889f23b829aSLevon Ter-Grigoryan 
890f23b829aSLevon Ter-Grigoryan   size_t size = strlen(data);
891f23b829aSLevon Ter-Grigoryan   if (size == 0) {
892f23b829aSLevon Ter-Grigoryan     result.SetErrorString("String data is empty");
893f23b829aSLevon Ter-Grigoryan     return result;
894f23b829aSLevon Ter-Grigoryan   }
895f23b829aSLevon Ter-Grigoryan 
896f23b829aSLevon Ter-Grigoryan   if (OpenPipe(fds, size) != 0) {
897f23b829aSLevon Ter-Grigoryan     result.SetErrorString(
898f23b829aSLevon Ter-Grigoryan         "can't create pipe file descriptors for LLDB commands");
899f23b829aSLevon Ter-Grigoryan     return result;
900f23b829aSLevon Ter-Grigoryan   }
901f23b829aSLevon Ter-Grigoryan 
9026e388242SMartin Storsjö   int r = write(fds[WRITE], data, size);
9036e388242SMartin Storsjö   (void)r;
904f23b829aSLevon Ter-Grigoryan   // Close the write end of the pipe, so that the command interpreter will exit
905f23b829aSLevon Ter-Grigoryan   // when it consumes all the data.
906f23b829aSLevon Ter-Grigoryan   llvm::sys::Process::SafelyCloseFileDescriptor(fds[WRITE]);
907f23b829aSLevon Ter-Grigoryan 
908f23b829aSLevon Ter-Grigoryan   // Open the read file descriptor as a FILE * that we can return as an input
909f23b829aSLevon Ter-Grigoryan   // handle.
910f23b829aSLevon Ter-Grigoryan   FILE *commands_file = fdopen(fds[READ], "rb");
911f23b829aSLevon Ter-Grigoryan   if (commands_file == nullptr) {
912f23b829aSLevon Ter-Grigoryan     result.SetErrorStringWithFormat("fdopen(%i, \"rb\") failed (errno = %i) "
913f23b829aSLevon Ter-Grigoryan                                     "when trying to open LLDB commands pipe",
914f23b829aSLevon Ter-Grigoryan                                     fds[READ], errno);
915f23b829aSLevon Ter-Grigoryan     llvm::sys::Process::SafelyCloseFileDescriptor(fds[READ]);
916f23b829aSLevon Ter-Grigoryan     return result;
917f23b829aSLevon Ter-Grigoryan   }
918f23b829aSLevon Ter-Grigoryan 
919f23b829aSLevon Ter-Grigoryan   return SetInputFile(
920f23b829aSLevon Ter-Grigoryan       (FileSP)std::make_shared<NativeFile>(commands_file, true));
921f23b829aSLevon Ter-Grigoryan }
922f23b829aSLevon Ter-Grigoryan 
SetInputFile(FileSP file_sp)923f23b829aSLevon Ter-Grigoryan Status Debugger::SetInputFile(FileSP file_sp) {
924f23b829aSLevon Ter-Grigoryan   Status error;
925f23b829aSLevon Ter-Grigoryan   repro::DataRecorder *recorder = nullptr;
926f23b829aSLevon Ter-Grigoryan   if (repro::Generator *g = repro::Reproducer::Instance().GetGenerator())
927f23b829aSLevon Ter-Grigoryan     recorder = g->GetOrCreate<repro::CommandProvider>().GetNewRecorder();
928f23b829aSLevon Ter-Grigoryan 
929f23b829aSLevon Ter-Grigoryan   static std::unique_ptr<repro::MultiLoader<repro::CommandProvider>> loader =
930f23b829aSLevon Ter-Grigoryan       repro::MultiLoader<repro::CommandProvider>::Create(
931f23b829aSLevon Ter-Grigoryan           repro::Reproducer::Instance().GetLoader());
932f23b829aSLevon Ter-Grigoryan   if (loader) {
933f23b829aSLevon Ter-Grigoryan     llvm::Optional<std::string> nextfile = loader->GetNextFile();
934f23b829aSLevon Ter-Grigoryan     FILE *fh = nextfile ? FileSystem::Instance().Fopen(nextfile->c_str(), "r")
935f23b829aSLevon Ter-Grigoryan                         : nullptr;
936f23b829aSLevon Ter-Grigoryan     // FIXME Jonas Devlieghere: shouldn't this error be propagated out to the
937f23b829aSLevon Ter-Grigoryan     // reproducer somehow if fh is NULL?
938f23b829aSLevon Ter-Grigoryan     if (fh) {
939f23b829aSLevon Ter-Grigoryan       file_sp = std::make_shared<NativeFile>(fh, true);
940f23b829aSLevon Ter-Grigoryan     }
941f23b829aSLevon Ter-Grigoryan   }
942f23b829aSLevon Ter-Grigoryan 
943f23b829aSLevon Ter-Grigoryan   if (!file_sp || !file_sp->IsValid()) {
944f23b829aSLevon Ter-Grigoryan     error.SetErrorString("invalid file");
945f23b829aSLevon Ter-Grigoryan     return error;
946f23b829aSLevon Ter-Grigoryan   }
947f23b829aSLevon Ter-Grigoryan 
948f23b829aSLevon Ter-Grigoryan   SetInputFile(file_sp, recorder);
949f23b829aSLevon Ter-Grigoryan   return error;
950f23b829aSLevon Ter-Grigoryan }
951f23b829aSLevon Ter-Grigoryan 
SetInputFile(FileSP file_sp,repro::DataRecorder * recorder)95296898eb6SLawrence D'Anna void Debugger::SetInputFile(FileSP file_sp, repro::DataRecorder *recorder) {
95396898eb6SLawrence D'Anna   assert(file_sp && file_sp->IsValid());
954d77c2e09SJonas Devlieghere   m_input_recorder = recorder;
955c4701c9cSJonas Devlieghere   m_input_file_sp = std::move(file_sp);
95605097246SAdrian Prantl   // Save away the terminal state if that is relevant, so that we can restore
95705097246SAdrian Prantl   // it in RestoreInputState.
958c5917d9aSJim Ingham   SaveInputTerminalState();
95930fdc8d8SChris Lattner }
96030fdc8d8SChris Lattner 
SetOutputFile(FileSP file_sp)96196898eb6SLawrence D'Anna void Debugger::SetOutputFile(FileSP file_sp) {
96296898eb6SLawrence D'Anna   assert(file_sp && file_sp->IsValid());
9637ca15ba7SLawrence D'Anna   m_output_stream_sp = std::make_shared<StreamFile>(file_sp);
96430fdc8d8SChris Lattner }
96530fdc8d8SChris Lattner 
SetErrorFile(FileSP file_sp)96696898eb6SLawrence D'Anna void Debugger::SetErrorFile(FileSP file_sp) {
96796898eb6SLawrence D'Anna   assert(file_sp && file_sp->IsValid());
9687ca15ba7SLawrence D'Anna   m_error_stream_sp = std::make_shared<StreamFile>(file_sp);
96930fdc8d8SChris Lattner }
97030fdc8d8SChris Lattner 
SaveInputTerminalState()971b9c1b51eSKate Stone void Debugger::SaveInputTerminalState() {
9727ca15ba7SLawrence D'Anna   int fd = GetInputFile().GetDescriptor();
9737ca15ba7SLawrence D'Anna   if (fd != File::kInvalidDescriptor)
9747ca15ba7SLawrence D'Anna     m_terminal_state.Save(fd, true);
97544d93782SGreg Clayton }
976c5917d9aSJim Ingham 
RestoreInputTerminalState()977b9c1b51eSKate Stone void Debugger::RestoreInputTerminalState() { m_terminal_state.Restore(); }
978c5917d9aSJim Ingham 
GetSelectedExecutionContext()979b9c1b51eSKate Stone ExecutionContext Debugger::GetSelectedExecutionContext() {
980a39bcbcaSTatyana Krasnukha   bool adopt_selected = true;
981a39bcbcaSTatyana Krasnukha   ExecutionContextRef exe_ctx_ref(GetSelectedTarget().get(), adopt_selected);
982a39bcbcaSTatyana Krasnukha   return ExecutionContext(exe_ctx_ref);
98330fdc8d8SChris Lattner }
98430fdc8d8SChris Lattner 
DispatchInputInterrupt()985b9c1b51eSKate Stone void Debugger::DispatchInputInterrupt() {
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->Interrupt();
990efed6131SCaroline Tice }
991efed6131SCaroline Tice 
DispatchInputEndOfFile()992b9c1b51eSKate Stone void Debugger::DispatchInputEndOfFile() {
9937ce2de2cSJonas Devlieghere   std::lock_guard<std::recursive_mutex> guard(m_io_handler_stack.GetMutex());
9947ce2de2cSJonas Devlieghere   IOHandlerSP reader_sp(m_io_handler_stack.Top());
995efed6131SCaroline Tice   if (reader_sp)
99644d93782SGreg Clayton     reader_sp->GotEOF();
997efed6131SCaroline Tice }
998efed6131SCaroline Tice 
ClearIOHandlers()999b9c1b51eSKate Stone void Debugger::ClearIOHandlers() {
1000b9c1b51eSKate Stone   // The bottom input reader should be the main debugger input reader.  We do
1001b9c1b51eSKate Stone   // not want to close that one here.
10027ce2de2cSJonas Devlieghere   std::lock_guard<std::recursive_mutex> guard(m_io_handler_stack.GetMutex());
10037ce2de2cSJonas Devlieghere   while (m_io_handler_stack.GetSize() > 1) {
10047ce2de2cSJonas Devlieghere     IOHandlerSP reader_sp(m_io_handler_stack.Top());
10053d6086f6SCaroline Tice     if (reader_sp)
10064446487dSPavel Labath       PopIOHandler(reader_sp);
10073d6086f6SCaroline Tice   }
10083d6086f6SCaroline Tice }
10093d6086f6SCaroline Tice 
RunIOHandlers()10102671df9bSJonas Devlieghere void Debugger::RunIOHandlers() {
101104de24e6SJonas Devlieghere   IOHandlerSP reader_sp = m_io_handler_stack.Top();
1012b9c1b51eSKate Stone   while (true) {
101330fdc8d8SChris Lattner     if (!reader_sp)
101430fdc8d8SChris Lattner       break;
101530fdc8d8SChris Lattner 
101644d93782SGreg Clayton     reader_sp->Run();
101704de24e6SJonas Devlieghere     {
101804de24e6SJonas Devlieghere       std::lock_guard<std::recursive_mutex> guard(
101904de24e6SJonas Devlieghere           m_io_handler_synchronous_mutex);
102044d93782SGreg Clayton 
102144d93782SGreg Clayton       // Remove all input readers that are done from the top of the stack
1022b9c1b51eSKate Stone       while (true) {
10237ce2de2cSJonas Devlieghere         IOHandlerSP top_reader_sp = m_io_handler_stack.Top();
102444d93782SGreg Clayton         if (top_reader_sp && top_reader_sp->GetIsDone())
10254446487dSPavel Labath           PopIOHandler(top_reader_sp);
102630fdc8d8SChris Lattner         else
102730fdc8d8SChris Lattner           break;
102830fdc8d8SChris Lattner       }
102904de24e6SJonas Devlieghere       reader_sp = m_io_handler_stack.Top();
103004de24e6SJonas Devlieghere     }
103130fdc8d8SChris Lattner   }
103244d93782SGreg Clayton   ClearIOHandlers();
103344d93782SGreg Clayton }
103430fdc8d8SChris Lattner 
RunIOHandlerSync(const IOHandlerSP & reader_sp)103504de24e6SJonas Devlieghere void Debugger::RunIOHandlerSync(const IOHandlerSP &reader_sp) {
103604de24e6SJonas Devlieghere   std::lock_guard<std::recursive_mutex> guard(m_io_handler_synchronous_mutex);
103704de24e6SJonas Devlieghere 
103804de24e6SJonas Devlieghere   PushIOHandler(reader_sp);
103904de24e6SJonas Devlieghere   IOHandlerSP top_reader_sp = reader_sp;
104004de24e6SJonas Devlieghere 
104104de24e6SJonas Devlieghere   while (top_reader_sp) {
104204de24e6SJonas Devlieghere     if (!top_reader_sp)
104304de24e6SJonas Devlieghere       break;
104404de24e6SJonas Devlieghere 
104504de24e6SJonas Devlieghere     top_reader_sp->Run();
104604de24e6SJonas Devlieghere 
104704de24e6SJonas Devlieghere     // Don't unwind past the starting point.
104804de24e6SJonas Devlieghere     if (top_reader_sp.get() == reader_sp.get()) {
104904de24e6SJonas Devlieghere       if (PopIOHandler(reader_sp))
105004de24e6SJonas Devlieghere         break;
105104de24e6SJonas Devlieghere     }
105204de24e6SJonas Devlieghere 
105304de24e6SJonas Devlieghere     // If we pushed new IO handlers, pop them if they're done or restart the
105404de24e6SJonas Devlieghere     // loop to run them if they're not.
105504de24e6SJonas Devlieghere     while (true) {
105604de24e6SJonas Devlieghere       top_reader_sp = m_io_handler_stack.Top();
105704de24e6SJonas Devlieghere       if (top_reader_sp && top_reader_sp->GetIsDone()) {
105804de24e6SJonas Devlieghere         PopIOHandler(top_reader_sp);
105904de24e6SJonas Devlieghere         // Don't unwind past the starting point.
106004de24e6SJonas Devlieghere         if (top_reader_sp.get() == reader_sp.get())
106104de24e6SJonas Devlieghere           return;
106204de24e6SJonas Devlieghere       } else {
106304de24e6SJonas Devlieghere         break;
106404de24e6SJonas Devlieghere       }
106504de24e6SJonas Devlieghere     }
106604de24e6SJonas Devlieghere   }
106704de24e6SJonas Devlieghere }
106804de24e6SJonas Devlieghere 
IsTopIOHandler(const lldb::IOHandlerSP & reader_sp)1069b9c1b51eSKate Stone bool Debugger::IsTopIOHandler(const lldb::IOHandlerSP &reader_sp) {
10707ce2de2cSJonas Devlieghere   return m_io_handler_stack.IsTop(reader_sp);
107144d93782SGreg Clayton }
107230fdc8d8SChris Lattner 
CheckTopIOHandlerTypes(IOHandler::Type top_type,IOHandler::Type second_top_type)1073b9c1b51eSKate Stone bool Debugger::CheckTopIOHandlerTypes(IOHandler::Type top_type,
1074b9c1b51eSKate Stone                                       IOHandler::Type second_top_type) {
10757ce2de2cSJonas Devlieghere   return m_io_handler_stack.CheckTopIOHandlerTypes(top_type, second_top_type);
10766681041dSSean Callanan }
10776681041dSSean Callanan 
PrintAsync(const char * s,size_t len,bool is_stdout)1078b9c1b51eSKate Stone void Debugger::PrintAsync(const char *s, size_t len, bool is_stdout) {
10792436c570SJonas Devlieghere   bool printed = m_io_handler_stack.PrintAsync(s, len, is_stdout);
10802436c570SJonas Devlieghere   if (!printed) {
10812436c570SJonas Devlieghere     lldb::StreamFileSP stream =
10822436c570SJonas Devlieghere         is_stdout ? m_output_stream_sp : m_error_stream_sp;
10832436c570SJonas Devlieghere     stream->Write(s, len);
10842436c570SJonas Devlieghere   }
10854446487dSPavel Labath }
108644d93782SGreg Clayton 
GetTopIOHandlerControlSequence(char ch)1087b9c1b51eSKate Stone ConstString Debugger::GetTopIOHandlerControlSequence(char ch) {
10887ce2de2cSJonas Devlieghere   return m_io_handler_stack.GetTopIOHandlerControlSequence(ch);
108930fdc8d8SChris Lattner }
109030fdc8d8SChris Lattner 
GetIOHandlerCommandPrefix()1091b9c1b51eSKate Stone const char *Debugger::GetIOHandlerCommandPrefix() {
10927ce2de2cSJonas Devlieghere   return m_io_handler_stack.GetTopIOHandlerCommandPrefix();
1093a487aa4cSKate Stone }
1094a487aa4cSKate Stone 
GetIOHandlerHelpPrologue()1095b9c1b51eSKate Stone const char *Debugger::GetIOHandlerHelpPrologue() {
10967ce2de2cSJonas Devlieghere   return m_io_handler_stack.GetTopIOHandlerHelpPrologue();
1097a487aa4cSKate Stone }
1098a487aa4cSKate Stone 
RemoveIOHandler(const IOHandlerSP & reader_sp)10997ce2de2cSJonas Devlieghere bool Debugger::RemoveIOHandler(const IOHandlerSP &reader_sp) {
11007ce2de2cSJonas Devlieghere   return PopIOHandler(reader_sp);
11017ce2de2cSJonas Devlieghere }
11027ce2de2cSJonas Devlieghere 
RunIOHandlerAsync(const IOHandlerSP & reader_sp,bool cancel_top_handler)11037ce2de2cSJonas Devlieghere void Debugger::RunIOHandlerAsync(const IOHandlerSP &reader_sp,
11047ce2de2cSJonas Devlieghere                                  bool cancel_top_handler) {
11057ce2de2cSJonas Devlieghere   PushIOHandler(reader_sp, cancel_top_handler);
11067ce2de2cSJonas Devlieghere }
11077ce2de2cSJonas Devlieghere 
AdoptTopIOHandlerFilesIfInvalid(FileSP & in,StreamFileSP & out,StreamFileSP & err)11087ca15ba7SLawrence D'Anna void Debugger::AdoptTopIOHandlerFilesIfInvalid(FileSP &in, StreamFileSP &out,
1109b9c1b51eSKate Stone                                                StreamFileSP &err) {
111005097246SAdrian Prantl   // Before an IOHandler runs, it must have in/out/err streams. This function
111105097246SAdrian Prantl   // is called when one ore more of the streams are nullptr. We use the top
111205097246SAdrian Prantl   // input reader's in/out/err streams, or fall back to the debugger file
111305097246SAdrian Prantl   // handles, or we fall back onto stdin/stdout/stderr as a last resort.
111444d93782SGreg Clayton 
11157ce2de2cSJonas Devlieghere   std::lock_guard<std::recursive_mutex> guard(m_io_handler_stack.GetMutex());
11167ce2de2cSJonas Devlieghere   IOHandlerSP top_reader_sp(m_io_handler_stack.Top());
111744d93782SGreg Clayton   // If no STDIN has been set, then set it appropriately
1118b07823f3SLawrence D'Anna   if (!in || !in->IsValid()) {
111944d93782SGreg Clayton     if (top_reader_sp)
11207ca15ba7SLawrence D'Anna       in = top_reader_sp->GetInputFileSP();
112144d93782SGreg Clayton     else
11227ca15ba7SLawrence D'Anna       in = GetInputFileSP();
112344d93782SGreg Clayton     // If there is nothing, use stdin
112444d93782SGreg Clayton     if (!in)
1125f913fd6eSLawrence D'Anna       in = std::make_shared<NativeFile>(stdin, false);
112644d93782SGreg Clayton   }
112744d93782SGreg Clayton   // If no STDOUT has been set, then set it appropriately
1128b07823f3SLawrence D'Anna   if (!out || !out->GetFile().IsValid()) {
112944d93782SGreg Clayton     if (top_reader_sp)
11307ca15ba7SLawrence D'Anna       out = top_reader_sp->GetOutputStreamFileSP();
113144d93782SGreg Clayton     else
11327ca15ba7SLawrence D'Anna       out = GetOutputStreamSP();
113344d93782SGreg Clayton     // If there is nothing, use stdout
113444d93782SGreg Clayton     if (!out)
11352f3df613SZachary Turner       out = std::make_shared<StreamFile>(stdout, false);
113644d93782SGreg Clayton   }
113744d93782SGreg Clayton   // If no STDERR has been set, then set it appropriately
1138b07823f3SLawrence D'Anna   if (!err || !err->GetFile().IsValid()) {
113944d93782SGreg Clayton     if (top_reader_sp)
11407ca15ba7SLawrence D'Anna       err = top_reader_sp->GetErrorStreamFileSP();
114144d93782SGreg Clayton     else
11427ca15ba7SLawrence D'Anna       err = GetErrorStreamSP();
114344d93782SGreg Clayton     // If there is nothing, use stderr
114444d93782SGreg Clayton     if (!err)
11457ca15ba7SLawrence D'Anna       err = std::make_shared<StreamFile>(stderr, false);
114644d93782SGreg Clayton   }
114744d93782SGreg Clayton }
114844d93782SGreg Clayton 
PushIOHandler(const IOHandlerSP & reader_sp,bool cancel_top_handler)1149c01783a8SRaphael Isemann void Debugger::PushIOHandler(const IOHandlerSP &reader_sp,
1150c01783a8SRaphael Isemann                              bool cancel_top_handler) {
115130fdc8d8SChris Lattner   if (!reader_sp)
115230fdc8d8SChris Lattner     return;
1153b44880caSCaroline Tice 
11547ce2de2cSJonas Devlieghere   std::lock_guard<std::recursive_mutex> guard(m_io_handler_stack.GetMutex());
11554446487dSPavel Labath 
11564446487dSPavel Labath   // Get the current top input reader...
11577ce2de2cSJonas Devlieghere   IOHandlerSP top_reader_sp(m_io_handler_stack.Top());
1158b44880caSCaroline Tice 
1159b4874f1aSGreg Clayton   // Don't push the same IO handler twice...
11604446487dSPavel Labath   if (reader_sp == top_reader_sp)
11614446487dSPavel Labath     return;
11624446487dSPavel Labath 
116344d93782SGreg Clayton   // Push our new input reader
11647ce2de2cSJonas Devlieghere   m_io_handler_stack.Push(reader_sp);
11654446487dSPavel Labath   reader_sp->Activate();
116644d93782SGreg Clayton 
116705097246SAdrian Prantl   // Interrupt the top input reader to it will exit its Run() function and let
116805097246SAdrian Prantl   // this new input reader take over
1169b9c1b51eSKate Stone   if (top_reader_sp) {
117044d93782SGreg Clayton     top_reader_sp->Deactivate();
1171c01783a8SRaphael Isemann     if (cancel_top_handler)
11724446487dSPavel Labath       top_reader_sp->Cancel();
117330fdc8d8SChris Lattner   }
1174b4874f1aSGreg Clayton }
117530fdc8d8SChris Lattner 
PopIOHandler(const IOHandlerSP & pop_reader_sp)1176b9c1b51eSKate Stone bool Debugger::PopIOHandler(const IOHandlerSP &pop_reader_sp) {
11774446487dSPavel Labath   if (!pop_reader_sp)
11784446487dSPavel Labath     return false;
117930fdc8d8SChris Lattner 
11807ce2de2cSJonas Devlieghere   std::lock_guard<std::recursive_mutex> guard(m_io_handler_stack.GetMutex());
118144d93782SGreg Clayton 
118205097246SAdrian Prantl   // The reader on the stop of the stack is done, so let the next read on the
118305097246SAdrian Prantl   // stack refresh its prompt and if there is one...
11847ce2de2cSJonas Devlieghere   if (m_io_handler_stack.IsEmpty())
11854446487dSPavel Labath     return false;
11864446487dSPavel Labath 
11877ce2de2cSJonas Devlieghere   IOHandlerSP reader_sp(m_io_handler_stack.Top());
118830fdc8d8SChris Lattner 
11894446487dSPavel Labath   if (pop_reader_sp != reader_sp)
11904446487dSPavel Labath     return false;
11914446487dSPavel Labath 
119244d93782SGreg Clayton   reader_sp->Deactivate();
1193b4874f1aSGreg Clayton   reader_sp->Cancel();
11947ce2de2cSJonas Devlieghere   m_io_handler_stack.Pop();
119530fdc8d8SChris Lattner 
11967ce2de2cSJonas Devlieghere   reader_sp = m_io_handler_stack.Top();
119730fdc8d8SChris Lattner   if (reader_sp)
119844d93782SGreg Clayton     reader_sp->Activate();
119944d93782SGreg Clayton 
120044d93782SGreg Clayton   return true;
120130fdc8d8SChris Lattner }
12026611103cSGreg Clayton 
GetAsyncOutputStream()1203b9c1b51eSKate Stone StreamSP Debugger::GetAsyncOutputStream() {
1204990d0c71SJonas Devlieghere   return std::make_shared<StreamAsynchronousIO>(*this, true, GetUseColor());
12055b52f0c7SJim Ingham }
12065b52f0c7SJim Ingham 
GetAsyncErrorStream()1207b9c1b51eSKate Stone StreamSP Debugger::GetAsyncErrorStream() {
1208990d0c71SJonas Devlieghere   return std::make_shared<StreamAsynchronousIO>(*this, false, GetUseColor());
12095b52f0c7SJim Ingham }
12105b52f0c7SJim Ingham 
GetNumDebuggers()1211b9c1b51eSKate Stone size_t Debugger::GetNumDebuggers() {
1212b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
12136c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
12146c42e063SGreg Clayton     return g_debugger_list_ptr->size();
1215061858ceSEnrico Granata   }
1216c15f55e2SGreg Clayton   return 0;
1217c15f55e2SGreg Clayton }
1218061858ceSEnrico Granata 
GetDebuggerAtIndex(size_t index)1219b9c1b51eSKate Stone lldb::DebuggerSP Debugger::GetDebuggerAtIndex(size_t index) {
1220061858ceSEnrico Granata   DebuggerSP debugger_sp;
1221061858ceSEnrico Granata 
1222b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
12236c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
12246c42e063SGreg Clayton     if (index < g_debugger_list_ptr->size())
12256c42e063SGreg Clayton       debugger_sp = g_debugger_list_ptr->at(index);
1226c15f55e2SGreg Clayton   }
1227061858ceSEnrico Granata 
1228061858ceSEnrico Granata   return debugger_sp;
1229061858ceSEnrico Granata }
1230061858ceSEnrico Granata 
FindDebuggerWithID(lldb::user_id_t id)1231b9c1b51eSKate Stone DebuggerSP Debugger::FindDebuggerWithID(lldb::user_id_t id) {
12324d122c40SGreg Clayton   DebuggerSP debugger_sp;
1233ebc1bb27SCaroline Tice 
1234b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
12356c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
12366c42e063SGreg Clayton     DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
1237b9c1b51eSKate Stone     for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
1238b9c1b51eSKate Stone       if ((*pos)->GetID() == id) {
1239ebc1bb27SCaroline Tice         debugger_sp = *pos;
1240ebc1bb27SCaroline Tice         break;
1241ebc1bb27SCaroline Tice       }
1242ebc1bb27SCaroline Tice     }
1243c15f55e2SGreg Clayton   }
1244ebc1bb27SCaroline Tice   return debugger_sp;
1245ebc1bb27SCaroline Tice }
12463df9a8dfSCaroline Tice 
FormatDisassemblerAddress(const FormatEntity::Entry * format,const SymbolContext * sc,const SymbolContext * prev_sc,const ExecutionContext * exe_ctx,const Address * addr,Stream & s)1247b9c1b51eSKate Stone bool Debugger::FormatDisassemblerAddress(const FormatEntity::Entry *format,
1248aff1b357SJason Molenda                                          const SymbolContext *sc,
1249aff1b357SJason Molenda                                          const SymbolContext *prev_sc,
1250aff1b357SJason Molenda                                          const ExecutionContext *exe_ctx,
1251b9c1b51eSKate Stone                                          const Address *addr, Stream &s) {
1252554f68d3SGreg Clayton   FormatEntity::Entry format_entry;
1253554f68d3SGreg Clayton 
1254b9c1b51eSKate Stone   if (format == nullptr) {
1255df370550SEugene Zelenko     if (exe_ctx != nullptr && exe_ctx->HasTargetScope())
1256aff1b357SJason Molenda       format = exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat();
1257b9c1b51eSKate Stone     if (format == nullptr) {
1258554f68d3SGreg Clayton       FormatEntity::Parse("${addr}: ", format_entry);
1259554f68d3SGreg Clayton       format = &format_entry;
1260554f68d3SGreg Clayton     }
1261aff1b357SJason Molenda   }
1262aff1b357SJason Molenda   bool function_changed = false;
1263aff1b357SJason Molenda   bool initial_function = false;
1264b9c1b51eSKate Stone   if (prev_sc && (prev_sc->function || prev_sc->symbol)) {
1265b9c1b51eSKate Stone     if (sc && (sc->function || sc->symbol)) {
1266b9c1b51eSKate Stone       if (prev_sc->symbol && sc->symbol) {
1267b9c1b51eSKate Stone         if (!sc->symbol->Compare(prev_sc->symbol->GetName(),
1268b9c1b51eSKate Stone                                  prev_sc->symbol->GetType())) {
1269aff1b357SJason Molenda           function_changed = true;
1270aff1b357SJason Molenda         }
1271b9c1b51eSKate Stone       } else if (prev_sc->function && sc->function) {
1272b9c1b51eSKate Stone         if (prev_sc->function->GetMangled() != sc->function->GetMangled()) {
1273aff1b357SJason Molenda           function_changed = true;
1274aff1b357SJason Molenda         }
1275aff1b357SJason Molenda       }
1276aff1b357SJason Molenda     }
1277aff1b357SJason Molenda   }
127805097246SAdrian Prantl   // The first context on a list of instructions will have a prev_sc that has
127905097246SAdrian Prantl   // no Function or Symbol -- if SymbolContext had an IsValid() method, it
1280aff1b357SJason Molenda   // would return false.  But we do get a prev_sc pointer.
1281b9c1b51eSKate Stone   if ((sc && (sc->function || sc->symbol)) && prev_sc &&
1282b9c1b51eSKate Stone       (prev_sc->function == nullptr && prev_sc->symbol == nullptr)) {
1283aff1b357SJason Molenda     initial_function = true;
1284aff1b357SJason Molenda   }
1285b9c1b51eSKate Stone   return FormatEntity::Format(*format, s, sc, exe_ctx, addr, nullptr,
1286b9c1b51eSKate Stone                               function_changed, initial_function);
1287aff1b357SJason Molenda }
1288aff1b357SJason Molenda 
SetLoggingCallback(lldb::LogOutputCallback log_callback,void * baton)1289b9c1b51eSKate Stone void Debugger::SetLoggingCallback(lldb::LogOutputCallback log_callback,
1290b9c1b51eSKate Stone                                   void *baton) {
12914f02b22dSJim Ingham   // For simplicity's sake, I am not going to deal with how to close down any
12924f02b22dSJim Ingham   // open logging streams, I just redirect everything from here on out to the
12934f02b22dSJim Ingham   // callback.
1294de747565SJonas Devlieghere   m_callback_handler_sp =
1295de747565SJonas Devlieghere       std::make_shared<CallbackLogHandler>(log_callback, baton);
1296228063cdSJim Ingham }
1297228063cdSJim Ingham 
PrivateReportProgress(Debugger & debugger,uint64_t progress_id,const std::string & message,uint64_t completed,uint64_t total,bool is_debugger_specific)1298e122877fSGreg Clayton static void PrivateReportProgress(Debugger &debugger, uint64_t progress_id,
1299e122877fSGreg Clayton                                   const std::string &message,
1300e122877fSGreg Clayton                                   uint64_t completed, uint64_t total,
1301e122877fSGreg Clayton                                   bool is_debugger_specific) {
1302e122877fSGreg Clayton   // Only deliver progress events if we have any progress listeners.
1303e122877fSGreg Clayton   const uint32_t event_type = Debugger::eBroadcastBitProgress;
1304e122877fSGreg Clayton   if (!debugger.GetBroadcaster().EventTypeHasListeners(event_type))
1305e122877fSGreg Clayton     return;
13065e65e79bSJonas Devlieghere   EventSP event_sp(new Event(
13075e65e79bSJonas Devlieghere       event_type, new ProgressEventData(progress_id, message, completed, total,
13085e65e79bSJonas Devlieghere                                         is_debugger_specific)));
1309e122877fSGreg Clayton   debugger.GetBroadcaster().BroadcastEvent(event_sp);
1310e122877fSGreg Clayton }
1311e122877fSGreg Clayton 
ReportProgress(uint64_t progress_id,const std::string & message,uint64_t completed,uint64_t total,llvm::Optional<lldb::user_id_t> debugger_id)1312e122877fSGreg Clayton void Debugger::ReportProgress(uint64_t progress_id, const std::string &message,
1313e122877fSGreg Clayton                               uint64_t completed, uint64_t total,
1314e122877fSGreg Clayton                               llvm::Optional<lldb::user_id_t> debugger_id) {
1315e122877fSGreg Clayton   // Check if this progress is for a specific debugger.
13165413bf1bSKazu Hirata   if (debugger_id) {
1317e122877fSGreg Clayton     // It is debugger specific, grab it and deliver the event if the debugger
1318e122877fSGreg Clayton     // still exists.
1319e122877fSGreg Clayton     DebuggerSP debugger_sp = FindDebuggerWithID(*debugger_id);
1320e122877fSGreg Clayton     if (debugger_sp)
1321e122877fSGreg Clayton       PrivateReportProgress(*debugger_sp, progress_id, message, completed,
1322e122877fSGreg Clayton                             total, /*is_debugger_specific*/ true);
1323e122877fSGreg Clayton     return;
1324e122877fSGreg Clayton   }
1325e122877fSGreg Clayton   // The progress event is not debugger specific, iterate over all debuggers
1326e122877fSGreg Clayton   // and deliver a progress event to each one.
1327e122877fSGreg Clayton   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
1328e122877fSGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
1329e122877fSGreg Clayton     DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
1330e122877fSGreg Clayton     for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos)
1331e122877fSGreg Clayton       PrivateReportProgress(*(*pos), progress_id, message, completed, total,
1332e122877fSGreg Clayton                             /*is_debugger_specific*/ false);
1333e122877fSGreg Clayton   }
1334e122877fSGreg Clayton }
1335e122877fSGreg Clayton 
PrivateReportDiagnostic(Debugger & debugger,DiagnosticEventData::Type type,std::string message,bool debugger_specific)13362fc38b2bSJonas Devlieghere static void PrivateReportDiagnostic(Debugger &debugger,
13372fc38b2bSJonas Devlieghere                                     DiagnosticEventData::Type type,
13382fc38b2bSJonas Devlieghere                                     std::string message,
13392fc38b2bSJonas Devlieghere                                     bool debugger_specific) {
13402fc38b2bSJonas Devlieghere   uint32_t event_type = 0;
13412fc38b2bSJonas Devlieghere   switch (type) {
13422fc38b2bSJonas Devlieghere   case DiagnosticEventData::Type::Warning:
13432fc38b2bSJonas Devlieghere     event_type = Debugger::eBroadcastBitWarning;
13442fc38b2bSJonas Devlieghere     break;
13452fc38b2bSJonas Devlieghere   case DiagnosticEventData::Type::Error:
13462fc38b2bSJonas Devlieghere     event_type = Debugger::eBroadcastBitError;
13472fc38b2bSJonas Devlieghere     break;
13482fc38b2bSJonas Devlieghere   }
13492fc38b2bSJonas Devlieghere 
13502fc38b2bSJonas Devlieghere   Broadcaster &broadcaster = debugger.GetBroadcaster();
13512fc38b2bSJonas Devlieghere   if (!broadcaster.EventTypeHasListeners(event_type)) {
13522fc38b2bSJonas Devlieghere     // Diagnostics are too important to drop. If nobody is listening, print the
13532fc38b2bSJonas Devlieghere     // diagnostic directly to the debugger's error stream.
13542fc38b2bSJonas Devlieghere     DiagnosticEventData event_data(type, std::move(message), debugger_specific);
13552fc38b2bSJonas Devlieghere     StreamSP stream = debugger.GetAsyncErrorStream();
13562fc38b2bSJonas Devlieghere     event_data.Dump(stream.get());
13572fc38b2bSJonas Devlieghere     return;
13582fc38b2bSJonas Devlieghere   }
13592fc38b2bSJonas Devlieghere   EventSP event_sp = std::make_shared<Event>(
13602fc38b2bSJonas Devlieghere       event_type,
13612fc38b2bSJonas Devlieghere       new DiagnosticEventData(type, std::move(message), debugger_specific));
13622fc38b2bSJonas Devlieghere   broadcaster.BroadcastEvent(event_sp);
13632fc38b2bSJonas Devlieghere }
13642fc38b2bSJonas Devlieghere 
ReportDiagnosticImpl(DiagnosticEventData::Type type,std::string message,llvm::Optional<lldb::user_id_t> debugger_id,std::once_flag * once)13652fc38b2bSJonas Devlieghere void Debugger::ReportDiagnosticImpl(DiagnosticEventData::Type type,
13662fc38b2bSJonas Devlieghere                                     std::string message,
13672fc38b2bSJonas Devlieghere                                     llvm::Optional<lldb::user_id_t> debugger_id,
13682fc38b2bSJonas Devlieghere                                     std::once_flag *once) {
13692fc38b2bSJonas Devlieghere   auto ReportDiagnosticLambda = [&]() {
13702fc38b2bSJonas Devlieghere     // Check if this progress is for a specific debugger.
13712fc38b2bSJonas Devlieghere     if (debugger_id) {
13722fc38b2bSJonas Devlieghere       // It is debugger specific, grab it and deliver the event if the debugger
13732fc38b2bSJonas Devlieghere       // still exists.
13742fc38b2bSJonas Devlieghere       DebuggerSP debugger_sp = FindDebuggerWithID(*debugger_id);
13752fc38b2bSJonas Devlieghere       if (debugger_sp)
13762fc38b2bSJonas Devlieghere         PrivateReportDiagnostic(*debugger_sp, type, std::move(message), true);
13772fc38b2bSJonas Devlieghere       return;
13782fc38b2bSJonas Devlieghere     }
13792fc38b2bSJonas Devlieghere     // The progress event is not debugger specific, iterate over all debuggers
13802fc38b2bSJonas Devlieghere     // and deliver a progress event to each one.
13812fc38b2bSJonas Devlieghere     if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
13822fc38b2bSJonas Devlieghere       std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
13832fc38b2bSJonas Devlieghere       for (const auto &debugger : *g_debugger_list_ptr)
13842fc38b2bSJonas Devlieghere         PrivateReportDiagnostic(*debugger, type, message, false);
13852fc38b2bSJonas Devlieghere     }
13862fc38b2bSJonas Devlieghere   };
13872fc38b2bSJonas Devlieghere 
13882fc38b2bSJonas Devlieghere   if (once)
13892fc38b2bSJonas Devlieghere     std::call_once(*once, ReportDiagnosticLambda);
13902fc38b2bSJonas Devlieghere   else
13912fc38b2bSJonas Devlieghere     ReportDiagnosticLambda();
13922fc38b2bSJonas Devlieghere }
13932fc38b2bSJonas Devlieghere 
ReportWarning(std::string message,llvm::Optional<lldb::user_id_t> debugger_id,std::once_flag * once)13942fc38b2bSJonas Devlieghere void Debugger::ReportWarning(std::string message,
13952fc38b2bSJonas Devlieghere                              llvm::Optional<lldb::user_id_t> debugger_id,
13962fc38b2bSJonas Devlieghere                              std::once_flag *once) {
13972fc38b2bSJonas Devlieghere   ReportDiagnosticImpl(DiagnosticEventData::Type::Warning, std::move(message),
13982fc38b2bSJonas Devlieghere                        debugger_id, once);
13992fc38b2bSJonas Devlieghere }
14002fc38b2bSJonas Devlieghere 
ReportError(std::string message,llvm::Optional<lldb::user_id_t> debugger_id,std::once_flag * once)14012fc38b2bSJonas Devlieghere void Debugger::ReportError(std::string message,
14022fc38b2bSJonas Devlieghere                            llvm::Optional<lldb::user_id_t> debugger_id,
14032fc38b2bSJonas Devlieghere                            std::once_flag *once) {
14042fc38b2bSJonas Devlieghere 
14052fc38b2bSJonas Devlieghere   ReportDiagnosticImpl(DiagnosticEventData::Type::Error, std::move(message),
14062fc38b2bSJonas Devlieghere                        debugger_id, once);
14072fc38b2bSJonas Devlieghere }
14082fc38b2bSJonas Devlieghere 
1409be265d25SJonas Devlieghere static std::shared_ptr<LogHandler>
CreateLogHandler(LogHandlerKind log_handler_kind,int fd,bool should_close,size_t buffer_size)1410be265d25SJonas Devlieghere CreateLogHandler(LogHandlerKind log_handler_kind, int fd, bool should_close,
1411be265d25SJonas Devlieghere                  size_t buffer_size) {
1412be265d25SJonas Devlieghere   switch (log_handler_kind) {
1413be265d25SJonas Devlieghere   case eLogHandlerStream:
1414be265d25SJonas Devlieghere     return std::make_shared<StreamLogHandler>(fd, should_close, buffer_size);
1415be265d25SJonas Devlieghere   case eLogHandlerCircular:
1416be265d25SJonas Devlieghere     return std::make_shared<RotatingLogHandler>(buffer_size);
1417be265d25SJonas Devlieghere   case eLogHandlerSystem:
1418be265d25SJonas Devlieghere     return std::make_shared<SystemLogHandler>();
1419be265d25SJonas Devlieghere   case eLogHandlerCallback:
1420be265d25SJonas Devlieghere     return {};
1421be265d25SJonas Devlieghere   }
1422be265d25SJonas Devlieghere   return {};
1423be265d25SJonas Devlieghere }
1424be265d25SJonas Devlieghere 
EnableLog(llvm::StringRef channel,llvm::ArrayRef<const char * > categories,llvm::StringRef log_file,uint32_t log_options,size_t buffer_size,LogHandlerKind log_handler_kind,llvm::raw_ostream & error_stream)14255e336903SPavel Labath bool Debugger::EnableLog(llvm::StringRef channel,
14265e336903SPavel Labath                          llvm::ArrayRef<const char *> categories,
14275e336903SPavel Labath                          llvm::StringRef log_file, uint32_t log_options,
1428be265d25SJonas Devlieghere                          size_t buffer_size, LogHandlerKind log_handler_kind,
1429be265d25SJonas Devlieghere                          llvm::raw_ostream &error_stream) {
14305fae71c5SPavel Labath 
14316ff49af3SJonas Devlieghere   std::shared_ptr<LogHandler> log_handler_sp;
14326ff49af3SJonas Devlieghere   if (m_callback_handler_sp) {
14336ff49af3SJonas Devlieghere     log_handler_sp = m_callback_handler_sp;
1434228063cdSJim Ingham     // For now when using the callback mode you always get thread & timestamp.
1435b9c1b51eSKate Stone     log_options |=
1436b9c1b51eSKate Stone         LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_THREAD_NAME;
14375e336903SPavel Labath   } else if (log_file.empty()) {
1438be265d25SJonas Devlieghere     log_handler_sp =
1439be265d25SJonas Devlieghere         CreateLogHandler(log_handler_kind, GetOutputFile().GetDescriptor(),
1440be265d25SJonas Devlieghere                          /*should_close=*/false, buffer_size);
1441b9c1b51eSKate Stone   } else {
14426ff49af3SJonas Devlieghere     auto pos = m_stream_handlers.find(log_file);
14436ff49af3SJonas Devlieghere     if (pos != m_stream_handlers.end())
14446ff49af3SJonas Devlieghere       log_handler_sp = pos->second.lock();
14456ff49af3SJonas Devlieghere     if (!log_handler_sp) {
14466b2e6765SJonas Devlieghere       File::OpenOptions flags =
144714735cabSMichał Górny           File::eOpenOptionWriteOnly | File::eOpenOptionCanCreate;
14485fae71c5SPavel Labath       if (log_options & LLDB_LOG_OPTION_APPEND)
14496b2e6765SJonas Devlieghere         flags |= File::eOpenOptionAppend;
14506b2e6765SJonas Devlieghere       else
14516b2e6765SJonas Devlieghere         flags |= File::eOpenOptionTruncate;
1452867c347cSRaphael Isemann       llvm::Expected<FileUP> file = FileSystem::Instance().Open(
14536b2e6765SJonas Devlieghere           FileSpec(log_file), flags, lldb::eFilePermissionsFileDefault, false);
14546b2e6765SJonas Devlieghere       if (!file) {
1455867c347cSRaphael Isemann         error_stream << "Unable to open log file '" << log_file
1456867c347cSRaphael Isemann                      << "': " << llvm::toString(file.takeError()) << "\n";
14575fae71c5SPavel Labath         return false;
14585fae71c5SPavel Labath       }
14596b2e6765SJonas Devlieghere 
1460be265d25SJonas Devlieghere       log_handler_sp =
1461be265d25SJonas Devlieghere           CreateLogHandler(log_handler_kind, (*file)->GetDescriptor(),
1462be265d25SJonas Devlieghere                            /*should_close=*/true, buffer_size);
14636ff49af3SJonas Devlieghere       m_stream_handlers[log_file] = log_handler_sp;
1464228063cdSJim Ingham     }
1465228063cdSJim Ingham   }
14666ff49af3SJonas Devlieghere   assert(log_handler_sp);
1467228063cdSJim Ingham 
1468228063cdSJim Ingham   if (log_options == 0)
146970841b97SJonas Devlieghere     log_options = LLDB_LOG_OPTION_PREPEND_THREAD_NAME;
1470228063cdSJim Ingham 
14716ff49af3SJonas Devlieghere   return Log::EnableLogChannel(log_handler_sp, log_options, channel, categories,
1472b9c1b51eSKate Stone                                error_stream);
1473228063cdSJim Ingham }
1474228063cdSJim Ingham 
1475bbf70c04SJonas Devlieghere ScriptInterpreter *
GetScriptInterpreter(bool can_create,llvm::Optional<lldb::ScriptLanguage> language)1476bbf70c04SJonas Devlieghere Debugger::GetScriptInterpreter(bool can_create,
1477bbf70c04SJonas Devlieghere                                llvm::Optional<lldb::ScriptLanguage> language) {
14782b29b432SJonas Devlieghere   std::lock_guard<std::recursive_mutex> locker(m_script_interpreter_mutex);
1479bbf70c04SJonas Devlieghere   lldb::ScriptLanguage script_language =
1480bbf70c04SJonas Devlieghere       language ? *language : GetScriptLanguage();
14812b29b432SJonas Devlieghere 
1482bbf70c04SJonas Devlieghere   if (!m_script_interpreters[script_language]) {
14832b29b432SJonas Devlieghere     if (!can_create)
14842b29b432SJonas Devlieghere       return nullptr;
1485bbf70c04SJonas Devlieghere     m_script_interpreters[script_language] =
1486bbf70c04SJonas Devlieghere         PluginManager::GetScriptInterpreterForLanguage(script_language, *this);
14872b29b432SJonas Devlieghere   }
14882b29b432SJonas Devlieghere 
1489bbf70c04SJonas Devlieghere   return m_script_interpreters[script_language].get();
14902b29b432SJonas Devlieghere }
14912b29b432SJonas Devlieghere 
GetSourceManager()1492b9c1b51eSKate Stone SourceManager &Debugger::GetSourceManager() {
1493d5b44036SJonas Devlieghere   if (!m_source_manager_up)
1494a8f3ae7cSJonas Devlieghere     m_source_manager_up = std::make_unique<SourceManager>(shared_from_this());
1495d5b44036SJonas Devlieghere   return *m_source_manager_up;
14969585fbfcSGreg Clayton }
14979585fbfcSGreg Clayton 
149844d93782SGreg Clayton // This function handles events that were broadcast by the process.
HandleBreakpointEvent(const EventSP & event_sp)1499b9c1b51eSKate Stone void Debugger::HandleBreakpointEvent(const EventSP &event_sp) {
150044d93782SGreg Clayton   using namespace lldb;
1501b9c1b51eSKate Stone   const uint32_t event_type =
1502b9c1b51eSKate Stone       Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent(
1503b9c1b51eSKate Stone           event_sp);
150444d93782SGreg Clayton 
150544d93782SGreg Clayton   //    if (event_type & eBreakpointEventTypeAdded
150644d93782SGreg Clayton   //        || event_type & eBreakpointEventTypeRemoved
150744d93782SGreg Clayton   //        || event_type & eBreakpointEventTypeEnabled
150844d93782SGreg Clayton   //        || event_type & eBreakpointEventTypeDisabled
150944d93782SGreg Clayton   //        || event_type & eBreakpointEventTypeCommandChanged
151044d93782SGreg Clayton   //        || event_type & eBreakpointEventTypeConditionChanged
151144d93782SGreg Clayton   //        || event_type & eBreakpointEventTypeIgnoreChanged
151244d93782SGreg Clayton   //        || event_type & eBreakpointEventTypeLocationsResolved)
151344d93782SGreg Clayton   //    {
1514b9c1b51eSKate Stone   //        // Don't do anything about these events, since the breakpoint
1515b9c1b51eSKate Stone   //        commands already echo these actions.
151644d93782SGreg Clayton   //    }
151744d93782SGreg Clayton   //
1518b9c1b51eSKate Stone   if (event_type & eBreakpointEventTypeLocationsAdded) {
1519b9c1b51eSKate Stone     uint32_t num_new_locations =
1520b9c1b51eSKate Stone         Breakpoint::BreakpointEventData::GetNumBreakpointLocationsFromEvent(
1521b9c1b51eSKate Stone             event_sp);
1522b9c1b51eSKate Stone     if (num_new_locations > 0) {
1523b9c1b51eSKate Stone       BreakpointSP breakpoint =
1524b9c1b51eSKate Stone           Breakpoint::BreakpointEventData::GetBreakpointFromEvent(event_sp);
15254446487dSPavel Labath       StreamSP output_sp(GetAsyncOutputStream());
1526b9c1b51eSKate Stone       if (output_sp) {
152744d93782SGreg Clayton         output_sp->Printf("%d location%s added to breakpoint %d\n",
1528b9c1b51eSKate Stone                           num_new_locations, num_new_locations == 1 ? "" : "s",
152944d93782SGreg Clayton                           breakpoint->GetID());
15304446487dSPavel Labath         output_sp->Flush();
153144d93782SGreg Clayton       }
153244d93782SGreg Clayton     }
153344d93782SGreg Clayton   }
153444d93782SGreg Clayton   //    else if (event_type & eBreakpointEventTypeLocationsRemoved)
153544d93782SGreg Clayton   //    {
1536b9c1b51eSKate Stone   //        // These locations just get disabled, not sure it is worth spamming
1537b9c1b51eSKate Stone   //        folks about this on the command line.
153844d93782SGreg Clayton   //    }
153944d93782SGreg Clayton   //    else if (event_type & eBreakpointEventTypeLocationsResolved)
154044d93782SGreg Clayton   //    {
1541b9c1b51eSKate Stone   //        // This might be an interesting thing to note, but I'm going to
1542b9c1b51eSKate Stone   //        leave it quiet for now, it just looked noisy.
154344d93782SGreg Clayton   //    }
154444d93782SGreg Clayton }
154544d93782SGreg Clayton 
FlushProcessOutput(Process & process,bool flush_stdout,bool flush_stderr)1546a9d58436SPavel Labath void Debugger::FlushProcessOutput(Process &process, bool flush_stdout,
1547a9d58436SPavel Labath                                   bool flush_stderr) {
1548a9d58436SPavel Labath   const auto &flush = [&](Stream &stream,
1549a9d58436SPavel Labath                           size_t (Process::*get)(char *, size_t, Status &)) {
155097206d57SZachary Turner     Status error;
155144d93782SGreg Clayton     size_t len;
1552a9d58436SPavel Labath     char buffer[1024];
1553a9d58436SPavel Labath     while ((len = (process.*get)(buffer, sizeof(buffer), error)) > 0)
1554a9d58436SPavel Labath       stream.Write(buffer, len);
1555a9d58436SPavel Labath     stream.Flush();
1556a9d58436SPavel Labath   };
155744d93782SGreg Clayton 
1558a9d58436SPavel Labath   std::lock_guard<std::mutex> guard(m_output_flush_mutex);
1559a9d58436SPavel Labath   if (flush_stdout)
1560a9d58436SPavel Labath     flush(*GetAsyncOutputStream(), &Process::GetSTDOUT);
1561a9d58436SPavel Labath   if (flush_stderr)
1562a9d58436SPavel Labath     flush(*GetAsyncErrorStream(), &Process::GetSTDERR);
156344d93782SGreg Clayton }
156444d93782SGreg Clayton 
156544d93782SGreg Clayton // This function handles events that were broadcast by the process.
HandleProcessEvent(const EventSP & event_sp)1566b9c1b51eSKate Stone void Debugger::HandleProcessEvent(const EventSP &event_sp) {
156744d93782SGreg Clayton   using namespace lldb;
156844d93782SGreg Clayton   const uint32_t event_type = event_sp->GetType();
1569b9c1b51eSKate Stone   ProcessSP process_sp =
1570b9c1b51eSKate Stone       (event_type == Process::eBroadcastBitStructuredData)
157175930019STodd Fiala           ? EventDataStructuredData::GetProcessFromEvent(event_sp.get())
157275930019STodd Fiala           : Process::ProcessEventData::GetProcessFromEvent(event_sp.get());
157344d93782SGreg Clayton 
15744446487dSPavel Labath   StreamSP output_stream_sp = GetAsyncOutputStream();
15754446487dSPavel Labath   StreamSP error_stream_sp = GetAsyncErrorStream();
157644d93782SGreg Clayton   const bool gui_enabled = IsForwardingEvents();
157744d93782SGreg Clayton 
1578b9c1b51eSKate Stone   if (!gui_enabled) {
1579b4874f1aSGreg Clayton     bool pop_process_io_handler = false;
158044d93782SGreg Clayton     assert(process_sp);
158144d93782SGreg Clayton 
15824446487dSPavel Labath     bool state_is_stopped = false;
1583b9c1b51eSKate Stone     const bool got_state_changed =
1584b9c1b51eSKate Stone         (event_type & Process::eBroadcastBitStateChanged) != 0;
15854446487dSPavel Labath     const bool got_stdout = (event_type & Process::eBroadcastBitSTDOUT) != 0;
15864446487dSPavel Labath     const bool got_stderr = (event_type & Process::eBroadcastBitSTDERR) != 0;
1587b9c1b51eSKate Stone     const bool got_structured_data =
1588b9c1b51eSKate Stone         (event_type & Process::eBroadcastBitStructuredData) != 0;
158975930019STodd Fiala 
1590b9c1b51eSKate Stone     if (got_state_changed) {
1591b9c1b51eSKate Stone       StateType event_state =
1592b9c1b51eSKate Stone           Process::ProcessEventData::GetStateFromEvent(event_sp.get());
15934446487dSPavel Labath       state_is_stopped = StateIsStoppedState(event_state, false);
159444d93782SGreg Clayton     }
1595b4874f1aSGreg Clayton 
15964446487dSPavel Labath     // Display running state changes first before any STDIO
1597b9c1b51eSKate Stone     if (got_state_changed && !state_is_stopped) {
1598b9c1b51eSKate Stone       Process::HandleProcessStateChangedEvent(event_sp, output_stream_sp.get(),
1599b9c1b51eSKate Stone                                               pop_process_io_handler);
160044d93782SGreg Clayton     }
1601b4874f1aSGreg Clayton 
1602a9d58436SPavel Labath     // Now display STDOUT and STDERR
1603a9d58436SPavel Labath     FlushProcessOutput(*process_sp, got_stdout || got_state_changed,
1604a9d58436SPavel Labath                        got_stderr || got_state_changed);
1605b4874f1aSGreg Clayton 
160675930019STodd Fiala     // Give structured data events an opportunity to display.
1607b9c1b51eSKate Stone     if (got_structured_data) {
160875930019STodd Fiala       StructuredDataPluginSP plugin_sp =
160975930019STodd Fiala           EventDataStructuredData::GetPluginFromEvent(event_sp.get());
1610b9c1b51eSKate Stone       if (plugin_sp) {
161175930019STodd Fiala         auto structured_data_sp =
161275930019STodd Fiala             EventDataStructuredData::GetObjectFromEvent(event_sp.get());
1613b9c1b51eSKate Stone         if (output_stream_sp) {
161475930019STodd Fiala           StreamString content_stream;
161597206d57SZachary Turner           Status error =
1616b9c1b51eSKate Stone               plugin_sp->GetDescription(structured_data_sp, content_stream);
1617b9c1b51eSKate Stone           if (error.Success()) {
1618b9c1b51eSKate Stone             if (!content_stream.GetString().empty()) {
161975930019STodd Fiala               // Add newline.
162075930019STodd Fiala               content_stream.PutChar('\n');
162175930019STodd Fiala               content_stream.Flush();
162275930019STodd Fiala 
162375930019STodd Fiala               // Print it.
1624771ef6d4SMalcolm Parsons               output_stream_sp->PutCString(content_stream.GetString());
162575930019STodd Fiala             }
1626b9c1b51eSKate Stone           } else {
1627a3939e15SPavel Labath             error_stream_sp->Format("Failed to print structured "
1628a3939e15SPavel Labath                                     "data with plugin {0}: {1}",
1629a3939e15SPavel Labath                                     plugin_sp->GetPluginName(), error);
163075930019STodd Fiala           }
163175930019STodd Fiala         }
163275930019STodd Fiala       }
163375930019STodd Fiala     }
163475930019STodd Fiala 
16354446487dSPavel Labath     // Now display any stopped state changes after any STDIO
1636b9c1b51eSKate Stone     if (got_state_changed && state_is_stopped) {
1637b9c1b51eSKate Stone       Process::HandleProcessStateChangedEvent(event_sp, output_stream_sp.get(),
1638b9c1b51eSKate Stone                                               pop_process_io_handler);
163944d93782SGreg Clayton     }
164044d93782SGreg Clayton 
16414446487dSPavel Labath     output_stream_sp->Flush();
16424446487dSPavel Labath     error_stream_sp->Flush();
164344d93782SGreg Clayton 
1644b4874f1aSGreg Clayton     if (pop_process_io_handler)
1645b4874f1aSGreg Clayton       process_sp->PopProcessIOHandler();
1646b4874f1aSGreg Clayton   }
1647b4874f1aSGreg Clayton }
1648b4874f1aSGreg Clayton 
HandleThreadEvent(const EventSP & event_sp)1649b9c1b51eSKate Stone void Debugger::HandleThreadEvent(const EventSP &event_sp) {
165005097246SAdrian Prantl   // At present the only thread event we handle is the Frame Changed event, and
165105097246SAdrian Prantl   // all we do for that is just reprint the thread status for that thread.
165244d93782SGreg Clayton   using namespace lldb;
165344d93782SGreg Clayton   const uint32_t event_type = event_sp->GetType();
16546a9767c7SJim Ingham   const bool stop_format = true;
165544d93782SGreg Clayton   if (event_type == Thread::eBroadcastBitStackChanged ||
1656b9c1b51eSKate Stone       event_type == Thread::eBroadcastBitThreadSelected) {
1657b9c1b51eSKate Stone     ThreadSP thread_sp(
1658b9c1b51eSKate Stone         Thread::ThreadEventData::GetThreadFromEvent(event_sp.get()));
1659b9c1b51eSKate Stone     if (thread_sp) {
16606a9767c7SJim Ingham       thread_sp->GetStatus(*GetAsyncOutputStream(), 0, 1, 1, stop_format);
166144d93782SGreg Clayton     }
166244d93782SGreg Clayton   }
166344d93782SGreg Clayton }
166444d93782SGreg Clayton 
IsForwardingEvents()1665b9c1b51eSKate Stone bool Debugger::IsForwardingEvents() { return (bool)m_forward_listener_sp; }
166644d93782SGreg Clayton 
EnableForwardEvents(const ListenerSP & listener_sp)1667b9c1b51eSKate Stone void Debugger::EnableForwardEvents(const ListenerSP &listener_sp) {
166844d93782SGreg Clayton   m_forward_listener_sp = listener_sp;
166944d93782SGreg Clayton }
167044d93782SGreg Clayton 
CancelForwardEvents(const ListenerSP & listener_sp)1671b9c1b51eSKate Stone void Debugger::CancelForwardEvents(const ListenerSP &listener_sp) {
167244d93782SGreg Clayton   m_forward_listener_sp.reset();
167344d93782SGreg Clayton }
167444d93782SGreg Clayton 
DefaultEventHandler()1675d0810779SPavel Labath lldb::thread_result_t Debugger::DefaultEventHandler() {
1676583bbb1dSJim Ingham   ListenerSP listener_sp(GetListener());
167744d93782SGreg Clayton   ConstString broadcaster_class_target(Target::GetStaticBroadcasterClass());
167844d93782SGreg Clayton   ConstString broadcaster_class_process(Process::GetStaticBroadcasterClass());
167944d93782SGreg Clayton   ConstString broadcaster_class_thread(Thread::GetStaticBroadcasterClass());
168044d93782SGreg Clayton   BroadcastEventSpec target_event_spec(broadcaster_class_target,
168144d93782SGreg Clayton                                        Target::eBroadcastBitBreakpointChanged);
168244d93782SGreg Clayton 
1683b9c1b51eSKate Stone   BroadcastEventSpec process_event_spec(
1684b9c1b51eSKate Stone       broadcaster_class_process,
1685b9c1b51eSKate Stone       Process::eBroadcastBitStateChanged | Process::eBroadcastBitSTDOUT |
1686b9c1b51eSKate Stone           Process::eBroadcastBitSTDERR | Process::eBroadcastBitStructuredData);
168744d93782SGreg Clayton 
168844d93782SGreg Clayton   BroadcastEventSpec thread_event_spec(broadcaster_class_thread,
168944d93782SGreg Clayton                                        Thread::eBroadcastBitStackChanged |
169044d93782SGreg Clayton                                            Thread::eBroadcastBitThreadSelected);
169144d93782SGreg Clayton 
1692b9c1b51eSKate Stone   listener_sp->StartListeningForEventSpec(m_broadcaster_manager_sp,
1693b9c1b51eSKate Stone                                           target_event_spec);
1694b9c1b51eSKate Stone   listener_sp->StartListeningForEventSpec(m_broadcaster_manager_sp,
1695b9c1b51eSKate Stone                                           process_event_spec);
1696b9c1b51eSKate Stone   listener_sp->StartListeningForEventSpec(m_broadcaster_manager_sp,
1697b9c1b51eSKate Stone                                           thread_event_spec);
1698b9c1b51eSKate Stone   listener_sp->StartListeningForEvents(
1699d5b44036SJonas Devlieghere       m_command_interpreter_up.get(),
170044d93782SGreg Clayton       CommandInterpreter::eBroadcastBitQuitCommandReceived |
170144d93782SGreg Clayton           CommandInterpreter::eBroadcastBitAsynchronousOutputData |
170244d93782SGreg Clayton           CommandInterpreter::eBroadcastBitAsynchronousErrorData);
170344d93782SGreg Clayton 
17042fc38b2bSJonas Devlieghere   listener_sp->StartListeningForEvents(
17052fc38b2bSJonas Devlieghere       &m_broadcaster,
17062fc38b2bSJonas Devlieghere       eBroadcastBitProgress | eBroadcastBitWarning | eBroadcastBitError);
17075a27b998SJonas Devlieghere 
170805097246SAdrian Prantl   // Let the thread that spawned us know that we have started up and that we
170905097246SAdrian Prantl   // are now listening to all required events so no events get missed
1710afa91e33SGreg Clayton   m_sync_broadcaster.BroadcastEvent(eBroadcastBitEventThreadIsListening);
1711afa91e33SGreg Clayton 
171244d93782SGreg Clayton   bool done = false;
1713b9c1b51eSKate Stone   while (!done) {
171444d93782SGreg Clayton     EventSP event_sp;
1715d35031e1SPavel Labath     if (listener_sp->GetEvent(event_sp, llvm::None)) {
1716b9c1b51eSKate Stone       if (event_sp) {
171744d93782SGreg Clayton         Broadcaster *broadcaster = event_sp->GetBroadcaster();
1718b9c1b51eSKate Stone         if (broadcaster) {
171944d93782SGreg Clayton           uint32_t event_type = event_sp->GetType();
172044d93782SGreg Clayton           ConstString broadcaster_class(broadcaster->GetBroadcasterClass());
1721b9c1b51eSKate Stone           if (broadcaster_class == broadcaster_class_process) {
172244d93782SGreg Clayton             HandleProcessEvent(event_sp);
1723b9c1b51eSKate Stone           } else if (broadcaster_class == broadcaster_class_target) {
1724b9c1b51eSKate Stone             if (Breakpoint::BreakpointEventData::GetEventDataFromEvent(
1725b9c1b51eSKate Stone                     event_sp.get())) {
172644d93782SGreg Clayton               HandleBreakpointEvent(event_sp);
172744d93782SGreg Clayton             }
1728b9c1b51eSKate Stone           } else if (broadcaster_class == broadcaster_class_thread) {
172944d93782SGreg Clayton             HandleThreadEvent(event_sp);
1730d5b44036SJonas Devlieghere           } else if (broadcaster == m_command_interpreter_up.get()) {
1731b9c1b51eSKate Stone             if (event_type &
1732b9c1b51eSKate Stone                 CommandInterpreter::eBroadcastBitQuitCommandReceived) {
173344d93782SGreg Clayton               done = true;
1734b9c1b51eSKate Stone             } else if (event_type &
1735b9c1b51eSKate Stone                        CommandInterpreter::eBroadcastBitAsynchronousErrorData) {
173665fdb342SRaphael Isemann               const char *data = static_cast<const char *>(
1737b9c1b51eSKate Stone                   EventDataBytes::GetBytesFromEvent(event_sp.get()));
1738b9c1b51eSKate Stone               if (data && data[0]) {
17394446487dSPavel Labath                 StreamSP error_sp(GetAsyncErrorStream());
1740b9c1b51eSKate Stone                 if (error_sp) {
174144d93782SGreg Clayton                   error_sp->PutCString(data);
174244d93782SGreg Clayton                   error_sp->Flush();
174344d93782SGreg Clayton                 }
174444d93782SGreg Clayton               }
1745b9c1b51eSKate Stone             } else if (event_type & CommandInterpreter::
1746b9c1b51eSKate Stone                                         eBroadcastBitAsynchronousOutputData) {
174765fdb342SRaphael Isemann               const char *data = static_cast<const char *>(
1748b9c1b51eSKate Stone                   EventDataBytes::GetBytesFromEvent(event_sp.get()));
1749b9c1b51eSKate Stone               if (data && data[0]) {
17504446487dSPavel Labath                 StreamSP output_sp(GetAsyncOutputStream());
1751b9c1b51eSKate Stone                 if (output_sp) {
175244d93782SGreg Clayton                   output_sp->PutCString(data);
175344d93782SGreg Clayton                   output_sp->Flush();
175444d93782SGreg Clayton                 }
175544d93782SGreg Clayton               }
175644d93782SGreg Clayton             }
17575a27b998SJonas Devlieghere           } else if (broadcaster == &m_broadcaster) {
17585a27b998SJonas Devlieghere             if (event_type & Debugger::eBroadcastBitProgress)
17595a27b998SJonas Devlieghere               HandleProgressEvent(event_sp);
17602fc38b2bSJonas Devlieghere             else if (event_type & Debugger::eBroadcastBitWarning)
17612fc38b2bSJonas Devlieghere               HandleDiagnosticEvent(event_sp);
17622fc38b2bSJonas Devlieghere             else if (event_type & Debugger::eBroadcastBitError)
17632fc38b2bSJonas Devlieghere               HandleDiagnosticEvent(event_sp);
176444d93782SGreg Clayton           }
176544d93782SGreg Clayton         }
176644d93782SGreg Clayton 
176744d93782SGreg Clayton         if (m_forward_listener_sp)
176844d93782SGreg Clayton           m_forward_listener_sp->AddEvent(event_sp);
176944d93782SGreg Clayton       }
177044d93782SGreg Clayton     }
177144d93782SGreg Clayton   }
177285200645SKonrad Kleine   return {};
177344d93782SGreg Clayton }
177444d93782SGreg Clayton 
StartEventHandlerThread()1775b9c1b51eSKate Stone bool Debugger::StartEventHandlerThread() {
1776b9c1b51eSKate Stone   if (!m_event_handler_thread.IsJoinable()) {
177705097246SAdrian Prantl     // We must synchronize with the DefaultEventHandler() thread to ensure it
177805097246SAdrian Prantl     // is up and running and listening to events before we return from this
177905097246SAdrian Prantl     // function. We do this by listening to events for the
1780afa91e33SGreg Clayton     // eBroadcastBitEventThreadIsListening from the m_sync_broadcaster
17811a728f66STatyana Krasnukha     ConstString full_name("lldb.debugger.event-handler");
17821a728f66STatyana Krasnukha     ListenerSP listener_sp(Listener::MakeListener(full_name.AsCString()));
1783b9c1b51eSKate Stone     listener_sp->StartListeningForEvents(&m_sync_broadcaster,
1784b9c1b51eSKate Stone                                          eBroadcastBitEventThreadIsListening);
1785afa91e33SGreg Clayton 
1786642bc15dSRaphael Isemann     llvm::StringRef thread_name =
1787e063ecccSJonas Devlieghere         full_name.GetLength() < llvm::get_max_thread_name_length()
1788642bc15dSRaphael Isemann             ? full_name.GetStringRef()
1789e063ecccSJonas Devlieghere             : "dbg.evt-handler";
17901a728f66STatyana Krasnukha 
17917c2896a2SZachary Turner     // Use larger 8MB stack for this thread
1792f39c2e18SJonas Devlieghere     llvm::Expected<HostThread> event_handler_thread =
1793d0810779SPavel Labath         ThreadLauncher::LaunchThread(
1794d0810779SPavel Labath             thread_name, [this] { return DefaultEventHandler(); },
1795f39c2e18SJonas Devlieghere             g_debugger_event_thread_stack_bytes);
1796f39c2e18SJonas Devlieghere 
1797f39c2e18SJonas Devlieghere     if (event_handler_thread) {
1798f39c2e18SJonas Devlieghere       m_event_handler_thread = *event_handler_thread;
1799f39c2e18SJonas Devlieghere     } else {
1800a007a6d8SPavel Labath       LLDB_LOG(GetLog(LLDBLog::Host), "failed to launch host thread: {}",
1801f39c2e18SJonas Devlieghere                llvm::toString(event_handler_thread.takeError()));
1802f39c2e18SJonas Devlieghere     }
1803afa91e33SGreg Clayton 
180405097246SAdrian Prantl     // Make sure DefaultEventHandler() is running and listening to events
180505097246SAdrian Prantl     // before we return from this function. We are only listening for events of
180605097246SAdrian Prantl     // type eBroadcastBitEventThreadIsListening so we don't need to check the
180705097246SAdrian Prantl     // event, we just need to wait an infinite amount of time for it (nullptr
180805097246SAdrian Prantl     // timeout as the first parameter)
1809afa91e33SGreg Clayton     lldb::EventSP event_sp;
1810d35031e1SPavel Labath     listener_sp->GetEvent(event_sp, llvm::None);
1811807b6b32SGreg Clayton   }
1812acee96aeSZachary Turner   return m_event_handler_thread.IsJoinable();
181344d93782SGreg Clayton }
181444d93782SGreg Clayton 
StopEventHandlerThread()1815b9c1b51eSKate Stone void Debugger::StopEventHandlerThread() {
1816b9c1b51eSKate Stone   if (m_event_handler_thread.IsJoinable()) {
1817b9c1b51eSKate Stone     GetCommandInterpreter().BroadcastEvent(
1818b9c1b51eSKate Stone         CommandInterpreter::eBroadcastBitQuitCommandReceived);
181939de3110SZachary Turner     m_event_handler_thread.Join(nullptr);
182044d93782SGreg Clayton   }
182144d93782SGreg Clayton }
182244d93782SGreg Clayton 
IOHandlerThread()1823d0810779SPavel Labath lldb::thread_result_t Debugger::IOHandlerThread() {
1824d0810779SPavel Labath   RunIOHandlers();
1825d0810779SPavel Labath   StopEventHandlerThread();
182685200645SKonrad Kleine   return {};
182744d93782SGreg Clayton }
182844d93782SGreg Clayton 
HandleProgressEvent(const lldb::EventSP & event_sp)18295a27b998SJonas Devlieghere void Debugger::HandleProgressEvent(const lldb::EventSP &event_sp) {
18305e65e79bSJonas Devlieghere   auto *data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
18315a27b998SJonas Devlieghere   if (!data)
18325a27b998SJonas Devlieghere     return;
18335a27b998SJonas Devlieghere 
18345a27b998SJonas Devlieghere   // Do some bookkeeping for the current event, regardless of whether we're
18355a27b998SJonas Devlieghere   // going to show the progress.
18365a27b998SJonas Devlieghere   const uint64_t id = data->GetID();
18375a27b998SJonas Devlieghere   if (m_current_event_id) {
1838ea8b811bSMed Ismail Bennani     Log *log = GetLog(LLDBLog::Events);
1839ea8b811bSMed Ismail Bennani     if (log && log->GetVerbose()) {
1840ea8b811bSMed Ismail Bennani       StreamString log_stream;
1841ea8b811bSMed Ismail Bennani       log_stream.AsRawOstream()
1842ea8b811bSMed Ismail Bennani           << static_cast<void *>(this) << " Debugger(" << GetID()
1843ea8b811bSMed Ismail Bennani           << ")::HandleProgressEvent( m_current_event_id = "
1844ea8b811bSMed Ismail Bennani           << *m_current_event_id << ", data = { ";
1845ea8b811bSMed Ismail Bennani       data->Dump(&log_stream);
1846ea8b811bSMed Ismail Bennani       log_stream << " } )";
1847ea8b811bSMed Ismail Bennani       log->PutString(log_stream.GetString());
1848ea8b811bSMed Ismail Bennani     }
18495a27b998SJonas Devlieghere     if (id != *m_current_event_id)
18505a27b998SJonas Devlieghere       return;
1851ea8b811bSMed Ismail Bennani     if (data->GetCompleted() == data->GetTotal())
18525a27b998SJonas Devlieghere       m_current_event_id.reset();
18535a27b998SJonas Devlieghere   } else {
18545a27b998SJonas Devlieghere     m_current_event_id = id;
18555a27b998SJonas Devlieghere   }
18565a27b998SJonas Devlieghere 
18575a27b998SJonas Devlieghere   // Decide whether we actually are going to show the progress. This decision
18585a27b998SJonas Devlieghere   // can change between iterations so check it inside the loop.
18595a27b998SJonas Devlieghere   if (!GetShowProgress())
18605a27b998SJonas Devlieghere     return;
18615a27b998SJonas Devlieghere 
18625a27b998SJonas Devlieghere   // Determine whether the current output file is an interactive terminal with
18635a27b998SJonas Devlieghere   // color support. We assume that if we support ANSI escape codes we support
18645a27b998SJonas Devlieghere   // vt100 escape codes.
1865c231deb7SJonas Devlieghere   File &file = GetOutputFile();
1866c231deb7SJonas Devlieghere   if (!file.GetIsInteractive() || !file.GetIsTerminalWithColors())
18675a27b998SJonas Devlieghere     return;
18685a27b998SJonas Devlieghere 
1869c231deb7SJonas Devlieghere   StreamSP output = GetAsyncOutputStream();
1870c231deb7SJonas Devlieghere 
1871e618eb87SJonas Devlieghere   // Print over previous line, if any.
1872c231deb7SJonas Devlieghere   output->Printf("\r");
1873e618eb87SJonas Devlieghere 
1874ea8b811bSMed Ismail Bennani   if (data->GetCompleted() == data->GetTotal()) {
18755a27b998SJonas Devlieghere     // Clear the current line.
1876c231deb7SJonas Devlieghere     output->Printf("\x1B[2K");
1877c231deb7SJonas Devlieghere     output->Flush();
18785a27b998SJonas Devlieghere     return;
18795a27b998SJonas Devlieghere   }
18805a27b998SJonas Devlieghere 
1881051a5ae9SMed Ismail Bennani   // Trim the progress message if it exceeds the window's width and print it.
1882051a5ae9SMed Ismail Bennani   std::string message = data->GetMessage();
1883051a5ae9SMed Ismail Bennani   if (data->IsFinite())
1884051a5ae9SMed Ismail Bennani     message = llvm::formatv("[{0}/{1}] {2}", data->GetCompleted(),
1885051a5ae9SMed Ismail Bennani                             data->GetTotal(), message)
1886051a5ae9SMed Ismail Bennani                   .str();
1887051a5ae9SMed Ismail Bennani 
1888051a5ae9SMed Ismail Bennani   // Trim the progress message if it exceeds the window's width and print it.
1889051a5ae9SMed Ismail Bennani   const uint32_t term_width = GetTerminalWidth();
1890051a5ae9SMed Ismail Bennani   const uint32_t ellipsis = 3;
1891051a5ae9SMed Ismail Bennani   if (message.size() + ellipsis >= term_width)
1892051a5ae9SMed Ismail Bennani     message = message.substr(0, term_width - ellipsis);
1893051a5ae9SMed Ismail Bennani 
1894097d46f4SJonas Devlieghere   const bool use_color = GetUseColor();
1895097d46f4SJonas Devlieghere   llvm::StringRef ansi_prefix = GetShowProgressAnsiPrefix();
1896097d46f4SJonas Devlieghere   if (!ansi_prefix.empty())
1897c231deb7SJonas Devlieghere     output->Printf(
1898097d46f4SJonas Devlieghere         "%s", ansi::FormatAnsiTerminalCodes(ansi_prefix, use_color).c_str());
1899097d46f4SJonas Devlieghere 
1900c231deb7SJonas Devlieghere   output->Printf("%s...", message.c_str());
19015a27b998SJonas Devlieghere 
1902097d46f4SJonas Devlieghere   llvm::StringRef ansi_suffix = GetShowProgressAnsiSuffix();
1903097d46f4SJonas Devlieghere   if (!ansi_suffix.empty())
1904c231deb7SJonas Devlieghere     output->Printf(
1905097d46f4SJonas Devlieghere         "%s", ansi::FormatAnsiTerminalCodes(ansi_suffix, use_color).c_str());
1906097d46f4SJonas Devlieghere 
19075a27b998SJonas Devlieghere   // Clear until the end of the line.
1908c231deb7SJonas Devlieghere   output->Printf("\x1B[K\r");
19095a27b998SJonas Devlieghere 
19105a27b998SJonas Devlieghere   // Flush the output.
1911c231deb7SJonas Devlieghere   output->Flush();
19125a27b998SJonas Devlieghere }
19135a27b998SJonas Devlieghere 
HandleDiagnosticEvent(const lldb::EventSP & event_sp)19142fc38b2bSJonas Devlieghere void Debugger::HandleDiagnosticEvent(const lldb::EventSP &event_sp) {
19152fc38b2bSJonas Devlieghere   auto *data = DiagnosticEventData::GetEventDataFromEvent(event_sp.get());
19162fc38b2bSJonas Devlieghere   if (!data)
19172fc38b2bSJonas Devlieghere     return;
19182fc38b2bSJonas Devlieghere 
19192fc38b2bSJonas Devlieghere   StreamSP stream = GetAsyncErrorStream();
19202fc38b2bSJonas Devlieghere   data->Dump(stream.get());
19212fc38b2bSJonas Devlieghere }
19222fc38b2bSJonas Devlieghere 
HasIOHandlerThread()1923b9c1b51eSKate Stone bool Debugger::HasIOHandlerThread() { return m_io_handler_thread.IsJoinable(); }
19246681041dSSean Callanan 
StartIOHandlerThread()1925b9c1b51eSKate Stone bool Debugger::StartIOHandlerThread() {
1926f39c2e18SJonas Devlieghere   if (!m_io_handler_thread.IsJoinable()) {
1927f39c2e18SJonas Devlieghere     llvm::Expected<HostThread> io_handler_thread = ThreadLauncher::LaunchThread(
1928d0810779SPavel Labath         "lldb.debugger.io-handler", [this] { return IOHandlerThread(); },
1929807b6b32SGreg Clayton         8 * 1024 * 1024); // Use larger 8MB stack for this thread
1930f39c2e18SJonas Devlieghere     if (io_handler_thread) {
1931f39c2e18SJonas Devlieghere       m_io_handler_thread = *io_handler_thread;
1932f39c2e18SJonas Devlieghere     } else {
1933a007a6d8SPavel Labath       LLDB_LOG(GetLog(LLDBLog::Host), "failed to launch host thread: {}",
1934f39c2e18SJonas Devlieghere                llvm::toString(io_handler_thread.takeError()));
1935f39c2e18SJonas Devlieghere     }
1936f39c2e18SJonas Devlieghere   }
1937acee96aeSZachary Turner   return m_io_handler_thread.IsJoinable();
193844d93782SGreg Clayton }
193944d93782SGreg Clayton 
StopIOHandlerThread()1940b9c1b51eSKate Stone void Debugger::StopIOHandlerThread() {
1941b9c1b51eSKate Stone   if (m_io_handler_thread.IsJoinable()) {
19427ca15ba7SLawrence D'Anna     GetInputFile().Close();
194339de3110SZachary Turner     m_io_handler_thread.Join(nullptr);
194444d93782SGreg Clayton   }
194544d93782SGreg Clayton }
194644d93782SGreg Clayton 
JoinIOHandlerThread()1947b9c1b51eSKate Stone void Debugger::JoinIOHandlerThread() {
1948b9c1b51eSKate Stone   if (HasIOHandlerThread()) {
19496681041dSSean Callanan     thread_result_t result;
19506681041dSSean Callanan     m_io_handler_thread.Join(&result);
19516681041dSSean Callanan     m_io_handler_thread = LLDB_INVALID_HOST_THREAD;
19526681041dSSean Callanan   }
19536681041dSSean Callanan }
19546681041dSSean Callanan 
GetSelectedOrDummyTarget(bool prefer_dummy)1955b2fa3b92SJonas Devlieghere Target &Debugger::GetSelectedOrDummyTarget(bool prefer_dummy) {
1956b9c1b51eSKate Stone   if (!prefer_dummy) {
1957b2fa3b92SJonas Devlieghere     if (TargetSP target = m_target_list.GetSelectedTarget())
1958b2fa3b92SJonas Devlieghere       return *target;
195933df7cd3SJim Ingham   }
1960893c932aSJim Ingham   return GetDummyTarget();
1961893c932aSJim Ingham }
196244d93782SGreg Clayton 
RunREPL(LanguageType language,const char * repl_options)196397206d57SZachary Turner Status Debugger::RunREPL(LanguageType language, const char *repl_options) {
196497206d57SZachary Turner   Status err;
19653e7e915dSSean Callanan   FileSpec repl_executable;
19663e7e915dSSean Callanan 
196746a28a95SJonas Devlieghere   if (language == eLanguageTypeUnknown)
196846a28a95SJonas Devlieghere     language = GetREPLLanguage();
196946a28a95SJonas Devlieghere 
1970b9c1b51eSKate Stone   if (language == eLanguageTypeUnknown) {
1971aa97a89dSAdrian Prantl     LanguageSet repl_languages = Language::GetLanguagesSupportingREPLs();
197297f84e87SSean Callanan 
1973aa97a89dSAdrian Prantl     if (auto single_lang = repl_languages.GetSingularLanguage()) {
1974aa97a89dSAdrian Prantl       language = *single_lang;
1975aa97a89dSAdrian Prantl     } else if (repl_languages.Empty()) {
197646a28a95SJonas Devlieghere       err.SetErrorString(
1977b9c1b51eSKate Stone           "LLDB isn't configured with REPL support for any languages.");
197897f84e87SSean Callanan       return err;
1979b9c1b51eSKate Stone     } else {
198046a28a95SJonas Devlieghere       err.SetErrorString(
1981b9c1b51eSKate Stone           "Multiple possible REPL languages.  Please specify a language.");
198297f84e87SSean Callanan       return err;
198397f84e87SSean Callanan     }
198497f84e87SSean Callanan   }
198597f84e87SSean Callanan 
1986b9c1b51eSKate Stone   Target *const target =
1987b9c1b51eSKate Stone       nullptr; // passing in an empty target means the REPL must create one
19883e7e915dSSean Callanan 
19893b682de6SSean Callanan   REPLSP repl_sp(REPL::Create(err, language, this, target, repl_options));
19903e7e915dSSean Callanan 
1991b9c1b51eSKate Stone   if (!err.Success()) {
19923e7e915dSSean Callanan     return err;
19933e7e915dSSean Callanan   }
19943e7e915dSSean Callanan 
1995b9c1b51eSKate Stone   if (!repl_sp) {
1996b9c1b51eSKate Stone     err.SetErrorStringWithFormat("couldn't find a REPL for %s",
1997b9c1b51eSKate Stone                                  Language::GetNameForLanguageType(language));
19983e7e915dSSean Callanan     return err;
19993e7e915dSSean Callanan   }
20003e7e915dSSean Callanan 
20013e7e915dSSean Callanan   repl_sp->SetCompilerOptions(repl_options);
20023e7e915dSSean Callanan   repl_sp->RunLoop();
20033e7e915dSSean Callanan 
20043e7e915dSSean Callanan   return err;
20053e7e915dSSean Callanan }
200620048f31SLuboš Luňák 
GetThreadPool()200720048f31SLuboš Luňák llvm::ThreadPool &Debugger::GetThreadPool() {
200820048f31SLuboš Luňák   // NOTE: intentional leak to avoid issues with C++ destructor chain
200920048f31SLuboš Luňák   static llvm::ThreadPool *g_thread_pool = nullptr;
201020048f31SLuboš Luňák   static llvm::once_flag g_once_flag;
201120048f31SLuboš Luňák   llvm::call_once(g_once_flag, []() {
201220048f31SLuboš Luňák     g_thread_pool = new llvm::ThreadPool(llvm::optimal_concurrency());
201320048f31SLuboš Luňák   });
201420048f31SLuboš Luňák   return *g_thread_pool;
201520048f31SLuboš Luňák }
2016