130fdc8d8SChris Lattner //===-- Debugger.cpp --------------------------------------------*- C++ -*-===//
230fdc8d8SChris Lattner //
330fdc8d8SChris Lattner //                     The LLVM Compiler Infrastructure
430fdc8d8SChris Lattner //
530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source
630fdc8d8SChris Lattner // License. See LICENSE.TXT for details.
730fdc8d8SChris Lattner //
830fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
930fdc8d8SChris Lattner 
104a33d318SGreg Clayton #include "lldb/Core/Debugger.h"
114a33d318SGreg Clayton 
12df370550SEugene Zelenko // C Includes
13df370550SEugene Zelenko // C++ Includes
144a33d318SGreg Clayton #include <map>
1516ff8604SSaleem Abdulrasool #include <mutex>
164a33d318SGreg Clayton 
17df370550SEugene Zelenko // Other libraries and framework includes
18705b1809SJason Molenda #include "llvm/ADT/StringRef.h"
19df370550SEugene Zelenko #include "llvm/Support/DynamicLibrary.h"
205fae71c5SPavel Labath #include "llvm/Support/FileSystem.h"
21c5f28e2aSKamil Rytarowski #include "llvm/Support/Threading.h"
224becb37eSEnrico Granata 
23df370550SEugene Zelenko // Project includes
24554f68d3SGreg Clayton #include "lldb/Core/FormatEntity.h"
251f746071SGreg Clayton #include "lldb/Core/Module.h"
260d5a2bd6SJim Ingham #include "lldb/Core/PluginInterface.h"
27e8cd0c98SGreg Clayton #include "lldb/Core/PluginManager.h"
287349bd90SGreg Clayton #include "lldb/Core/RegisterValue.h"
2930fdc8d8SChris Lattner #include "lldb/Core/State.h"
305b52f0c7SJim Ingham #include "lldb/Core/StreamAsynchronousIO.h"
3144d93782SGreg Clayton #include "lldb/Core/StreamFile.h"
32705b1809SJason Molenda #include "lldb/Core/StructuredData.h"
3330fdc8d8SChris Lattner #include "lldb/Core/Timer.h"
344becb37eSEnrico Granata #include "lldb/Core/ValueObject.h"
356d3dbf51SGreg Clayton #include "lldb/Core/ValueObjectVariable.h"
365548cb50SEnrico Granata #include "lldb/DataFormatters/DataVisualization.h"
375548cb50SEnrico Granata #include "lldb/DataFormatters/FormatManager.h"
38894f7359SEnrico Granata #include "lldb/DataFormatters/TypeSummary.h"
393e7e915dSSean Callanan #include "lldb/Expression/REPL.h"
4093a66fc1SZachary Turner #include "lldb/Host/ConnectionFileDescriptor.h"
4142ff0ad8SZachary Turner #include "lldb/Host/HostInfo.h"
42a3406614SGreg Clayton #include "lldb/Host/Terminal.h"
4339de3110SZachary Turner #include "lldb/Host/ThreadLauncher.h"
446611103cSGreg Clayton #include "lldb/Interpreter/CommandInterpreter.h"
45633a29cfSZachary Turner #include "lldb/Interpreter/OptionValueProperties.h"
4667cc0636SGreg Clayton #include "lldb/Interpreter/OptionValueSInt64.h"
4767cc0636SGreg Clayton #include "lldb/Interpreter/OptionValueString.h"
481f746071SGreg Clayton #include "lldb/Symbol/CompileUnit.h"
491f746071SGreg Clayton #include "lldb/Symbol/Function.h"
501f746071SGreg Clayton #include "lldb/Symbol/Symbol.h"
516d3dbf51SGreg Clayton #include "lldb/Symbol/VariableList.h"
523e7e915dSSean Callanan #include "lldb/Target/Language.h"
5330fdc8d8SChris Lattner #include "lldb/Target/Process.h"
541b654882SGreg Clayton #include "lldb/Target/RegisterContext.h"
555fb8f797SGreg Clayton #include "lldb/Target/SectionLoadList.h"
561b654882SGreg Clayton #include "lldb/Target/StopInfo.h"
5775930019STodd Fiala #include "lldb/Target/StructuredDataPlugin.h"
5884a53dfbSEnrico Granata #include "lldb/Target/Target.h"
59b9c1b51eSKate Stone #include "lldb/Target/TargetList.h"
6030fdc8d8SChris Lattner #include "lldb/Target/Thread.h"
615a31471eSGreg Clayton #include "lldb/Utility/AnsiTerminal.h"
62*fb1a0a0dSZachary Turner #include "lldb/Utility/StreamCallback.h"
63bf9a7730SZachary Turner #include "lldb/Utility/StreamString.h"
64b9c1b51eSKate Stone #include "lldb/lldb-private.h"
6530fdc8d8SChris Lattner 
6630fdc8d8SChris Lattner using namespace lldb;
6730fdc8d8SChris Lattner using namespace lldb_private;
6830fdc8d8SChris Lattner 
69ebc1bb27SCaroline Tice static lldb::user_id_t g_unique_id = 1;
707c2896a2SZachary Turner static size_t g_debugger_event_thread_stack_bytes = 8 * 1024 * 1024;
71ebc1bb27SCaroline Tice 
721b654882SGreg Clayton #pragma mark Static Functions
731b654882SGreg Clayton 
741b654882SGreg Clayton typedef std::vector<DebuggerSP> DebuggerList;
75b9c1b51eSKate Stone static std::recursive_mutex *g_debugger_list_mutex_ptr =
76b9c1b51eSKate Stone     nullptr; // NOTE: intentional leak to avoid issues with C++ destructor chain
77b9c1b51eSKate Stone static DebuggerList *g_debugger_list_ptr =
78b9c1b51eSKate Stone     nullptr; // NOTE: intentional leak to avoid issues with C++ destructor chain
79e372b98dSGreg Clayton 
80b9c1b51eSKate Stone OptionEnumValueElement g_show_disassembly_enum_values[] = {
81b9c1b51eSKate Stone     {Debugger::eStopDisassemblyTypeNever, "never",
82b9c1b51eSKate Stone      "Never show disassembly when displaying a stop context."},
83b9c1b51eSKate Stone     {Debugger::eStopDisassemblyTypeNoDebugInfo, "no-debuginfo",
84b9c1b51eSKate Stone      "Show disassembly when there is no debug information."},
85b9c1b51eSKate Stone     {Debugger::eStopDisassemblyTypeNoSource, "no-source",
86b9c1b51eSKate Stone      "Show disassembly when there is no source information, or the source file "
87b9c1b51eSKate Stone      "is missing when displaying a stop context."},
88b9c1b51eSKate Stone     {Debugger::eStopDisassemblyTypeAlways, "always",
89b9c1b51eSKate Stone      "Always show disassembly when displaying a stop context."},
90b9c1b51eSKate Stone     {0, nullptr, nullptr}};
91e372b98dSGreg Clayton 
92b9c1b51eSKate Stone OptionEnumValueElement g_language_enumerators[] = {
9367cc0636SGreg Clayton     {eScriptLanguageNone, "none", "Disable scripting languages."},
94b9c1b51eSKate Stone     {eScriptLanguagePython, "python",
95b9c1b51eSKate Stone      "Select python as the default scripting language."},
96b9c1b51eSKate Stone     {eScriptLanguageDefault, "default",
97b9c1b51eSKate Stone      "Select the lldb default as the default scripting language."},
98b9c1b51eSKate Stone     {0, nullptr, nullptr}};
99e372b98dSGreg Clayton 
100b9c1b51eSKate Stone #define MODULE_WITH_FUNC                                                       \
101b9c1b51eSKate Stone   "{ "                                                                         \
1026a9767c7SJim Ingham   "${module.file.basename}{`${function.name-with-args}"                        \
1036a9767c7SJim Ingham   "{${frame.no-debug}${function.pc-offset}}}}"
10467cc0636SGreg Clayton #define FILE_AND_LINE "{ at ${line.file.basename}:${line.number}}"
1056ab659a9SJason Molenda #define IS_OPTIMIZED "{${function.is-optimized} [opt]}"
10667cc0636SGreg Clayton 
107b9c1b51eSKate Stone #define DEFAULT_THREAD_FORMAT                                                  \
108b9c1b51eSKate Stone   "thread #${thread.index}: tid = ${thread.id%tid}"                            \
109b9c1b51eSKate Stone   "{, ${frame.pc}}" MODULE_WITH_FUNC FILE_AND_LINE                             \
1100769b2b1SMichael Sartain   "{, name = '${thread.name}'}"                                                \
1110769b2b1SMichael Sartain   "{, queue = '${thread.queue}'}"                                              \
112705b1809SJason Molenda   "{, activity = '${thread.info.activity.name}'}"                              \
113705b1809SJason Molenda   "{, ${thread.info.trace_messages} messages}"                                 \
11467cc0636SGreg Clayton   "{, stop reason = ${thread.stop-reason}}"                                    \
11567cc0636SGreg Clayton   "{\\nReturn value: ${thread.return-value}}"                                  \
11630fadafeSJim Ingham   "{\\nCompleted expression: ${thread.completed-expression}}"                  \
11767cc0636SGreg Clayton   "\\n"
11867cc0636SGreg Clayton 
1196a9767c7SJim Ingham #define DEFAULT_THREAD_STOP_FORMAT                                             \
1206a9767c7SJim Ingham   "thread #${thread.index}{, name = '${thread.name}'}"                         \
1216a9767c7SJim Ingham   "{, queue = '${thread.queue}'}"                                              \
1226a9767c7SJim Ingham   "{, activity = '${thread.info.activity.name}'}"                              \
1236a9767c7SJim Ingham   "{, ${thread.info.trace_messages} messages}"                                 \
1246a9767c7SJim Ingham   "{, stop reason = ${thread.stop-reason}}"                                    \
1256a9767c7SJim Ingham   "{\\nReturn value: ${thread.return-value}}"                                  \
1266a9767c7SJim Ingham   "{\\nCompleted expression: ${thread.completed-expression}}"                  \
1276a9767c7SJim Ingham   "\\n"
1286a9767c7SJim Ingham 
129b9c1b51eSKate Stone #define DEFAULT_FRAME_FORMAT                                                   \
130270e8228SJason Molenda   "frame #${frame.index}: ${frame.pc}" MODULE_WITH_FUNC FILE_AND_LINE          \
131b9c1b51eSKate Stone       IS_OPTIMIZED "\\n"
13267cc0636SGreg Clayton 
133c980fa92SJason Molenda // Three parts to this disassembly format specification:
134c980fa92SJason Molenda //   1. If this is a new function/symbol (no previous symbol/function), print
135c980fa92SJason Molenda //      dylib`funcname:\n
136b9c1b51eSKate Stone //   2. If this is a symbol context change (different from previous
137b9c1b51eSKate Stone //   symbol/function), print
138c980fa92SJason Molenda //      dylib`funcname:\n
139c980fa92SJason Molenda //   3. print
140c980fa92SJason Molenda //      address <+offset>:
141b9c1b51eSKate Stone #define DEFAULT_DISASSEMBLY_FORMAT                                             \
142b9c1b51eSKate Stone   "{${function.initial-function}{${module.file.basename}`}{${function.name-"   \
143b9c1b51eSKate Stone   "without-args}}:\n}{${function.changed}\n{${module.file.basename}`}{${"      \
144b9c1b51eSKate Stone   "function.name-without-args}}:\n}{${current-pc-arrow} "                      \
145b9c1b51eSKate Stone   "}${addr-file-or-load}{ "                                                    \
146b9c1b51eSKate Stone   "<${function.concrete-only-addr-offset-no-padding}>}: "
147c980fa92SJason Molenda 
148c980fa92SJason Molenda // gdb's disassembly format can be emulated with
149b9c1b51eSKate Stone // ${current-pc-arrow}${addr-file-or-load}{
150b9c1b51eSKate Stone // <${function.name-without-args}${function.concrete-only-addr-offset-no-padding}>}:
151c980fa92SJason Molenda 
152c980fa92SJason Molenda // lldb's original format for disassembly would look like this format string -
153b9c1b51eSKate Stone // {${function.initial-function}{${module.file.basename}`}{${function.name-without-args}}:\n}{${function.changed}\n{${module.file.basename}`}{${function.name-without-args}}:\n}{${current-pc-arrow}
154b9c1b51eSKate Stone // }{${addr-file-or-load}}:
155c980fa92SJason Molenda 
1569666ba75STodd Fiala #define DEFAULT_STOP_SHOW_COLUMN_ANSI_PREFIX "${ansi.underline}"
1579666ba75STodd Fiala #define DEFAULT_STOP_SHOW_COLUMN_ANSI_SUFFIX "${ansi.normal}"
1589666ba75STodd Fiala 
1599666ba75STodd Fiala static OptionEnumValueElement s_stop_show_column_values[] = {
1609666ba75STodd Fiala     {eStopShowColumnAnsiOrCaret, "ansi-or-caret",
1619666ba75STodd Fiala      "Highlight the stop column with ANSI terminal codes when color/ANSI mode "
1629666ba75STodd Fiala      "is enabled; otherwise, fall back to using a text-only caret (^) as if "
1639666ba75STodd Fiala      "\"caret-only\" mode was selected."},
1649666ba75STodd Fiala     {eStopShowColumnAnsi, "ansi", "Highlight the stop column with ANSI "
1659666ba75STodd Fiala                                   "terminal codes when running LLDB with "
1669666ba75STodd Fiala                                   "color/ANSI enabled."},
1679666ba75STodd Fiala     {eStopShowColumnCaret, "caret",
1689666ba75STodd Fiala      "Highlight the stop column with a caret character (^) underneath the stop "
1699666ba75STodd Fiala      "column. This method introduces a new line in source listings that "
1709666ba75STodd Fiala      "display thread stop locations."},
1719666ba75STodd Fiala     {eStopShowColumnNone, "none", "Do not highlight the stop column."},
1729666ba75STodd Fiala     {0, nullptr, nullptr}};
1739666ba75STodd Fiala 
174b9c1b51eSKate Stone static PropertyDefinition g_properties[] = {
175b9c1b51eSKate Stone     {"auto-confirm", OptionValue::eTypeBoolean, true, false, nullptr, nullptr,
176b9c1b51eSKate Stone      "If true all confirmation prompts will receive their default reply."},
177b9c1b51eSKate Stone     {"disassembly-format", OptionValue::eTypeFormatEntity, true, 0,
178b9c1b51eSKate Stone      DEFAULT_DISASSEMBLY_FORMAT, nullptr, "The default disassembly format "
179b9c1b51eSKate Stone                                           "string to use when disassembling "
180b9c1b51eSKate Stone                                           "instruction sequences."},
181b9c1b51eSKate Stone     {"frame-format", OptionValue::eTypeFormatEntity, true, 0,
182b9c1b51eSKate Stone      DEFAULT_FRAME_FORMAT, nullptr, "The default frame format string to use "
183b9c1b51eSKate Stone                                     "when displaying stack frame information "
184b9c1b51eSKate Stone                                     "for threads."},
185b9c1b51eSKate Stone     {"notify-void", OptionValue::eTypeBoolean, true, false, nullptr, nullptr,
186b9c1b51eSKate Stone      "Notify the user explicitly if an expression returns void (default: "
187b9c1b51eSKate Stone      "false)."},
188b9c1b51eSKate Stone     {"prompt", OptionValue::eTypeString, true,
189b9c1b51eSKate Stone      OptionValueString::eOptionEncodeCharacterEscapeSequences, "(lldb) ",
190b9c1b51eSKate Stone      nullptr, "The debugger command line prompt displayed for the user."},
191b9c1b51eSKate Stone     {"script-lang", OptionValue::eTypeEnum, true, eScriptLanguagePython,
192b9c1b51eSKate Stone      nullptr, g_language_enumerators,
193b9c1b51eSKate Stone      "The script language to be used for evaluating user-written scripts."},
194b9c1b51eSKate Stone     {"stop-disassembly-count", OptionValue::eTypeSInt64, true, 4, nullptr,
195b9c1b51eSKate Stone      nullptr, "The number of disassembly lines to show when displaying a "
196b9c1b51eSKate Stone               "stopped context."},
197b9c1b51eSKate Stone     {"stop-disassembly-display", OptionValue::eTypeEnum, true,
198b9c1b51eSKate Stone      Debugger::eStopDisassemblyTypeNoDebugInfo, nullptr,
199b9c1b51eSKate Stone      g_show_disassembly_enum_values,
200b9c1b51eSKate Stone      "Control when to display disassembly when displaying a stopped context."},
201b9c1b51eSKate Stone     {"stop-line-count-after", OptionValue::eTypeSInt64, true, 3, nullptr,
202b9c1b51eSKate Stone      nullptr, "The number of sources lines to display that come after the "
203b9c1b51eSKate Stone               "current source line when displaying a stopped context."},
204b9c1b51eSKate Stone     {"stop-line-count-before", OptionValue::eTypeSInt64, true, 3, nullptr,
205b9c1b51eSKate Stone      nullptr, "The number of sources lines to display that come before the "
206b9c1b51eSKate Stone               "current source line when displaying a stopped context."},
2079666ba75STodd Fiala     {"stop-show-column", OptionValue::eTypeEnum, false,
2089666ba75STodd Fiala      eStopShowColumnAnsiOrCaret, nullptr, s_stop_show_column_values,
2099666ba75STodd Fiala      "If true, LLDB will use the column information from the debug info to "
2109666ba75STodd Fiala      "mark the current position when displaying a stopped context."},
2119666ba75STodd Fiala     {"stop-show-column-ansi-prefix", OptionValue::eTypeFormatEntity, true, 0,
2129666ba75STodd Fiala      DEFAULT_STOP_SHOW_COLUMN_ANSI_PREFIX, nullptr,
2139666ba75STodd Fiala      "When displaying the column marker in a color-enabled (i.e. ANSI) "
2149666ba75STodd Fiala      "terminal, use the ANSI terminal code specified in this format at the "
2159666ba75STodd Fiala      "immediately before the column to be marked."},
2169666ba75STodd Fiala     {"stop-show-column-ansi-suffix", OptionValue::eTypeFormatEntity, true, 0,
2179666ba75STodd Fiala      DEFAULT_STOP_SHOW_COLUMN_ANSI_SUFFIX, nullptr,
2189666ba75STodd Fiala      "When displaying the column marker in a color-enabled (i.e. ANSI) "
2199666ba75STodd Fiala      "terminal, use the ANSI terminal code specified in this format "
2209666ba75STodd Fiala      "immediately after the column to be marked."},
221b9c1b51eSKate Stone     {"term-width", OptionValue::eTypeSInt64, true, 80, nullptr, nullptr,
222b9c1b51eSKate Stone      "The maximum number of columns to use for displaying text."},
223b9c1b51eSKate Stone     {"thread-format", OptionValue::eTypeFormatEntity, true, 0,
224b9c1b51eSKate Stone      DEFAULT_THREAD_FORMAT, nullptr, "The default thread format string to use "
225b9c1b51eSKate Stone                                      "when displaying thread information."},
2266a9767c7SJim Ingham     {"thread-stop-format", OptionValue::eTypeFormatEntity, true, 0,
2276a9767c7SJim Ingham      DEFAULT_THREAD_STOP_FORMAT, nullptr, "The default thread format  "
2286a9767c7SJim Ingham                                      "string to usewhen displaying thread "
2296a9767c7SJim Ingham                                      "information as part of the stop display."},
230b9c1b51eSKate Stone     {"use-external-editor", OptionValue::eTypeBoolean, true, false, nullptr,
231b9c1b51eSKate Stone      nullptr, "Whether to use an external editor or not."},
232b9c1b51eSKate Stone     {"use-color", OptionValue::eTypeBoolean, true, true, nullptr, nullptr,
233b9c1b51eSKate Stone      "Whether to use Ansi color codes or not."},
234b9c1b51eSKate Stone     {"auto-one-line-summaries", OptionValue::eTypeBoolean, true, true, nullptr,
235b9c1b51eSKate Stone      nullptr, "If true, LLDB will automatically display small structs in "
236b9c1b51eSKate Stone               "one-liner format (default: true)."},
237b9c1b51eSKate Stone     {"auto-indent", OptionValue::eTypeBoolean, true, true, nullptr, nullptr,
238b9c1b51eSKate Stone      "If true, LLDB will auto indent/outdent code. Currently only supported in "
239b9c1b51eSKate Stone      "the REPL (default: true)."},
240b9c1b51eSKate Stone     {"print-decls", OptionValue::eTypeBoolean, true, true, nullptr, nullptr,
241b9c1b51eSKate Stone      "If true, LLDB will print the values of variables declared in an "
242b9c1b51eSKate Stone      "expression. Currently only supported in the REPL (default: true)."},
243b9c1b51eSKate Stone     {"tab-size", OptionValue::eTypeUInt64, true, 4, nullptr, nullptr,
244b9c1b51eSKate Stone      "The tab size to use when indenting code in multi-line input mode "
245b9c1b51eSKate Stone      "(default: 4)."},
246b9c1b51eSKate Stone     {"escape-non-printables", OptionValue::eTypeBoolean, true, true, nullptr,
247b9c1b51eSKate Stone      nullptr, "If true, LLDB will automatically escape non-printable and "
248b9c1b51eSKate Stone               "escape characters when formatting strings."},
249b9c1b51eSKate Stone     {nullptr, OptionValue::eTypeInvalid, true, 0, nullptr, nullptr, nullptr}};
25067cc0636SGreg Clayton 
251b9c1b51eSKate Stone enum {
25267cc0636SGreg Clayton   ePropertyAutoConfirm = 0,
253aff1b357SJason Molenda   ePropertyDisassemblyFormat,
25467cc0636SGreg Clayton   ePropertyFrameFormat,
25567cc0636SGreg Clayton   ePropertyNotiftVoid,
25667cc0636SGreg Clayton   ePropertyPrompt,
25767cc0636SGreg Clayton   ePropertyScriptLanguage,
25867cc0636SGreg Clayton   ePropertyStopDisassemblyCount,
25967cc0636SGreg Clayton   ePropertyStopDisassemblyDisplay,
26067cc0636SGreg Clayton   ePropertyStopLineCountAfter,
26167cc0636SGreg Clayton   ePropertyStopLineCountBefore,
2629666ba75STodd Fiala   ePropertyStopShowColumn,
2639666ba75STodd Fiala   ePropertyStopShowColumnAnsiPrefix,
2649666ba75STodd Fiala   ePropertyStopShowColumnAnsiSuffix,
26567cc0636SGreg Clayton   ePropertyTerminalWidth,
26667cc0636SGreg Clayton   ePropertyThreadFormat,
2676a9767c7SJim Ingham   ePropertyThreadStopFormat,
268c3ce7f27SMichael Sartain   ePropertyUseExternalEditor,
269c3ce7f27SMichael Sartain   ePropertyUseColor,
270ebdc1ac0SEnrico Granata   ePropertyAutoOneLineSummaries,
2716681041dSSean Callanan   ePropertyAutoIndent,
2726681041dSSean Callanan   ePropertyPrintDecls,
2736681041dSSean Callanan   ePropertyTabSize,
274ebdc1ac0SEnrico Granata   ePropertyEscapeNonPrintables
27567cc0636SGreg Clayton };
27667cc0636SGreg Clayton 
277df370550SEugene Zelenko LoadPluginCallbackType Debugger::g_load_plugin_callback = nullptr;
2784c05410fSGreg Clayton 
279b9c1b51eSKate Stone Error Debugger::SetPropertyValue(const ExecutionContext *exe_ctx,
2804c05410fSGreg Clayton                                  VarSetOperationType op,
28131d97a5cSZachary Turner   llvm::StringRef property_path, llvm::StringRef value) {
28231d97a5cSZachary Turner   bool is_load_script = (property_path == "target.load-script-from-symbol-file");
28331d97a5cSZachary Turner   bool is_escape_non_printables = (property_path == "escape-non-printables");
28484a53dfbSEnrico Granata   TargetSP target_sp;
285397ddd5fSEnrico Granata   LoadScriptFromSymFile load_script_old_value;
286b9c1b51eSKate Stone   if (is_load_script && exe_ctx->GetTargetSP()) {
28784a53dfbSEnrico Granata     target_sp = exe_ctx->GetTargetSP();
288b9c1b51eSKate Stone     load_script_old_value =
289b9c1b51eSKate Stone         target_sp->TargetProperties::GetLoadScriptFromSymbolFile();
29084a53dfbSEnrico Granata   }
2914c05410fSGreg Clayton   Error error(Properties::SetPropertyValue(exe_ctx, op, property_path, value));
292b9c1b51eSKate Stone   if (error.Success()) {
29384a53dfbSEnrico Granata     // FIXME it would be nice to have "on-change" callbacks for properties
29431d97a5cSZachary Turner     if (property_path == g_properties[ePropertyPrompt].name) {
295514d8cd8SZachary Turner       llvm::StringRef new_prompt = GetPrompt();
296b9c1b51eSKate Stone       std::string str = lldb_utility::ansi::FormatAnsiTerminalCodes(
297b9c1b51eSKate Stone           new_prompt, GetUseColor());
298c3ce7f27SMichael Sartain       if (str.length())
299771ef6d4SMalcolm Parsons         new_prompt = str;
30044d93782SGreg Clayton       GetCommandInterpreter().UpdatePrompt(new_prompt);
301b9c1b51eSKate Stone       EventSP prompt_change_event_sp(
302b9c1b51eSKate Stone           new Event(CommandInterpreter::eBroadcastBitResetPrompt,
303b9c1b51eSKate Stone                     new EventDataBytes(new_prompt)));
3044c05410fSGreg Clayton       GetCommandInterpreter().BroadcastEvent(prompt_change_event_sp);
30531d97a5cSZachary Turner     } else if (property_path == g_properties[ePropertyUseColor].name) {
306b9c1b51eSKate Stone       // use-color changed. Ping the prompt so it can reset the ansi terminal
307b9c1b51eSKate Stone       // codes.
308c3ce7f27SMichael Sartain       SetPrompt(GetPrompt());
309b9c1b51eSKate Stone     } else if (is_load_script && target_sp &&
310b9c1b51eSKate Stone                load_script_old_value == eLoadScriptFromSymFileWarn) {
311b9c1b51eSKate Stone       if (target_sp->TargetProperties::GetLoadScriptFromSymbolFile() ==
312b9c1b51eSKate Stone           eLoadScriptFromSymFileTrue) {
31384a53dfbSEnrico Granata         std::list<Error> errors;
3149730339bSEnrico Granata         StreamString feedback_stream;
315b9c1b51eSKate Stone         if (!target_sp->LoadScriptingResources(errors, &feedback_stream)) {
31644d93782SGreg Clayton           StreamFileSP stream_sp(GetErrorFile());
317b9c1b51eSKate Stone           if (stream_sp) {
318b9c1b51eSKate Stone             for (auto error : errors) {
31944d93782SGreg Clayton               stream_sp->Printf("%s\n", error.AsCString());
32084a53dfbSEnrico Granata             }
3219730339bSEnrico Granata             if (feedback_stream.GetSize())
322c156427dSZachary Turner               stream_sp->PutCString(feedback_stream.GetString());
32344d93782SGreg Clayton           }
32484a53dfbSEnrico Granata         }
32584a53dfbSEnrico Granata       }
326b9c1b51eSKate Stone     } else if (is_escape_non_printables) {
327ebdc1ac0SEnrico Granata       DataVisualization::ForceUpdate();
328ebdc1ac0SEnrico Granata     }
3294c05410fSGreg Clayton   }
3304c05410fSGreg Clayton   return error;
3314c05410fSGreg Clayton }
3324c05410fSGreg Clayton 
333b9c1b51eSKate Stone bool Debugger::GetAutoConfirm() const {
33467cc0636SGreg Clayton   const uint32_t idx = ePropertyAutoConfirm;
335b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsBoolean(
336b9c1b51eSKate Stone       nullptr, idx, g_properties[idx].default_uint_value != 0);
33767cc0636SGreg Clayton }
33867cc0636SGreg Clayton 
339b9c1b51eSKate Stone const FormatEntity::Entry *Debugger::GetDisassemblyFormat() const {
340aff1b357SJason Molenda   const uint32_t idx = ePropertyDisassemblyFormat;
341df370550SEugene Zelenko   return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
342aff1b357SJason Molenda }
343aff1b357SJason Molenda 
344b9c1b51eSKate Stone const FormatEntity::Entry *Debugger::GetFrameFormat() const {
34567cc0636SGreg Clayton   const uint32_t idx = ePropertyFrameFormat;
346df370550SEugene Zelenko   return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
34767cc0636SGreg Clayton }
34867cc0636SGreg Clayton 
349b9c1b51eSKate Stone bool Debugger::GetNotifyVoid() const {
35067cc0636SGreg Clayton   const uint32_t idx = ePropertyNotiftVoid;
351b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsBoolean(
352b9c1b51eSKate Stone       nullptr, idx, g_properties[idx].default_uint_value != 0);
35367cc0636SGreg Clayton }
35467cc0636SGreg Clayton 
355514d8cd8SZachary Turner llvm::StringRef Debugger::GetPrompt() const {
35667cc0636SGreg Clayton   const uint32_t idx = ePropertyPrompt;
357b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsString(
358b9c1b51eSKate Stone       nullptr, idx, g_properties[idx].default_cstr_value);
35967cc0636SGreg Clayton }
36067cc0636SGreg Clayton 
361514d8cd8SZachary Turner void Debugger::SetPrompt(llvm::StringRef p) {
36267cc0636SGreg Clayton   const uint32_t idx = ePropertyPrompt;
363df370550SEugene Zelenko   m_collection_sp->SetPropertyAtIndexAsString(nullptr, idx, p);
364514d8cd8SZachary Turner   llvm::StringRef new_prompt = GetPrompt();
365b9c1b51eSKate Stone   std::string str =
366b9c1b51eSKate Stone       lldb_utility::ansi::FormatAnsiTerminalCodes(new_prompt, GetUseColor());
367c3ce7f27SMichael Sartain   if (str.length())
368771ef6d4SMalcolm Parsons     new_prompt = str;
36944d93782SGreg Clayton   GetCommandInterpreter().UpdatePrompt(new_prompt);
37067cc0636SGreg Clayton }
37167cc0636SGreg Clayton 
372b9c1b51eSKate Stone const FormatEntity::Entry *Debugger::GetThreadFormat() const {
37367cc0636SGreg Clayton   const uint32_t idx = ePropertyThreadFormat;
374df370550SEugene Zelenko   return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
37567cc0636SGreg Clayton }
37667cc0636SGreg Clayton 
3776a9767c7SJim Ingham const FormatEntity::Entry *Debugger::GetThreadStopFormat() const {
3786a9767c7SJim Ingham   const uint32_t idx = ePropertyThreadStopFormat;
3796a9767c7SJim Ingham   return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
3806a9767c7SJim Ingham }
3816a9767c7SJim Ingham 
382b9c1b51eSKate Stone lldb::ScriptLanguage Debugger::GetScriptLanguage() const {
38367cc0636SGreg Clayton   const uint32_t idx = ePropertyScriptLanguage;
384b9c1b51eSKate Stone   return (lldb::ScriptLanguage)m_collection_sp->GetPropertyAtIndexAsEnumeration(
385b9c1b51eSKate Stone       nullptr, idx, g_properties[idx].default_uint_value);
38667cc0636SGreg Clayton }
38767cc0636SGreg Clayton 
388b9c1b51eSKate Stone bool Debugger::SetScriptLanguage(lldb::ScriptLanguage script_lang) {
38967cc0636SGreg Clayton   const uint32_t idx = ePropertyScriptLanguage;
390b9c1b51eSKate Stone   return m_collection_sp->SetPropertyAtIndexAsEnumeration(nullptr, idx,
391b9c1b51eSKate Stone                                                           script_lang);
39267cc0636SGreg Clayton }
39367cc0636SGreg Clayton 
394b9c1b51eSKate Stone uint32_t Debugger::GetTerminalWidth() const {
39567cc0636SGreg Clayton   const uint32_t idx = ePropertyTerminalWidth;
396b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsSInt64(
397b9c1b51eSKate Stone       nullptr, idx, g_properties[idx].default_uint_value);
39867cc0636SGreg Clayton }
39967cc0636SGreg Clayton 
400b9c1b51eSKate Stone bool Debugger::SetTerminalWidth(uint32_t term_width) {
40167cc0636SGreg Clayton   const uint32_t idx = ePropertyTerminalWidth;
402df370550SEugene Zelenko   return m_collection_sp->SetPropertyAtIndexAsSInt64(nullptr, idx, term_width);
40367cc0636SGreg Clayton }
40467cc0636SGreg Clayton 
405b9c1b51eSKate Stone bool Debugger::GetUseExternalEditor() const {
40667cc0636SGreg Clayton   const uint32_t idx = ePropertyUseExternalEditor;
407b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsBoolean(
408b9c1b51eSKate Stone       nullptr, idx, g_properties[idx].default_uint_value != 0);
40967cc0636SGreg Clayton }
41067cc0636SGreg Clayton 
411b9c1b51eSKate Stone bool Debugger::SetUseExternalEditor(bool b) {
41267cc0636SGreg Clayton   const uint32_t idx = ePropertyUseExternalEditor;
413df370550SEugene Zelenko   return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
41467cc0636SGreg Clayton }
41567cc0636SGreg Clayton 
416b9c1b51eSKate Stone bool Debugger::GetUseColor() const {
417c3ce7f27SMichael Sartain   const uint32_t idx = ePropertyUseColor;
418b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsBoolean(
419b9c1b51eSKate Stone       nullptr, idx, g_properties[idx].default_uint_value != 0);
420c3ce7f27SMichael Sartain }
421c3ce7f27SMichael Sartain 
422b9c1b51eSKate Stone bool Debugger::SetUseColor(bool b) {
423c3ce7f27SMichael Sartain   const uint32_t idx = ePropertyUseColor;
424df370550SEugene Zelenko   bool ret = m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
425c3ce7f27SMichael Sartain   SetPrompt(GetPrompt());
426c3ce7f27SMichael Sartain   return ret;
427c3ce7f27SMichael Sartain }
428c3ce7f27SMichael Sartain 
4299666ba75STodd Fiala StopShowColumn Debugger::GetStopShowColumn() const {
4309666ba75STodd Fiala   const uint32_t idx = ePropertyStopShowColumn;
4319666ba75STodd Fiala   return (lldb::StopShowColumn)m_collection_sp->GetPropertyAtIndexAsEnumeration(
4329666ba75STodd Fiala       nullptr, idx, g_properties[idx].default_uint_value);
4339666ba75STodd Fiala }
4349666ba75STodd Fiala 
4359666ba75STodd Fiala const FormatEntity::Entry *Debugger::GetStopShowColumnAnsiPrefix() const {
4369666ba75STodd Fiala   const uint32_t idx = ePropertyStopShowColumnAnsiPrefix;
4379666ba75STodd Fiala   return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
4389666ba75STodd Fiala }
4399666ba75STodd Fiala 
4409666ba75STodd Fiala const FormatEntity::Entry *Debugger::GetStopShowColumnAnsiSuffix() const {
4419666ba75STodd Fiala   const uint32_t idx = ePropertyStopShowColumnAnsiSuffix;
4429666ba75STodd Fiala   return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
4439666ba75STodd Fiala }
4449666ba75STodd Fiala 
445b9c1b51eSKate Stone uint32_t Debugger::GetStopSourceLineCount(bool before) const {
446b9c1b51eSKate Stone   const uint32_t idx =
447b9c1b51eSKate Stone       before ? ePropertyStopLineCountBefore : ePropertyStopLineCountAfter;
448b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsSInt64(
449b9c1b51eSKate Stone       nullptr, idx, g_properties[idx].default_uint_value);
45067cc0636SGreg Clayton }
45167cc0636SGreg Clayton 
452b9c1b51eSKate Stone Debugger::StopDisassemblyType Debugger::GetStopDisassemblyDisplay() const {
45367cc0636SGreg Clayton   const uint32_t idx = ePropertyStopDisassemblyDisplay;
454b9c1b51eSKate Stone   return (Debugger::StopDisassemblyType)
455b9c1b51eSKate Stone       m_collection_sp->GetPropertyAtIndexAsEnumeration(
456b9c1b51eSKate Stone           nullptr, idx, g_properties[idx].default_uint_value);
45767cc0636SGreg Clayton }
45867cc0636SGreg Clayton 
459b9c1b51eSKate Stone uint32_t Debugger::GetDisassemblyLineCount() const {
46067cc0636SGreg Clayton   const uint32_t idx = ePropertyStopDisassemblyCount;
461b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsSInt64(
462b9c1b51eSKate Stone       nullptr, idx, g_properties[idx].default_uint_value);
46367cc0636SGreg Clayton }
464e372b98dSGreg Clayton 
465b9c1b51eSKate Stone bool Debugger::GetAutoOneLineSummaries() const {
46690a8db30SEnrico Granata   const uint32_t idx = ePropertyAutoOneLineSummaries;
467df370550SEugene Zelenko   return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true);
468ebdc1ac0SEnrico Granata }
469553fad5cSEnrico Granata 
470b9c1b51eSKate Stone bool Debugger::GetEscapeNonPrintables() const {
471ebdc1ac0SEnrico Granata   const uint32_t idx = ePropertyEscapeNonPrintables;
472df370550SEugene Zelenko   return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true);
473553fad5cSEnrico Granata }
474553fad5cSEnrico Granata 
475b9c1b51eSKate Stone bool Debugger::GetAutoIndent() const {
4766681041dSSean Callanan   const uint32_t idx = ePropertyAutoIndent;
477df370550SEugene Zelenko   return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true);
4786681041dSSean Callanan }
4796681041dSSean Callanan 
480b9c1b51eSKate Stone bool Debugger::SetAutoIndent(bool b) {
4816681041dSSean Callanan   const uint32_t idx = ePropertyAutoIndent;
482df370550SEugene Zelenko   return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
4836681041dSSean Callanan }
4846681041dSSean Callanan 
485b9c1b51eSKate Stone bool Debugger::GetPrintDecls() const {
4866681041dSSean Callanan   const uint32_t idx = ePropertyPrintDecls;
487df370550SEugene Zelenko   return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true);
4886681041dSSean Callanan }
4896681041dSSean Callanan 
490b9c1b51eSKate Stone bool Debugger::SetPrintDecls(bool b) {
4916681041dSSean Callanan   const uint32_t idx = ePropertyPrintDecls;
492df370550SEugene Zelenko   return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
4936681041dSSean Callanan }
4946681041dSSean Callanan 
495b9c1b51eSKate Stone uint32_t Debugger::GetTabSize() const {
4966681041dSSean Callanan   const uint32_t idx = ePropertyTabSize;
497b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsUInt64(
498b9c1b51eSKate Stone       nullptr, idx, g_properties[idx].default_uint_value);
4996681041dSSean Callanan }
5006681041dSSean Callanan 
501b9c1b51eSKate Stone bool Debugger::SetTabSize(uint32_t tab_size) {
5026681041dSSean Callanan   const uint32_t idx = ePropertyTabSize;
503df370550SEugene Zelenko   return m_collection_sp->SetPropertyAtIndexAsUInt64(nullptr, idx, tab_size);
5046681041dSSean Callanan }
5056681041dSSean Callanan 
5061b654882SGreg Clayton #pragma mark Debugger
5071b654882SGreg Clayton 
50867cc0636SGreg Clayton // const DebuggerPropertiesSP &
50967cc0636SGreg Clayton // Debugger::GetSettings() const
51067cc0636SGreg Clayton //{
51167cc0636SGreg Clayton //    return m_properties_sp;
51267cc0636SGreg Clayton //}
51367cc0636SGreg Clayton //
51499d0faf2SGreg Clayton 
515b9c1b51eSKate Stone void Debugger::Initialize(LoadPluginCallbackType load_plugin_callback) {
516b9c1b51eSKate Stone   assert(g_debugger_list_ptr == nullptr &&
517b9c1b51eSKate Stone          "Debugger::Initialize called more than once!");
5186c42e063SGreg Clayton   g_debugger_list_mutex_ptr = new std::recursive_mutex();
5196c42e063SGreg Clayton   g_debugger_list_ptr = new DebuggerList();
5205fb8f797SGreg Clayton   g_load_plugin_callback = load_plugin_callback;
52199d0faf2SGreg Clayton }
52230fdc8d8SChris Lattner 
523b9c1b51eSKate Stone void Debugger::Terminate() {
524b9c1b51eSKate Stone   assert(g_debugger_list_ptr &&
525b9c1b51eSKate Stone          "Debugger::Terminate called without a matching Debugger::Initialize!");
526e6e2bb38SZachary Turner 
527b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
52899d0faf2SGreg Clayton     // Clear our master list of debugger objects
5296c42e063SGreg Clayton     {
5306c42e063SGreg Clayton       std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
5316c42e063SGreg Clayton       for (const auto &debugger : *g_debugger_list_ptr)
532f3cd1819SOleksiy Vyalov         debugger->Clear();
5336c42e063SGreg Clayton       g_debugger_list_ptr->clear();
5346c42e063SGreg Clayton     }
5356c42e063SGreg Clayton   }
53630fdc8d8SChris Lattner }
53730fdc8d8SChris Lattner 
538b9c1b51eSKate Stone void Debugger::SettingsInitialize() { Target::SettingsInitialize(); }
53920bd37f7SCaroline Tice 
540b9c1b51eSKate Stone void Debugger::SettingsTerminate() { Target::SettingsTerminate(); }
54120bd37f7SCaroline Tice 
542b9c1b51eSKate Stone bool Debugger::LoadPlugin(const FileSpec &spec, Error &error) {
543b9c1b51eSKate Stone   if (g_load_plugin_callback) {
544b9c1b51eSKate Stone     llvm::sys::DynamicLibrary dynlib =
545b9c1b51eSKate Stone         g_load_plugin_callback(shared_from_this(), spec, error);
546b9c1b51eSKate Stone     if (dynlib.isValid()) {
54758a559c0SZachary Turner       m_loaded_plugins.push_back(dynlib);
54821dfcd9dSEnrico Granata       return true;
54921dfcd9dSEnrico Granata     }
550b9c1b51eSKate Stone   } else {
5515fb8f797SGreg Clayton     // The g_load_plugin_callback is registered in SBDebugger::Initialize()
5525fb8f797SGreg Clayton     // and if the public API layer isn't available (code is linking against
5535fb8f797SGreg Clayton     // all of the internal LLDB static libraries), then we can't load plugins
5545fb8f797SGreg Clayton     error.SetErrorString("Public API layer is not available");
5555fb8f797SGreg Clayton   }
55621dfcd9dSEnrico Granata   return false;
55721dfcd9dSEnrico Granata }
55821dfcd9dSEnrico Granata 
55921dfcd9dSEnrico Granata static FileSpec::EnumerateDirectoryResult
560b9c1b51eSKate Stone LoadPluginCallback(void *baton, FileSpec::FileType file_type,
561b9c1b51eSKate Stone                    const FileSpec &file_spec) {
56221dfcd9dSEnrico Granata   Error error;
56321dfcd9dSEnrico Granata 
56421dfcd9dSEnrico Granata   static ConstString g_dylibext("dylib");
5653cf443ddSMichael Sartain   static ConstString g_solibext("so");
56621dfcd9dSEnrico Granata 
56721dfcd9dSEnrico Granata   if (!baton)
56821dfcd9dSEnrico Granata     return FileSpec::eEnumerateDirectoryResultQuit;
56921dfcd9dSEnrico Granata 
57021dfcd9dSEnrico Granata   Debugger *debugger = (Debugger *)baton;
57121dfcd9dSEnrico Granata 
57221dfcd9dSEnrico Granata   // If we have a regular file, a symbolic link or unknown file type, try
57321dfcd9dSEnrico Granata   // and process the file. We must handle unknown as sometimes the directory
57421dfcd9dSEnrico Granata   // enumeration might be enumerating a file system that doesn't have correct
57521dfcd9dSEnrico Granata   // file type information.
57621dfcd9dSEnrico Granata   if (file_type == FileSpec::eFileTypeRegular ||
57721dfcd9dSEnrico Granata       file_type == FileSpec::eFileTypeSymbolicLink ||
578b9c1b51eSKate Stone       file_type == FileSpec::eFileTypeUnknown) {
57921dfcd9dSEnrico Granata     FileSpec plugin_file_spec(file_spec);
58021dfcd9dSEnrico Granata     plugin_file_spec.ResolvePath();
58121dfcd9dSEnrico Granata 
5823cf443ddSMichael Sartain     if (plugin_file_spec.GetFileNameExtension() != g_dylibext &&
583b9c1b51eSKate Stone         plugin_file_spec.GetFileNameExtension() != g_solibext) {
58421dfcd9dSEnrico Granata       return FileSpec::eEnumerateDirectoryResultNext;
5853cf443ddSMichael Sartain     }
58621dfcd9dSEnrico Granata 
587e743c782SEnrico Granata     Error plugin_load_error;
588e743c782SEnrico Granata     debugger->LoadPlugin(plugin_file_spec, plugin_load_error);
58921dfcd9dSEnrico Granata 
59021dfcd9dSEnrico Granata     return FileSpec::eEnumerateDirectoryResultNext;
591b9c1b51eSKate Stone   } else if (file_type == FileSpec::eFileTypeUnknown ||
59221dfcd9dSEnrico Granata              file_type == FileSpec::eFileTypeDirectory ||
593b9c1b51eSKate Stone              file_type == FileSpec::eFileTypeSymbolicLink) {
59421dfcd9dSEnrico Granata     // Try and recurse into anything that a directory or symbolic link.
59521dfcd9dSEnrico Granata     // We must also do this for unknown as sometimes the directory enumeration
5966a7f3338SBruce Mitchener     // might be enumerating a file system that doesn't have correct file type
59721dfcd9dSEnrico Granata     // information.
59821dfcd9dSEnrico Granata     return FileSpec::eEnumerateDirectoryResultEnter;
59921dfcd9dSEnrico Granata   }
60021dfcd9dSEnrico Granata 
60121dfcd9dSEnrico Granata   return FileSpec::eEnumerateDirectoryResultNext;
60221dfcd9dSEnrico Granata }
60321dfcd9dSEnrico Granata 
604b9c1b51eSKate Stone void Debugger::InstanceInitialize() {
60521dfcd9dSEnrico Granata   FileSpec dir_spec;
60621dfcd9dSEnrico Granata   const bool find_directories = true;
60721dfcd9dSEnrico Granata   const bool find_files = true;
60821dfcd9dSEnrico Granata   const bool find_other = true;
60921dfcd9dSEnrico Granata   char dir_path[PATH_MAX];
610b9c1b51eSKate Stone   if (HostInfo::GetLLDBPath(ePathTypeLLDBSystemPlugins, dir_spec)) {
611b9c1b51eSKate Stone     if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path))) {
612b9c1b51eSKate Stone       FileSpec::EnumerateDirectory(dir_path, find_directories, find_files,
613b9c1b51eSKate Stone                                    find_other, LoadPluginCallback, this);
61421dfcd9dSEnrico Granata     }
61521dfcd9dSEnrico Granata   }
61621dfcd9dSEnrico Granata 
617b9c1b51eSKate Stone   if (HostInfo::GetLLDBPath(ePathTypeLLDBUserPlugins, dir_spec)) {
618b9c1b51eSKate Stone     if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path))) {
619b9c1b51eSKate Stone       FileSpec::EnumerateDirectory(dir_path, find_directories, find_files,
620b9c1b51eSKate Stone                                    find_other, LoadPluginCallback, this);
62121dfcd9dSEnrico Granata     }
62221dfcd9dSEnrico Granata   }
623e8cd0c98SGreg Clayton 
624e8cd0c98SGreg Clayton   PluginManager::DebuggerInitialize(*this);
62521dfcd9dSEnrico Granata }
62621dfcd9dSEnrico Granata 
627b9c1b51eSKate Stone DebuggerSP Debugger::CreateInstance(lldb::LogOutputCallback log_callback,
628b9c1b51eSKate Stone                                     void *baton) {
629228063cdSJim Ingham   DebuggerSP debugger_sp(new Debugger(log_callback, baton));
630b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
6316c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
6326c42e063SGreg Clayton     g_debugger_list_ptr->push_back(debugger_sp);
6336611103cSGreg Clayton   }
63421dfcd9dSEnrico Granata   debugger_sp->InstanceInitialize();
6356611103cSGreg Clayton   return debugger_sp;
6366611103cSGreg Clayton }
6376611103cSGreg Clayton 
638b9c1b51eSKate Stone void Debugger::Destroy(DebuggerSP &debugger_sp) {
639df370550SEugene Zelenko   if (!debugger_sp)
640e02657b1SCaroline Tice     return;
641e02657b1SCaroline Tice 
6428314c525SJim Ingham   debugger_sp->Clear();
6438314c525SJim Ingham 
644b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
6456c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
6466c42e063SGreg Clayton     DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
647b9c1b51eSKate Stone     for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
648b9c1b51eSKate Stone       if ((*pos).get() == debugger_sp.get()) {
6496c42e063SGreg Clayton         g_debugger_list_ptr->erase(pos);
650e02657b1SCaroline Tice         return;
651e02657b1SCaroline Tice       }
652e02657b1SCaroline Tice     }
653e02657b1SCaroline Tice   }
654c15f55e2SGreg Clayton }
655e02657b1SCaroline Tice 
6564d122c40SGreg Clayton DebuggerSP
657b9c1b51eSKate Stone Debugger::FindDebuggerWithInstanceName(const ConstString &instance_name) {
6584d122c40SGreg Clayton   DebuggerSP debugger_sp;
659b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
6606c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
6616c42e063SGreg Clayton     DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
662b9c1b51eSKate Stone     for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
663b9c1b51eSKate Stone       if ((*pos)->m_instance_name == instance_name) {
6646920b52bSGreg Clayton         debugger_sp = *pos;
6656920b52bSGreg Clayton         break;
6666920b52bSGreg Clayton       }
6676920b52bSGreg Clayton     }
6686920b52bSGreg Clayton   }
6693df9a8dfSCaroline Tice   return debugger_sp;
6703df9a8dfSCaroline Tice }
6716611103cSGreg Clayton 
672b9c1b51eSKate Stone TargetSP Debugger::FindTargetWithProcessID(lldb::pid_t pid) {
6734d122c40SGreg Clayton   TargetSP target_sp;
674b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
6756c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
6766c42e063SGreg Clayton     DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
677b9c1b51eSKate Stone     for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
6786611103cSGreg Clayton       target_sp = (*pos)->GetTargetList().FindTargetWithProcessID(pid);
6796611103cSGreg Clayton       if (target_sp)
6806611103cSGreg Clayton         break;
6816611103cSGreg Clayton     }
682c15f55e2SGreg Clayton   }
6836611103cSGreg Clayton   return target_sp;
6846611103cSGreg Clayton }
6856611103cSGreg Clayton 
686b9c1b51eSKate Stone TargetSP Debugger::FindTargetWithProcess(Process *process) {
687e4e45924SGreg Clayton   TargetSP target_sp;
688b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
6896c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
6906c42e063SGreg Clayton     DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
691b9c1b51eSKate Stone     for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
692e4e45924SGreg Clayton       target_sp = (*pos)->GetTargetList().FindTargetWithProcess(process);
693e4e45924SGreg Clayton       if (target_sp)
694e4e45924SGreg Clayton         break;
695e4e45924SGreg Clayton     }
696c15f55e2SGreg Clayton   }
697e4e45924SGreg Clayton   return target_sp;
698e4e45924SGreg Clayton }
699e4e45924SGreg Clayton 
700b9c1b51eSKate Stone Debugger::Debugger(lldb::LogOutputCallback log_callback, void *baton)
701b9c1b51eSKate Stone     : UserID(g_unique_id++),
702e6481c7eSJason Molenda       Properties(OptionValuePropertiesSP(new OptionValueProperties())),
703e6481c7eSJason Molenda       m_input_file_sp(new StreamFile(stdin, false)),
704e6481c7eSJason Molenda       m_output_file_sp(new StreamFile(stdout, false)),
705e6481c7eSJason Molenda       m_error_file_sp(new StreamFile(stderr, false)),
706583bbb1dSJim Ingham       m_broadcaster_manager_sp(BroadcasterManager::MakeBroadcasterManager()),
707b9c1b51eSKate Stone       m_terminal_state(), m_target_list(*this), m_platform_list(),
708583bbb1dSJim Ingham       m_listener_sp(Listener::MakeListener("lldb.Debugger")),
709b9c1b51eSKate Stone       m_source_manager_ap(), m_source_file_cache(),
710b9c1b51eSKate Stone       m_command_interpreter_ap(
711b9c1b51eSKate Stone           new CommandInterpreter(*this, eScriptLanguageDefault, false)),
712b9c1b51eSKate Stone       m_input_reader_stack(), m_instance_name(), m_loaded_plugins(),
713b9c1b51eSKate Stone       m_event_handler_thread(), m_io_handler_thread(),
7144329fe42SGreg Clayton       m_sync_broadcaster(nullptr, "lldb.debugger.sync"),
715b9c1b51eSKate Stone       m_forward_listener_sp(), m_clear_once() {
71667cc0636SGreg Clayton   char instance_cstr[256];
71767cc0636SGreg Clayton   snprintf(instance_cstr, sizeof(instance_cstr), "debugger_%d", (int)GetID());
71867cc0636SGreg Clayton   m_instance_name.SetCString(instance_cstr);
719228063cdSJim Ingham   if (log_callback)
720228063cdSJim Ingham     m_log_callback_stream_sp.reset(new StreamCallback(log_callback, baton));
7216611103cSGreg Clayton   m_command_interpreter_ap->Initialize();
722ded470d3SGreg Clayton   // Always add our default platform to the platform list
723615eb7e6SGreg Clayton   PlatformSP default_platform_sp(Platform::GetHostPlatform());
724df370550SEugene Zelenko   assert(default_platform_sp);
725ded470d3SGreg Clayton   m_platform_list.Append(default_platform_sp, true);
72667cc0636SGreg Clayton 
727754a9369SGreg Clayton   m_collection_sp->Initialize(g_properties);
728b9c1b51eSKate Stone   m_collection_sp->AppendProperty(
729b9c1b51eSKate Stone       ConstString("target"),
730b9c1b51eSKate Stone       ConstString("Settings specify to debugging targets."), true,
73167cc0636SGreg Clayton       Target::GetGlobalProperties()->GetValueProperties());
732b9c1b51eSKate Stone   m_collection_sp->AppendProperty(
733b9c1b51eSKate Stone       ConstString("platform"), ConstString("Platform settings."), true,
73463acdfdeSOleksiy Vyalov       Platform::GetGlobalPlatformProperties()->GetValueProperties());
735b9c1b51eSKate Stone   if (m_command_interpreter_ap) {
736b9c1b51eSKate Stone     m_collection_sp->AppendProperty(
737b9c1b51eSKate Stone         ConstString("interpreter"),
738754a9369SGreg Clayton         ConstString("Settings specify to the debugger's command interpreter."),
739b9c1b51eSKate Stone         true, m_command_interpreter_ap->GetValueProperties());
740754a9369SGreg Clayton   }
741b9c1b51eSKate Stone   OptionValueSInt64 *term_width =
742b9c1b51eSKate Stone       m_collection_sp->GetPropertyAtIndexAsOptionValueSInt64(
743b9c1b51eSKate Stone           nullptr, ePropertyTerminalWidth);
74467cc0636SGreg Clayton   term_width->SetMinimumValue(10);
74567cc0636SGreg Clayton   term_width->SetMaximumValue(1024);
746c3ce7f27SMichael Sartain 
747c3ce7f27SMichael Sartain   // Turn off use-color if this is a dumb terminal.
748c3ce7f27SMichael Sartain   const char *term = getenv("TERM");
749c3ce7f27SMichael Sartain   if (term && !strcmp(term, "dumb"))
750c3ce7f27SMichael Sartain     SetUseColor(false);
75130fdc8d8SChris Lattner }
75230fdc8d8SChris Lattner 
753b9c1b51eSKate Stone Debugger::~Debugger() { Clear(); }
7548314c525SJim Ingham 
755b9c1b51eSKate Stone void Debugger::Clear() {
7564329fe42SGreg Clayton   //----------------------------------------------------------------------
7574329fe42SGreg Clayton   // Make sure we call this function only once. With the C++ global
7584329fe42SGreg Clayton   // destructor chain having a list of debuggers and with code that can be
7594329fe42SGreg Clayton   // running on other threads, we need to ensure this doesn't happen
7604329fe42SGreg Clayton   // multiple times.
7614329fe42SGreg Clayton   //
7624329fe42SGreg Clayton   // The following functions call Debugger::Clear():
7634329fe42SGreg Clayton   //     Debugger::~Debugger();
7644329fe42SGreg Clayton   //     static void Debugger::Destroy(lldb::DebuggerSP &debugger_sp);
7654329fe42SGreg Clayton   //     static void Debugger::Terminate();
7664329fe42SGreg Clayton   //----------------------------------------------------------------------
767c5f28e2aSKamil Rytarowski   llvm::call_once(m_clear_once, [this]() {
76844d93782SGreg Clayton     ClearIOHandlers();
76944d93782SGreg Clayton     StopIOHandlerThread();
77044d93782SGreg Clayton     StopEventHandlerThread();
771583bbb1dSJim Ingham     m_listener_sp->Clear();
7726611103cSGreg Clayton     int num_targets = m_target_list.GetNumTargets();
773b9c1b51eSKate Stone     for (int i = 0; i < num_targets; i++) {
774ccbc08e6SGreg Clayton       TargetSP target_sp(m_target_list.GetTargetAtIndex(i));
775b9c1b51eSKate Stone       if (target_sp) {
776ccbc08e6SGreg Clayton         ProcessSP process_sp(target_sp->GetProcessSP());
7776611103cSGreg Clayton         if (process_sp)
7781fd07059SJim Ingham           process_sp->Finalize();
779ccbc08e6SGreg Clayton         target_sp->Destroy();
7806611103cSGreg Clayton       }
78130fdc8d8SChris Lattner     }
782583bbb1dSJim Ingham     m_broadcaster_manager_sp->Clear();
78330fdc8d8SChris Lattner 
784b9c1b51eSKate Stone     // Close the input file _before_ we close the input read communications
785b9c1b51eSKate Stone     // class
7860d69a3a4SGreg Clayton     // as it does NOT own the input file, our m_input_file does.
787c5917d9aSJim Ingham     m_terminal_state.Clear();
78844d93782SGreg Clayton     if (m_input_file_sp)
78944d93782SGreg Clayton       m_input_file_sp->GetFile().Close();
7900c4129f2SGreg Clayton 
7910c4129f2SGreg Clayton     m_command_interpreter_ap->Clear();
7924329fe42SGreg Clayton   });
7938314c525SJim Ingham }
79430fdc8d8SChris Lattner 
795b9c1b51eSKate Stone bool Debugger::GetCloseInputOnEOF() const {
79644d93782SGreg Clayton   //    return m_input_comm.GetCloseOnEOF();
79744d93782SGreg Clayton   return false;
798fc3f027dSGreg Clayton }
799fc3f027dSGreg Clayton 
800b9c1b51eSKate Stone void Debugger::SetCloseInputOnEOF(bool b) {
80144d93782SGreg Clayton   //    m_input_comm.SetCloseOnEOF(b);
802fc3f027dSGreg Clayton }
803fc3f027dSGreg Clayton 
804b9c1b51eSKate Stone bool Debugger::GetAsyncExecution() {
8056611103cSGreg Clayton   return !m_command_interpreter_ap->GetSynchronous();
80630fdc8d8SChris Lattner }
80730fdc8d8SChris Lattner 
808b9c1b51eSKate Stone void Debugger::SetAsyncExecution(bool async_execution) {
8096611103cSGreg Clayton   m_command_interpreter_ap->SetSynchronous(!async_execution);
81030fdc8d8SChris Lattner }
81130fdc8d8SChris Lattner 
812b9c1b51eSKate Stone void Debugger::SetInputFileHandle(FILE *fh, bool tranfer_ownership) {
81344d93782SGreg Clayton   if (m_input_file_sp)
81444d93782SGreg Clayton     m_input_file_sp->GetFile().SetStream(fh, tranfer_ownership);
81544d93782SGreg Clayton   else
81644d93782SGreg Clayton     m_input_file_sp.reset(new StreamFile(fh, tranfer_ownership));
81744d93782SGreg Clayton 
81844d93782SGreg Clayton   File &in_file = m_input_file_sp->GetFile();
819df370550SEugene Zelenko   if (!in_file.IsValid())
82051b1e2d2SGreg Clayton     in_file.SetStream(stdin, true);
82130fdc8d8SChris Lattner 
822b9c1b51eSKate Stone   // Save away the terminal state if that is relevant, so that we can restore it
823b9c1b51eSKate Stone   // in RestoreInputState.
824c5917d9aSJim Ingham   SaveInputTerminalState();
82530fdc8d8SChris Lattner }
82630fdc8d8SChris Lattner 
827b9c1b51eSKate Stone void Debugger::SetOutputFileHandle(FILE *fh, bool tranfer_ownership) {
82844d93782SGreg Clayton   if (m_output_file_sp)
82944d93782SGreg Clayton     m_output_file_sp->GetFile().SetStream(fh, tranfer_ownership);
83044d93782SGreg Clayton   else
83144d93782SGreg Clayton     m_output_file_sp.reset(new StreamFile(fh, tranfer_ownership));
83244d93782SGreg Clayton 
83344d93782SGreg Clayton   File &out_file = m_output_file_sp->GetFile();
834df370550SEugene Zelenko   if (!out_file.IsValid())
83551b1e2d2SGreg Clayton     out_file.SetStream(stdout, false);
8362f88aadfSCaroline Tice 
837b588726eSEnrico Granata   // do not create the ScriptInterpreter just for setting the output file handle
838b588726eSEnrico Granata   // as the constructor will know how to do the right thing on its own
839b588726eSEnrico Granata   const bool can_create = false;
840b9c1b51eSKate Stone   ScriptInterpreter *script_interpreter =
841b9c1b51eSKate Stone       GetCommandInterpreter().GetScriptInterpreter(can_create);
842b588726eSEnrico Granata   if (script_interpreter)
843b588726eSEnrico Granata     script_interpreter->ResetOutputFileHandle(fh);
84430fdc8d8SChris Lattner }
84530fdc8d8SChris Lattner 
846b9c1b51eSKate Stone void Debugger::SetErrorFileHandle(FILE *fh, bool tranfer_ownership) {
84744d93782SGreg Clayton   if (m_error_file_sp)
84844d93782SGreg Clayton     m_error_file_sp->GetFile().SetStream(fh, tranfer_ownership);
84944d93782SGreg Clayton   else
85044d93782SGreg Clayton     m_error_file_sp.reset(new StreamFile(fh, tranfer_ownership));
85144d93782SGreg Clayton 
85244d93782SGreg Clayton   File &err_file = m_error_file_sp->GetFile();
853df370550SEugene Zelenko   if (!err_file.IsValid())
85451b1e2d2SGreg Clayton     err_file.SetStream(stderr, false);
85530fdc8d8SChris Lattner }
85630fdc8d8SChris Lattner 
857b9c1b51eSKate Stone void Debugger::SaveInputTerminalState() {
858b9c1b51eSKate Stone   if (m_input_file_sp) {
85944d93782SGreg Clayton     File &in_file = m_input_file_sp->GetFile();
860c5917d9aSJim Ingham     if (in_file.GetDescriptor() != File::kInvalidDescriptor)
861c5917d9aSJim Ingham       m_terminal_state.Save(in_file.GetDescriptor(), true);
862c5917d9aSJim Ingham   }
86344d93782SGreg Clayton }
864c5917d9aSJim Ingham 
865b9c1b51eSKate Stone void Debugger::RestoreInputTerminalState() { m_terminal_state.Restore(); }
866c5917d9aSJim Ingham 
867b9c1b51eSKate Stone ExecutionContext Debugger::GetSelectedExecutionContext() {
86830fdc8d8SChris Lattner   ExecutionContext exe_ctx;
869c14ee32dSGreg Clayton   TargetSP target_sp(GetSelectedTarget());
870c14ee32dSGreg Clayton   exe_ctx.SetTargetSP(target_sp);
87130fdc8d8SChris Lattner 
872b9c1b51eSKate Stone   if (target_sp) {
873c14ee32dSGreg Clayton     ProcessSP process_sp(target_sp->GetProcessSP());
874c14ee32dSGreg Clayton     exe_ctx.SetProcessSP(process_sp);
875b9c1b51eSKate Stone     if (process_sp && !process_sp->IsRunning()) {
876c14ee32dSGreg Clayton       ThreadSP thread_sp(process_sp->GetThreadList().GetSelectedThread());
877b9c1b51eSKate Stone       if (thread_sp) {
878c14ee32dSGreg Clayton         exe_ctx.SetThreadSP(thread_sp);
879c14ee32dSGreg Clayton         exe_ctx.SetFrameSP(thread_sp->GetSelectedFrame());
880df370550SEugene Zelenko         if (exe_ctx.GetFramePtr() == nullptr)
881c14ee32dSGreg Clayton           exe_ctx.SetFrameSP(thread_sp->GetStackFrameAtIndex(0));
88230fdc8d8SChris Lattner       }
88330fdc8d8SChris Lattner     }
88430fdc8d8SChris Lattner   }
88530fdc8d8SChris Lattner   return exe_ctx;
88630fdc8d8SChris Lattner }
88730fdc8d8SChris Lattner 
888b9c1b51eSKate Stone void Debugger::DispatchInputInterrupt() {
88916ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex());
89044d93782SGreg Clayton   IOHandlerSP reader_sp(m_input_reader_stack.Top());
891efed6131SCaroline Tice   if (reader_sp)
89244d93782SGreg Clayton     reader_sp->Interrupt();
893efed6131SCaroline Tice }
894efed6131SCaroline Tice 
895b9c1b51eSKate Stone void Debugger::DispatchInputEndOfFile() {
89616ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex());
89744d93782SGreg Clayton   IOHandlerSP reader_sp(m_input_reader_stack.Top());
898efed6131SCaroline Tice   if (reader_sp)
89944d93782SGreg Clayton     reader_sp->GotEOF();
900efed6131SCaroline Tice }
901efed6131SCaroline Tice 
902b9c1b51eSKate Stone void Debugger::ClearIOHandlers() {
903b9c1b51eSKate Stone   // The bottom input reader should be the main debugger input reader.  We do
904b9c1b51eSKate Stone   // not want to close that one here.
90516ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex());
906b9c1b51eSKate Stone   while (m_input_reader_stack.GetSize() > 1) {
90744d93782SGreg Clayton     IOHandlerSP reader_sp(m_input_reader_stack.Top());
9083d6086f6SCaroline Tice     if (reader_sp)
9094446487dSPavel Labath       PopIOHandler(reader_sp);
9103d6086f6SCaroline Tice   }
9113d6086f6SCaroline Tice }
9123d6086f6SCaroline Tice 
913b9c1b51eSKate Stone void Debugger::ExecuteIOHandlers() {
914b9c1b51eSKate Stone   while (true) {
91544d93782SGreg Clayton     IOHandlerSP reader_sp(m_input_reader_stack.Top());
91630fdc8d8SChris Lattner     if (!reader_sp)
91730fdc8d8SChris Lattner       break;
91830fdc8d8SChris Lattner 
91944d93782SGreg Clayton     reader_sp->Run();
92044d93782SGreg Clayton 
92144d93782SGreg Clayton     // Remove all input readers that are done from the top of the stack
922b9c1b51eSKate Stone     while (true) {
92344d93782SGreg Clayton       IOHandlerSP top_reader_sp = m_input_reader_stack.Top();
92444d93782SGreg Clayton       if (top_reader_sp && top_reader_sp->GetIsDone())
9254446487dSPavel Labath         PopIOHandler(top_reader_sp);
92630fdc8d8SChris Lattner       else
92730fdc8d8SChris Lattner         break;
92830fdc8d8SChris Lattner     }
92930fdc8d8SChris Lattner   }
93044d93782SGreg Clayton   ClearIOHandlers();
93144d93782SGreg Clayton }
93230fdc8d8SChris Lattner 
933b9c1b51eSKate Stone bool Debugger::IsTopIOHandler(const lldb::IOHandlerSP &reader_sp) {
93444d93782SGreg Clayton   return m_input_reader_stack.IsTop(reader_sp);
93544d93782SGreg Clayton }
93630fdc8d8SChris Lattner 
937b9c1b51eSKate Stone bool Debugger::CheckTopIOHandlerTypes(IOHandler::Type top_type,
938b9c1b51eSKate Stone                                       IOHandler::Type second_top_type) {
9396681041dSSean Callanan   return m_input_reader_stack.CheckTopIOHandlerTypes(top_type, second_top_type);
9406681041dSSean Callanan }
9416681041dSSean Callanan 
942b9c1b51eSKate Stone void Debugger::PrintAsync(const char *s, size_t len, bool is_stdout) {
9434446487dSPavel Labath   lldb::StreamFileSP stream = is_stdout ? GetOutputFile() : GetErrorFile();
9444446487dSPavel Labath   m_input_reader_stack.PrintAsync(stream.get(), s, len);
9454446487dSPavel Labath }
94644d93782SGreg Clayton 
947b9c1b51eSKate Stone ConstString Debugger::GetTopIOHandlerControlSequence(char ch) {
94844d93782SGreg Clayton   return m_input_reader_stack.GetTopIOHandlerControlSequence(ch);
94930fdc8d8SChris Lattner }
95030fdc8d8SChris Lattner 
951b9c1b51eSKate Stone const char *Debugger::GetIOHandlerCommandPrefix() {
952a487aa4cSKate Stone   return m_input_reader_stack.GetTopIOHandlerCommandPrefix();
953a487aa4cSKate Stone }
954a487aa4cSKate Stone 
955b9c1b51eSKate Stone const char *Debugger::GetIOHandlerHelpPrologue() {
956a487aa4cSKate Stone   return m_input_reader_stack.GetTopIOHandlerHelpPrologue();
957a487aa4cSKate Stone }
958a487aa4cSKate Stone 
959b9c1b51eSKate Stone void Debugger::RunIOHandler(const IOHandlerSP &reader_sp) {
96044d93782SGreg Clayton   PushIOHandler(reader_sp);
961577508dfSGreg Clayton 
962577508dfSGreg Clayton   IOHandlerSP top_reader_sp = reader_sp;
963b9c1b51eSKate Stone   while (top_reader_sp) {
964577508dfSGreg Clayton     top_reader_sp->Run();
965577508dfSGreg Clayton 
966b9c1b51eSKate Stone     if (top_reader_sp.get() == reader_sp.get()) {
967577508dfSGreg Clayton       if (PopIOHandler(reader_sp))
968577508dfSGreg Clayton         break;
969577508dfSGreg Clayton     }
970577508dfSGreg Clayton 
971b9c1b51eSKate Stone     while (true) {
972577508dfSGreg Clayton       top_reader_sp = m_input_reader_stack.Top();
973577508dfSGreg Clayton       if (top_reader_sp && top_reader_sp->GetIsDone())
9744446487dSPavel Labath         PopIOHandler(top_reader_sp);
975577508dfSGreg Clayton       else
976577508dfSGreg Clayton         break;
977577508dfSGreg Clayton     }
978577508dfSGreg Clayton   }
97944d93782SGreg Clayton }
98044d93782SGreg Clayton 
981b9c1b51eSKate Stone void Debugger::AdoptTopIOHandlerFilesIfInvalid(StreamFileSP &in,
982b9c1b51eSKate Stone                                                StreamFileSP &out,
983b9c1b51eSKate Stone                                                StreamFileSP &err) {
98444d93782SGreg Clayton   // Before an IOHandler runs, it must have in/out/err streams.
98544d93782SGreg Clayton   // This function is called when one ore more of the streams
986df370550SEugene Zelenko   // are nullptr. We use the top input reader's in/out/err streams,
98744d93782SGreg Clayton   // or fall back to the debugger file handles, or we fall back
98844d93782SGreg Clayton   // onto stdin/stdout/stderr as a last resort.
98944d93782SGreg Clayton 
99016ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex());
99144d93782SGreg Clayton   IOHandlerSP top_reader_sp(m_input_reader_stack.Top());
99244d93782SGreg Clayton   // If no STDIN has been set, then set it appropriately
993b9c1b51eSKate Stone   if (!in) {
99444d93782SGreg Clayton     if (top_reader_sp)
99544d93782SGreg Clayton       in = top_reader_sp->GetInputStreamFile();
99644d93782SGreg Clayton     else
99744d93782SGreg Clayton       in = GetInputFile();
99844d93782SGreg Clayton 
99944d93782SGreg Clayton     // If there is nothing, use stdin
100044d93782SGreg Clayton     if (!in)
100144d93782SGreg Clayton       in = StreamFileSP(new StreamFile(stdin, false));
100244d93782SGreg Clayton   }
100344d93782SGreg Clayton   // If no STDOUT has been set, then set it appropriately
1004b9c1b51eSKate Stone   if (!out) {
100544d93782SGreg Clayton     if (top_reader_sp)
100644d93782SGreg Clayton       out = top_reader_sp->GetOutputStreamFile();
100744d93782SGreg Clayton     else
100844d93782SGreg Clayton       out = GetOutputFile();
100944d93782SGreg Clayton 
101044d93782SGreg Clayton     // If there is nothing, use stdout
101144d93782SGreg Clayton     if (!out)
101244d93782SGreg Clayton       out = StreamFileSP(new StreamFile(stdout, false));
101344d93782SGreg Clayton   }
101444d93782SGreg Clayton   // If no STDERR has been set, then set it appropriately
1015b9c1b51eSKate Stone   if (!err) {
101644d93782SGreg Clayton     if (top_reader_sp)
101744d93782SGreg Clayton       err = top_reader_sp->GetErrorStreamFile();
101844d93782SGreg Clayton     else
101944d93782SGreg Clayton       err = GetErrorFile();
102044d93782SGreg Clayton 
102144d93782SGreg Clayton     // If there is nothing, use stderr
102244d93782SGreg Clayton     if (!err)
102344d93782SGreg Clayton       err = StreamFileSP(new StreamFile(stdout, false));
102444d93782SGreg Clayton   }
102544d93782SGreg Clayton }
102644d93782SGreg Clayton 
1027b9c1b51eSKate Stone void Debugger::PushIOHandler(const IOHandlerSP &reader_sp) {
102830fdc8d8SChris Lattner   if (!reader_sp)
102930fdc8d8SChris Lattner     return;
1030b44880caSCaroline Tice 
103116ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex());
10324446487dSPavel Labath 
10334446487dSPavel Labath   // Get the current top input reader...
103444d93782SGreg Clayton   IOHandlerSP top_reader_sp(m_input_reader_stack.Top());
1035b44880caSCaroline Tice 
1036b4874f1aSGreg Clayton   // Don't push the same IO handler twice...
10374446487dSPavel Labath   if (reader_sp == top_reader_sp)
10384446487dSPavel Labath     return;
10394446487dSPavel Labath 
104044d93782SGreg Clayton   // Push our new input reader
1041d5a0a01bSCaroline Tice   m_input_reader_stack.Push(reader_sp);
10424446487dSPavel Labath   reader_sp->Activate();
104344d93782SGreg Clayton 
104444d93782SGreg Clayton   // Interrupt the top input reader to it will exit its Run() function
104544d93782SGreg Clayton   // and let this new input reader take over
1046b9c1b51eSKate Stone   if (top_reader_sp) {
104744d93782SGreg Clayton     top_reader_sp->Deactivate();
10484446487dSPavel Labath     top_reader_sp->Cancel();
104930fdc8d8SChris Lattner   }
1050b4874f1aSGreg Clayton }
105130fdc8d8SChris Lattner 
1052b9c1b51eSKate Stone bool Debugger::PopIOHandler(const IOHandlerSP &pop_reader_sp) {
10534446487dSPavel Labath   if (!pop_reader_sp)
10544446487dSPavel Labath     return false;
105530fdc8d8SChris Lattner 
105616ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex());
105744d93782SGreg Clayton 
105830fdc8d8SChris Lattner   // The reader on the stop of the stack is done, so let the next
10596a7f3338SBruce Mitchener   // read on the stack refresh its prompt and if there is one...
10604446487dSPavel Labath   if (m_input_reader_stack.IsEmpty())
10614446487dSPavel Labath     return false;
10624446487dSPavel Labath 
106344d93782SGreg Clayton   IOHandlerSP reader_sp(m_input_reader_stack.Top());
106430fdc8d8SChris Lattner 
10654446487dSPavel Labath   if (pop_reader_sp != reader_sp)
10664446487dSPavel Labath     return false;
10674446487dSPavel Labath 
106844d93782SGreg Clayton   reader_sp->Deactivate();
1069b4874f1aSGreg Clayton   reader_sp->Cancel();
1070d5a0a01bSCaroline Tice   m_input_reader_stack.Pop();
107130fdc8d8SChris Lattner 
1072d5a0a01bSCaroline Tice   reader_sp = m_input_reader_stack.Top();
107330fdc8d8SChris Lattner   if (reader_sp)
107444d93782SGreg Clayton     reader_sp->Activate();
107544d93782SGreg Clayton 
107644d93782SGreg Clayton   return true;
107730fdc8d8SChris Lattner }
10786611103cSGreg Clayton 
1079b9c1b51eSKate Stone StreamSP Debugger::GetAsyncOutputStream() {
10804446487dSPavel Labath   return StreamSP(new StreamAsynchronousIO(*this, true));
10815b52f0c7SJim Ingham }
10825b52f0c7SJim Ingham 
1083b9c1b51eSKate Stone StreamSP Debugger::GetAsyncErrorStream() {
10844446487dSPavel Labath   return StreamSP(new StreamAsynchronousIO(*this, false));
10855b52f0c7SJim Ingham }
10865b52f0c7SJim Ingham 
1087b9c1b51eSKate Stone size_t Debugger::GetNumDebuggers() {
1088b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
10896c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
10906c42e063SGreg Clayton     return g_debugger_list_ptr->size();
1091061858ceSEnrico Granata   }
1092c15f55e2SGreg Clayton   return 0;
1093c15f55e2SGreg Clayton }
1094061858ceSEnrico Granata 
1095b9c1b51eSKate Stone lldb::DebuggerSP Debugger::GetDebuggerAtIndex(size_t index) {
1096061858ceSEnrico Granata   DebuggerSP debugger_sp;
1097061858ceSEnrico Granata 
1098b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
10996c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
11006c42e063SGreg Clayton     if (index < g_debugger_list_ptr->size())
11016c42e063SGreg Clayton       debugger_sp = g_debugger_list_ptr->at(index);
1102c15f55e2SGreg Clayton   }
1103061858ceSEnrico Granata 
1104061858ceSEnrico Granata   return debugger_sp;
1105061858ceSEnrico Granata }
1106061858ceSEnrico Granata 
1107b9c1b51eSKate Stone DebuggerSP Debugger::FindDebuggerWithID(lldb::user_id_t id) {
11084d122c40SGreg Clayton   DebuggerSP debugger_sp;
1109ebc1bb27SCaroline Tice 
1110b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
11116c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
11126c42e063SGreg Clayton     DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
1113b9c1b51eSKate Stone     for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
1114b9c1b51eSKate Stone       if ((*pos)->GetID() == id) {
1115ebc1bb27SCaroline Tice         debugger_sp = *pos;
1116ebc1bb27SCaroline Tice         break;
1117ebc1bb27SCaroline Tice       }
1118ebc1bb27SCaroline Tice     }
1119c15f55e2SGreg Clayton   }
1120ebc1bb27SCaroline Tice   return debugger_sp;
1121ebc1bb27SCaroline Tice }
11223df9a8dfSCaroline Tice 
11232643b905SSaleem Abdulrasool #if 0
11241b654882SGreg Clayton static void
1125b57e4a1bSJason Molenda TestPromptFormats (StackFrame *frame)
11261b654882SGreg Clayton {
1127df370550SEugene Zelenko     if (frame == nullptr)
11281b654882SGreg Clayton         return;
11291b654882SGreg Clayton 
11301b654882SGreg Clayton     StreamString s;
11311b654882SGreg Clayton     const char *prompt_format =
11321b654882SGreg Clayton     "{addr = '${addr}'\n}"
1133aff1b357SJason Molenda     "{addr-file-or-load = '${addr-file-or-load}'\n}"
1134aff1b357SJason Molenda     "{current-pc-arrow = '${current-pc-arrow}'\n}"
11351b654882SGreg Clayton     "{process.id = '${process.id}'\n}"
11361b654882SGreg Clayton     "{process.name = '${process.name}'\n}"
11371b654882SGreg Clayton     "{process.file.basename = '${process.file.basename}'\n}"
11381b654882SGreg Clayton     "{process.file.fullpath = '${process.file.fullpath}'\n}"
11391b654882SGreg Clayton     "{thread.id = '${thread.id}'\n}"
11401b654882SGreg Clayton     "{thread.index = '${thread.index}'\n}"
11411b654882SGreg Clayton     "{thread.name = '${thread.name}'\n}"
11421b654882SGreg Clayton     "{thread.queue = '${thread.queue}'\n}"
11431b654882SGreg Clayton     "{thread.stop-reason = '${thread.stop-reason}'\n}"
11441b654882SGreg Clayton     "{target.arch = '${target.arch}'\n}"
11451b654882SGreg Clayton     "{module.file.basename = '${module.file.basename}'\n}"
11461b654882SGreg Clayton     "{module.file.fullpath = '${module.file.fullpath}'\n}"
11471b654882SGreg Clayton     "{file.basename = '${file.basename}'\n}"
11481b654882SGreg Clayton     "{file.fullpath = '${file.fullpath}'\n}"
11491b654882SGreg Clayton     "{frame.index = '${frame.index}'\n}"
11501b654882SGreg Clayton     "{frame.pc = '${frame.pc}'\n}"
11511b654882SGreg Clayton     "{frame.sp = '${frame.sp}'\n}"
11521b654882SGreg Clayton     "{frame.fp = '${frame.fp}'\n}"
11531b654882SGreg Clayton     "{frame.flags = '${frame.flags}'\n}"
11541b654882SGreg Clayton     "{frame.reg.rdi = '${frame.reg.rdi}'\n}"
11551b654882SGreg Clayton     "{frame.reg.rip = '${frame.reg.rip}'\n}"
11561b654882SGreg Clayton     "{frame.reg.rsp = '${frame.reg.rsp}'\n}"
11571b654882SGreg Clayton     "{frame.reg.rbp = '${frame.reg.rbp}'\n}"
11581b654882SGreg Clayton     "{frame.reg.rflags = '${frame.reg.rflags}'\n}"
11591b654882SGreg Clayton     "{frame.reg.xmm0 = '${frame.reg.xmm0}'\n}"
11601b654882SGreg Clayton     "{frame.reg.carp = '${frame.reg.carp}'\n}"
11611b654882SGreg Clayton     "{function.id = '${function.id}'\n}"
1162aff1b357SJason Molenda     "{function.changed = '${function.changed}'\n}"
1163aff1b357SJason Molenda     "{function.initial-function = '${function.initial-function}'\n}"
11641b654882SGreg Clayton     "{function.name = '${function.name}'\n}"
1165aff1b357SJason Molenda     "{function.name-without-args = '${function.name-without-args}'\n}"
1166ccbc08e6SGreg Clayton     "{function.name-with-args = '${function.name-with-args}'\n}"
11671b654882SGreg Clayton     "{function.addr-offset = '${function.addr-offset}'\n}"
1168aff1b357SJason Molenda     "{function.concrete-only-addr-offset-no-padding = '${function.concrete-only-addr-offset-no-padding}'\n}"
11691b654882SGreg Clayton     "{function.line-offset = '${function.line-offset}'\n}"
11701b654882SGreg Clayton     "{function.pc-offset = '${function.pc-offset}'\n}"
11711b654882SGreg Clayton     "{line.file.basename = '${line.file.basename}'\n}"
11721b654882SGreg Clayton     "{line.file.fullpath = '${line.file.fullpath}'\n}"
11731b654882SGreg Clayton     "{line.number = '${line.number}'\n}"
11741b654882SGreg Clayton     "{line.start-addr = '${line.start-addr}'\n}"
11751b654882SGreg Clayton     "{line.end-addr = '${line.end-addr}'\n}"
11761b654882SGreg Clayton ;
11771b654882SGreg Clayton 
11781b654882SGreg Clayton     SymbolContext sc (frame->GetSymbolContext(eSymbolContextEverything));
11791b654882SGreg Clayton     ExecutionContext exe_ctx;
11800603aa9dSGreg Clayton     frame->CalculateExecutionContext(exe_ctx);
1181c3ce7f27SMichael Sartain     if (Debugger::FormatPrompt (prompt_format, &sc, &exe_ctx, &sc.line_entry.range.GetBaseAddress(), s))
11821b654882SGreg Clayton     {
11831b654882SGreg Clayton         printf("%s\n", s.GetData());
11841b654882SGreg Clayton     }
11851b654882SGreg Clayton     else
11861b654882SGreg Clayton     {
11871b654882SGreg Clayton         printf ("what we got: %s\n", s.GetData());
11881b654882SGreg Clayton     }
11891b654882SGreg Clayton }
11902643b905SSaleem Abdulrasool #endif
11911b654882SGreg Clayton 
1192b9c1b51eSKate Stone bool Debugger::FormatDisassemblerAddress(const FormatEntity::Entry *format,
1193aff1b357SJason Molenda                                          const SymbolContext *sc,
1194aff1b357SJason Molenda                                          const SymbolContext *prev_sc,
1195aff1b357SJason Molenda                                          const ExecutionContext *exe_ctx,
1196b9c1b51eSKate Stone                                          const Address *addr, Stream &s) {
1197554f68d3SGreg Clayton   FormatEntity::Entry format_entry;
1198554f68d3SGreg Clayton 
1199b9c1b51eSKate Stone   if (format == nullptr) {
1200df370550SEugene Zelenko     if (exe_ctx != nullptr && exe_ctx->HasTargetScope())
1201aff1b357SJason Molenda       format = exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat();
1202b9c1b51eSKate Stone     if (format == nullptr) {
1203554f68d3SGreg Clayton       FormatEntity::Parse("${addr}: ", format_entry);
1204554f68d3SGreg Clayton       format = &format_entry;
1205554f68d3SGreg Clayton     }
1206aff1b357SJason Molenda   }
1207aff1b357SJason Molenda   bool function_changed = false;
1208aff1b357SJason Molenda   bool initial_function = false;
1209b9c1b51eSKate Stone   if (prev_sc && (prev_sc->function || prev_sc->symbol)) {
1210b9c1b51eSKate Stone     if (sc && (sc->function || sc->symbol)) {
1211b9c1b51eSKate Stone       if (prev_sc->symbol && sc->symbol) {
1212b9c1b51eSKate Stone         if (!sc->symbol->Compare(prev_sc->symbol->GetName(),
1213b9c1b51eSKate Stone                                  prev_sc->symbol->GetType())) {
1214aff1b357SJason Molenda           function_changed = true;
1215aff1b357SJason Molenda         }
1216b9c1b51eSKate Stone       } else if (prev_sc->function && sc->function) {
1217b9c1b51eSKate Stone         if (prev_sc->function->GetMangled() != sc->function->GetMangled()) {
1218aff1b357SJason Molenda           function_changed = true;
1219aff1b357SJason Molenda         }
1220aff1b357SJason Molenda       }
1221aff1b357SJason Molenda     }
1222aff1b357SJason Molenda   }
1223aff1b357SJason Molenda   // The first context on a list of instructions will have a prev_sc that
1224aff1b357SJason Molenda   // has no Function or Symbol -- if SymbolContext had an IsValid() method, it
1225aff1b357SJason Molenda   // would return false.  But we do get a prev_sc pointer.
1226b9c1b51eSKate Stone   if ((sc && (sc->function || sc->symbol)) && prev_sc &&
1227b9c1b51eSKate Stone       (prev_sc->function == nullptr && prev_sc->symbol == nullptr)) {
1228aff1b357SJason Molenda     initial_function = true;
1229aff1b357SJason Molenda   }
1230b9c1b51eSKate Stone   return FormatEntity::Format(*format, s, sc, exe_ctx, addr, nullptr,
1231b9c1b51eSKate Stone                               function_changed, initial_function);
1232aff1b357SJason Molenda }
1233aff1b357SJason Molenda 
1234b9c1b51eSKate Stone void Debugger::SetLoggingCallback(lldb::LogOutputCallback log_callback,
1235b9c1b51eSKate Stone                                   void *baton) {
12364f02b22dSJim Ingham   // For simplicity's sake, I am not going to deal with how to close down any
12374f02b22dSJim Ingham   // open logging streams, I just redirect everything from here on out to the
12384f02b22dSJim Ingham   // callback.
1239228063cdSJim Ingham   m_log_callback_stream_sp.reset(new StreamCallback(log_callback, baton));
1240228063cdSJim Ingham }
1241228063cdSJim Ingham 
12425e336903SPavel Labath bool Debugger::EnableLog(llvm::StringRef channel,
12435e336903SPavel Labath                          llvm::ArrayRef<const char *> categories,
12445e336903SPavel Labath                          llvm::StringRef log_file, uint32_t log_options,
1245b9c1b51eSKate Stone                          Stream &error_stream) {
12465fae71c5SPavel Labath   const bool should_close = true;
12475fae71c5SPavel Labath   const bool unbuffered = true;
12485fae71c5SPavel Labath 
12495fae71c5SPavel Labath   std::shared_ptr<llvm::raw_ostream> log_stream_sp;
1250b9c1b51eSKate Stone   if (m_log_callback_stream_sp) {
1251228063cdSJim Ingham     log_stream_sp = m_log_callback_stream_sp;
1252228063cdSJim Ingham     // For now when using the callback mode you always get thread & timestamp.
1253b9c1b51eSKate Stone     log_options |=
1254b9c1b51eSKate Stone         LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_THREAD_NAME;
12555e336903SPavel Labath   } else if (log_file.empty()) {
12565fae71c5SPavel Labath     log_stream_sp = std::make_shared<llvm::raw_fd_ostream>(
12575fae71c5SPavel Labath         GetOutputFile()->GetFile().GetDescriptor(), !should_close, unbuffered);
1258b9c1b51eSKate Stone   } else {
12595fae71c5SPavel Labath     auto pos = m_log_streams.find(log_file);
1260c1b2ccfdSGreg Clayton     if (pos != m_log_streams.end())
1261c1b2ccfdSGreg Clayton       log_stream_sp = pos->second.lock();
1262b9c1b51eSKate Stone     if (!log_stream_sp) {
12635fae71c5SPavel Labath       llvm::sys::fs::OpenFlags flags = llvm::sys::fs::F_Text;
12645fae71c5SPavel Labath       if (log_options & LLDB_LOG_OPTION_APPEND)
12655fae71c5SPavel Labath         flags |= llvm::sys::fs::F_Append;
12665fae71c5SPavel Labath       int FD;
12675fae71c5SPavel Labath       if (std::error_code ec =
12685fae71c5SPavel Labath               llvm::sys::fs::openFileForWrite(log_file, FD, flags)) {
12695fae71c5SPavel Labath         error_stream.Format("Unable to open log file: {0}", ec.message());
12705fae71c5SPavel Labath         return false;
12715fae71c5SPavel Labath       }
12725fae71c5SPavel Labath       log_stream_sp.reset(
12735fae71c5SPavel Labath           new llvm::raw_fd_ostream(FD, should_close, unbuffered));
1274228063cdSJim Ingham       m_log_streams[log_file] = log_stream_sp;
1275228063cdSJim Ingham     }
1276228063cdSJim Ingham   }
1277df370550SEugene Zelenko   assert(log_stream_sp);
1278228063cdSJim Ingham 
1279228063cdSJim Ingham   if (log_options == 0)
1280b9c1b51eSKate Stone     log_options =
1281b9c1b51eSKate Stone         LLDB_LOG_OPTION_PREPEND_THREAD_NAME | LLDB_LOG_OPTION_THREADSAFE;
1282228063cdSJim Ingham 
1283b9c1b51eSKate Stone   return Log::EnableLogChannel(log_stream_sp, log_options, channel, categories,
1284b9c1b51eSKate Stone                                error_stream);
1285228063cdSJim Ingham }
1286228063cdSJim Ingham 
1287b9c1b51eSKate Stone SourceManager &Debugger::GetSourceManager() {
1288df370550SEugene Zelenko   if (!m_source_manager_ap)
12899585fbfcSGreg Clayton     m_source_manager_ap.reset(new SourceManager(shared_from_this()));
12909585fbfcSGreg Clayton   return *m_source_manager_ap;
12919585fbfcSGreg Clayton }
12929585fbfcSGreg Clayton 
129344d93782SGreg Clayton // This function handles events that were broadcast by the process.
1294b9c1b51eSKate Stone void Debugger::HandleBreakpointEvent(const EventSP &event_sp) {
129544d93782SGreg Clayton   using namespace lldb;
1296b9c1b51eSKate Stone   const uint32_t event_type =
1297b9c1b51eSKate Stone       Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent(
1298b9c1b51eSKate Stone           event_sp);
129944d93782SGreg Clayton 
130044d93782SGreg Clayton   //    if (event_type & eBreakpointEventTypeAdded
130144d93782SGreg Clayton   //        || event_type & eBreakpointEventTypeRemoved
130244d93782SGreg Clayton   //        || event_type & eBreakpointEventTypeEnabled
130344d93782SGreg Clayton   //        || event_type & eBreakpointEventTypeDisabled
130444d93782SGreg Clayton   //        || event_type & eBreakpointEventTypeCommandChanged
130544d93782SGreg Clayton   //        || event_type & eBreakpointEventTypeConditionChanged
130644d93782SGreg Clayton   //        || event_type & eBreakpointEventTypeIgnoreChanged
130744d93782SGreg Clayton   //        || event_type & eBreakpointEventTypeLocationsResolved)
130844d93782SGreg Clayton   //    {
1309b9c1b51eSKate Stone   //        // Don't do anything about these events, since the breakpoint
1310b9c1b51eSKate Stone   //        commands already echo these actions.
131144d93782SGreg Clayton   //    }
131244d93782SGreg Clayton   //
1313b9c1b51eSKate Stone   if (event_type & eBreakpointEventTypeLocationsAdded) {
1314b9c1b51eSKate Stone     uint32_t num_new_locations =
1315b9c1b51eSKate Stone         Breakpoint::BreakpointEventData::GetNumBreakpointLocationsFromEvent(
1316b9c1b51eSKate Stone             event_sp);
1317b9c1b51eSKate Stone     if (num_new_locations > 0) {
1318b9c1b51eSKate Stone       BreakpointSP breakpoint =
1319b9c1b51eSKate Stone           Breakpoint::BreakpointEventData::GetBreakpointFromEvent(event_sp);
13204446487dSPavel Labath       StreamSP output_sp(GetAsyncOutputStream());
1321b9c1b51eSKate Stone       if (output_sp) {
132244d93782SGreg Clayton         output_sp->Printf("%d location%s added to breakpoint %d\n",
1323b9c1b51eSKate Stone                           num_new_locations, num_new_locations == 1 ? "" : "s",
132444d93782SGreg Clayton                           breakpoint->GetID());
13254446487dSPavel Labath         output_sp->Flush();
132644d93782SGreg Clayton       }
132744d93782SGreg Clayton     }
132844d93782SGreg Clayton   }
132944d93782SGreg Clayton   //    else if (event_type & eBreakpointEventTypeLocationsRemoved)
133044d93782SGreg Clayton   //    {
1331b9c1b51eSKate Stone   //        // These locations just get disabled, not sure it is worth spamming
1332b9c1b51eSKate Stone   //        folks about this on the command line.
133344d93782SGreg Clayton   //    }
133444d93782SGreg Clayton   //    else if (event_type & eBreakpointEventTypeLocationsResolved)
133544d93782SGreg Clayton   //    {
1336b9c1b51eSKate Stone   //        // This might be an interesting thing to note, but I'm going to
1337b9c1b51eSKate Stone   //        leave it quiet for now, it just looked noisy.
133844d93782SGreg Clayton   //    }
133944d93782SGreg Clayton }
134044d93782SGreg Clayton 
1341b9c1b51eSKate Stone size_t Debugger::GetProcessSTDOUT(Process *process, Stream *stream) {
134244d93782SGreg Clayton   size_t total_bytes = 0;
1343df370550SEugene Zelenko   if (stream == nullptr)
134444d93782SGreg Clayton     stream = GetOutputFile().get();
134544d93782SGreg Clayton 
1346b9c1b51eSKate Stone   if (stream) {
1347b9c1b51eSKate Stone     //  The process has stuff waiting for stdout; get it and write it out to the
1348b9c1b51eSKate Stone     //  appropriate place.
1349b9c1b51eSKate Stone     if (process == nullptr) {
135044d93782SGreg Clayton       TargetSP target_sp = GetTargetList().GetSelectedTarget();
135144d93782SGreg Clayton       if (target_sp)
135244d93782SGreg Clayton         process = target_sp->GetProcessSP().get();
135344d93782SGreg Clayton     }
1354b9c1b51eSKate Stone     if (process) {
135544d93782SGreg Clayton       Error error;
135644d93782SGreg Clayton       size_t len;
135744d93782SGreg Clayton       char stdio_buffer[1024];
1358b9c1b51eSKate Stone       while ((len = process->GetSTDOUT(stdio_buffer, sizeof(stdio_buffer),
1359b9c1b51eSKate Stone                                        error)) > 0) {
136044d93782SGreg Clayton         stream->Write(stdio_buffer, len);
136144d93782SGreg Clayton         total_bytes += len;
136244d93782SGreg Clayton       }
136344d93782SGreg Clayton     }
136444d93782SGreg Clayton     stream->Flush();
136544d93782SGreg Clayton   }
136644d93782SGreg Clayton   return total_bytes;
136744d93782SGreg Clayton }
136844d93782SGreg Clayton 
1369b9c1b51eSKate Stone size_t Debugger::GetProcessSTDERR(Process *process, Stream *stream) {
137044d93782SGreg Clayton   size_t total_bytes = 0;
1371df370550SEugene Zelenko   if (stream == nullptr)
137244d93782SGreg Clayton     stream = GetOutputFile().get();
137344d93782SGreg Clayton 
1374b9c1b51eSKate Stone   if (stream) {
1375b9c1b51eSKate Stone     //  The process has stuff waiting for stderr; get it and write it out to the
1376b9c1b51eSKate Stone     //  appropriate place.
1377b9c1b51eSKate Stone     if (process == nullptr) {
137844d93782SGreg Clayton       TargetSP target_sp = GetTargetList().GetSelectedTarget();
137944d93782SGreg Clayton       if (target_sp)
138044d93782SGreg Clayton         process = target_sp->GetProcessSP().get();
138144d93782SGreg Clayton     }
1382b9c1b51eSKate Stone     if (process) {
138344d93782SGreg Clayton       Error error;
138444d93782SGreg Clayton       size_t len;
138544d93782SGreg Clayton       char stdio_buffer[1024];
1386b9c1b51eSKate Stone       while ((len = process->GetSTDERR(stdio_buffer, sizeof(stdio_buffer),
1387b9c1b51eSKate Stone                                        error)) > 0) {
138844d93782SGreg Clayton         stream->Write(stdio_buffer, len);
138944d93782SGreg Clayton         total_bytes += len;
139044d93782SGreg Clayton       }
139144d93782SGreg Clayton     }
139244d93782SGreg Clayton     stream->Flush();
139344d93782SGreg Clayton   }
139444d93782SGreg Clayton   return total_bytes;
139544d93782SGreg Clayton }
139644d93782SGreg Clayton 
139744d93782SGreg Clayton // This function handles events that were broadcast by the process.
1398b9c1b51eSKate Stone void Debugger::HandleProcessEvent(const EventSP &event_sp) {
139944d93782SGreg Clayton   using namespace lldb;
140044d93782SGreg Clayton   const uint32_t event_type = event_sp->GetType();
1401b9c1b51eSKate Stone   ProcessSP process_sp =
1402b9c1b51eSKate Stone       (event_type == Process::eBroadcastBitStructuredData)
140375930019STodd Fiala           ? EventDataStructuredData::GetProcessFromEvent(event_sp.get())
140475930019STodd Fiala           : Process::ProcessEventData::GetProcessFromEvent(event_sp.get());
140544d93782SGreg Clayton 
14064446487dSPavel Labath   StreamSP output_stream_sp = GetAsyncOutputStream();
14074446487dSPavel Labath   StreamSP error_stream_sp = GetAsyncErrorStream();
140844d93782SGreg Clayton   const bool gui_enabled = IsForwardingEvents();
140944d93782SGreg Clayton 
1410b9c1b51eSKate Stone   if (!gui_enabled) {
1411b4874f1aSGreg Clayton     bool pop_process_io_handler = false;
141244d93782SGreg Clayton     assert(process_sp);
141344d93782SGreg Clayton 
14144446487dSPavel Labath     bool state_is_stopped = false;
1415b9c1b51eSKate Stone     const bool got_state_changed =
1416b9c1b51eSKate Stone         (event_type & Process::eBroadcastBitStateChanged) != 0;
14174446487dSPavel Labath     const bool got_stdout = (event_type & Process::eBroadcastBitSTDOUT) != 0;
14184446487dSPavel Labath     const bool got_stderr = (event_type & Process::eBroadcastBitSTDERR) != 0;
1419b9c1b51eSKate Stone     const bool got_structured_data =
1420b9c1b51eSKate Stone         (event_type & Process::eBroadcastBitStructuredData) != 0;
142175930019STodd Fiala 
1422b9c1b51eSKate Stone     if (got_state_changed) {
1423b9c1b51eSKate Stone       StateType event_state =
1424b9c1b51eSKate Stone           Process::ProcessEventData::GetStateFromEvent(event_sp.get());
14254446487dSPavel Labath       state_is_stopped = StateIsStoppedState(event_state, false);
142644d93782SGreg Clayton     }
1427b4874f1aSGreg Clayton 
14284446487dSPavel Labath     // Display running state changes first before any STDIO
1429b9c1b51eSKate Stone     if (got_state_changed && !state_is_stopped) {
1430b9c1b51eSKate Stone       Process::HandleProcessStateChangedEvent(event_sp, output_stream_sp.get(),
1431b9c1b51eSKate Stone                                               pop_process_io_handler);
143244d93782SGreg Clayton     }
1433b4874f1aSGreg Clayton 
14344446487dSPavel Labath     // Now display and STDOUT
1435b9c1b51eSKate Stone     if (got_stdout || got_state_changed) {
14364446487dSPavel Labath       GetProcessSTDOUT(process_sp.get(), output_stream_sp.get());
143744d93782SGreg Clayton     }
1438b4874f1aSGreg Clayton 
14394446487dSPavel Labath     // Now display and STDERR
1440b9c1b51eSKate Stone     if (got_stderr || got_state_changed) {
14414446487dSPavel Labath       GetProcessSTDERR(process_sp.get(), error_stream_sp.get());
1442b4874f1aSGreg Clayton     }
1443b4874f1aSGreg Clayton 
144475930019STodd Fiala     // Give structured data events an opportunity to display.
1445b9c1b51eSKate Stone     if (got_structured_data) {
144675930019STodd Fiala       StructuredDataPluginSP plugin_sp =
144775930019STodd Fiala           EventDataStructuredData::GetPluginFromEvent(event_sp.get());
1448b9c1b51eSKate Stone       if (plugin_sp) {
144975930019STodd Fiala         auto structured_data_sp =
145075930019STodd Fiala             EventDataStructuredData::GetObjectFromEvent(event_sp.get());
1451b9c1b51eSKate Stone         if (output_stream_sp) {
145275930019STodd Fiala           StreamString content_stream;
1453b9c1b51eSKate Stone           Error error =
1454b9c1b51eSKate Stone               plugin_sp->GetDescription(structured_data_sp, content_stream);
1455b9c1b51eSKate Stone           if (error.Success()) {
1456b9c1b51eSKate Stone             if (!content_stream.GetString().empty()) {
145775930019STodd Fiala               // Add newline.
145875930019STodd Fiala               content_stream.PutChar('\n');
145975930019STodd Fiala               content_stream.Flush();
146075930019STodd Fiala 
146175930019STodd Fiala               // Print it.
1462771ef6d4SMalcolm Parsons               output_stream_sp->PutCString(content_stream.GetString());
146375930019STodd Fiala             }
1464b9c1b51eSKate Stone           } else {
146575930019STodd Fiala             error_stream_sp->Printf("Failed to print structured "
146675930019STodd Fiala                                     "data with plugin %s: %s",
1467b9c1b51eSKate Stone                                     plugin_sp->GetPluginName().AsCString(),
146875930019STodd Fiala                                     error.AsCString());
146975930019STodd Fiala           }
147075930019STodd Fiala         }
147175930019STodd Fiala       }
147275930019STodd Fiala     }
147375930019STodd Fiala 
14744446487dSPavel Labath     // Now display any stopped state changes after any STDIO
1475b9c1b51eSKate Stone     if (got_state_changed && state_is_stopped) {
1476b9c1b51eSKate Stone       Process::HandleProcessStateChangedEvent(event_sp, output_stream_sp.get(),
1477b9c1b51eSKate Stone                                               pop_process_io_handler);
147844d93782SGreg Clayton     }
147944d93782SGreg Clayton 
14804446487dSPavel Labath     output_stream_sp->Flush();
14814446487dSPavel Labath     error_stream_sp->Flush();
148244d93782SGreg Clayton 
1483b4874f1aSGreg Clayton     if (pop_process_io_handler)
1484b4874f1aSGreg Clayton       process_sp->PopProcessIOHandler();
1485b4874f1aSGreg Clayton   }
1486b4874f1aSGreg Clayton }
1487b4874f1aSGreg Clayton 
1488b9c1b51eSKate Stone void Debugger::HandleThreadEvent(const EventSP &event_sp) {
148944d93782SGreg Clayton   // At present the only thread event we handle is the Frame Changed event,
149044d93782SGreg Clayton   // and all we do for that is just reprint the thread status for that thread.
149144d93782SGreg Clayton   using namespace lldb;
149244d93782SGreg Clayton   const uint32_t event_type = event_sp->GetType();
14936a9767c7SJim Ingham   const bool stop_format = true;
149444d93782SGreg Clayton   if (event_type == Thread::eBroadcastBitStackChanged ||
1495b9c1b51eSKate Stone       event_type == Thread::eBroadcastBitThreadSelected) {
1496b9c1b51eSKate Stone     ThreadSP thread_sp(
1497b9c1b51eSKate Stone         Thread::ThreadEventData::GetThreadFromEvent(event_sp.get()));
1498b9c1b51eSKate Stone     if (thread_sp) {
14996a9767c7SJim Ingham       thread_sp->GetStatus(*GetAsyncOutputStream(), 0, 1, 1, stop_format);
150044d93782SGreg Clayton     }
150144d93782SGreg Clayton   }
150244d93782SGreg Clayton }
150344d93782SGreg Clayton 
1504b9c1b51eSKate Stone bool Debugger::IsForwardingEvents() { return (bool)m_forward_listener_sp; }
150544d93782SGreg Clayton 
1506b9c1b51eSKate Stone void Debugger::EnableForwardEvents(const ListenerSP &listener_sp) {
150744d93782SGreg Clayton   m_forward_listener_sp = listener_sp;
150844d93782SGreg Clayton }
150944d93782SGreg Clayton 
1510b9c1b51eSKate Stone void Debugger::CancelForwardEvents(const ListenerSP &listener_sp) {
151144d93782SGreg Clayton   m_forward_listener_sp.reset();
151244d93782SGreg Clayton }
151344d93782SGreg Clayton 
1514b9c1b51eSKate Stone void Debugger::DefaultEventHandler() {
1515583bbb1dSJim Ingham   ListenerSP listener_sp(GetListener());
151644d93782SGreg Clayton   ConstString broadcaster_class_target(Target::GetStaticBroadcasterClass());
151744d93782SGreg Clayton   ConstString broadcaster_class_process(Process::GetStaticBroadcasterClass());
151844d93782SGreg Clayton   ConstString broadcaster_class_thread(Thread::GetStaticBroadcasterClass());
151944d93782SGreg Clayton   BroadcastEventSpec target_event_spec(broadcaster_class_target,
152044d93782SGreg Clayton                                        Target::eBroadcastBitBreakpointChanged);
152144d93782SGreg Clayton 
1522b9c1b51eSKate Stone   BroadcastEventSpec process_event_spec(
1523b9c1b51eSKate Stone       broadcaster_class_process,
1524b9c1b51eSKate Stone       Process::eBroadcastBitStateChanged | Process::eBroadcastBitSTDOUT |
1525b9c1b51eSKate Stone           Process::eBroadcastBitSTDERR | Process::eBroadcastBitStructuredData);
152644d93782SGreg Clayton 
152744d93782SGreg Clayton   BroadcastEventSpec thread_event_spec(broadcaster_class_thread,
152844d93782SGreg Clayton                                        Thread::eBroadcastBitStackChanged |
152944d93782SGreg Clayton                                            Thread::eBroadcastBitThreadSelected);
153044d93782SGreg Clayton 
1531b9c1b51eSKate Stone   listener_sp->StartListeningForEventSpec(m_broadcaster_manager_sp,
1532b9c1b51eSKate Stone                                           target_event_spec);
1533b9c1b51eSKate Stone   listener_sp->StartListeningForEventSpec(m_broadcaster_manager_sp,
1534b9c1b51eSKate Stone                                           process_event_spec);
1535b9c1b51eSKate Stone   listener_sp->StartListeningForEventSpec(m_broadcaster_manager_sp,
1536b9c1b51eSKate Stone                                           thread_event_spec);
1537b9c1b51eSKate Stone   listener_sp->StartListeningForEvents(
1538b9c1b51eSKate Stone       m_command_interpreter_ap.get(),
153944d93782SGreg Clayton       CommandInterpreter::eBroadcastBitQuitCommandReceived |
154044d93782SGreg Clayton           CommandInterpreter::eBroadcastBitAsynchronousOutputData |
154144d93782SGreg Clayton           CommandInterpreter::eBroadcastBitAsynchronousErrorData);
154244d93782SGreg Clayton 
1543afa91e33SGreg Clayton   // Let the thread that spawned us know that we have started up and
1544afa91e33SGreg Clayton   // that we are now listening to all required events so no events get missed
1545afa91e33SGreg Clayton   m_sync_broadcaster.BroadcastEvent(eBroadcastBitEventThreadIsListening);
1546afa91e33SGreg Clayton 
154744d93782SGreg Clayton   bool done = false;
1548b9c1b51eSKate Stone   while (!done) {
154944d93782SGreg Clayton     EventSP event_sp;
1550d35031e1SPavel Labath     if (listener_sp->GetEvent(event_sp, llvm::None)) {
1551b9c1b51eSKate Stone       if (event_sp) {
155244d93782SGreg Clayton         Broadcaster *broadcaster = event_sp->GetBroadcaster();
1553b9c1b51eSKate Stone         if (broadcaster) {
155444d93782SGreg Clayton           uint32_t event_type = event_sp->GetType();
155544d93782SGreg Clayton           ConstString broadcaster_class(broadcaster->GetBroadcasterClass());
1556b9c1b51eSKate Stone           if (broadcaster_class == broadcaster_class_process) {
155744d93782SGreg Clayton             HandleProcessEvent(event_sp);
1558b9c1b51eSKate Stone           } else if (broadcaster_class == broadcaster_class_target) {
1559b9c1b51eSKate Stone             if (Breakpoint::BreakpointEventData::GetEventDataFromEvent(
1560b9c1b51eSKate Stone                     event_sp.get())) {
156144d93782SGreg Clayton               HandleBreakpointEvent(event_sp);
156244d93782SGreg Clayton             }
1563b9c1b51eSKate Stone           } else if (broadcaster_class == broadcaster_class_thread) {
156444d93782SGreg Clayton             HandleThreadEvent(event_sp);
1565b9c1b51eSKate Stone           } else if (broadcaster == m_command_interpreter_ap.get()) {
1566b9c1b51eSKate Stone             if (event_type &
1567b9c1b51eSKate Stone                 CommandInterpreter::eBroadcastBitQuitCommandReceived) {
156844d93782SGreg Clayton               done = true;
1569b9c1b51eSKate Stone             } else if (event_type &
1570b9c1b51eSKate Stone                        CommandInterpreter::eBroadcastBitAsynchronousErrorData) {
1571b9c1b51eSKate Stone               const char *data = reinterpret_cast<const char *>(
1572b9c1b51eSKate Stone                   EventDataBytes::GetBytesFromEvent(event_sp.get()));
1573b9c1b51eSKate Stone               if (data && data[0]) {
15744446487dSPavel Labath                 StreamSP error_sp(GetAsyncErrorStream());
1575b9c1b51eSKate Stone                 if (error_sp) {
157644d93782SGreg Clayton                   error_sp->PutCString(data);
157744d93782SGreg Clayton                   error_sp->Flush();
157844d93782SGreg Clayton                 }
157944d93782SGreg Clayton               }
1580b9c1b51eSKate Stone             } else if (event_type & CommandInterpreter::
1581b9c1b51eSKate Stone                                         eBroadcastBitAsynchronousOutputData) {
1582b9c1b51eSKate Stone               const char *data = reinterpret_cast<const char *>(
1583b9c1b51eSKate Stone                   EventDataBytes::GetBytesFromEvent(event_sp.get()));
1584b9c1b51eSKate Stone               if (data && data[0]) {
15854446487dSPavel Labath                 StreamSP output_sp(GetAsyncOutputStream());
1586b9c1b51eSKate Stone                 if (output_sp) {
158744d93782SGreg Clayton                   output_sp->PutCString(data);
158844d93782SGreg Clayton                   output_sp->Flush();
158944d93782SGreg Clayton                 }
159044d93782SGreg Clayton               }
159144d93782SGreg Clayton             }
159244d93782SGreg Clayton           }
159344d93782SGreg Clayton         }
159444d93782SGreg Clayton 
159544d93782SGreg Clayton         if (m_forward_listener_sp)
159644d93782SGreg Clayton           m_forward_listener_sp->AddEvent(event_sp);
159744d93782SGreg Clayton       }
159844d93782SGreg Clayton     }
159944d93782SGreg Clayton   }
160044d93782SGreg Clayton }
160144d93782SGreg Clayton 
1602b9c1b51eSKate Stone lldb::thread_result_t Debugger::EventHandlerThread(lldb::thread_arg_t arg) {
160344d93782SGreg Clayton   ((Debugger *)arg)->DefaultEventHandler();
160444d93782SGreg Clayton   return NULL;
160544d93782SGreg Clayton }
160644d93782SGreg Clayton 
1607b9c1b51eSKate Stone bool Debugger::StartEventHandlerThread() {
1608b9c1b51eSKate Stone   if (!m_event_handler_thread.IsJoinable()) {
1609afa91e33SGreg Clayton     // We must synchronize with the DefaultEventHandler() thread to ensure
1610afa91e33SGreg Clayton     // it is up and running and listening to events before we return from
1611afa91e33SGreg Clayton     // this function. We do this by listening to events for the
1612afa91e33SGreg Clayton     // eBroadcastBitEventThreadIsListening from the m_sync_broadcaster
1613b9c1b51eSKate Stone     ListenerSP listener_sp(
1614b9c1b51eSKate Stone         Listener::MakeListener("lldb.debugger.event-handler"));
1615b9c1b51eSKate Stone     listener_sp->StartListeningForEvents(&m_sync_broadcaster,
1616b9c1b51eSKate Stone                                          eBroadcastBitEventThreadIsListening);
1617afa91e33SGreg Clayton 
16187c2896a2SZachary Turner     // Use larger 8MB stack for this thread
1619b9c1b51eSKate Stone     m_event_handler_thread = ThreadLauncher::LaunchThread(
1620b9c1b51eSKate Stone         "lldb.debugger.event-handler", EventHandlerThread, this, nullptr,
16217c2896a2SZachary Turner         g_debugger_event_thread_stack_bytes);
1622afa91e33SGreg Clayton 
1623b9c1b51eSKate Stone     // Make sure DefaultEventHandler() is running and listening to events before
1624b9c1b51eSKate Stone     // we return
1625afa91e33SGreg Clayton     // from this function. We are only listening for events of type
1626b9c1b51eSKate Stone     // eBroadcastBitEventThreadIsListening so we don't need to check the event,
1627b9c1b51eSKate Stone     // we just need
1628b9c1b51eSKate Stone     // to wait an infinite amount of time for it (nullptr timeout as the first
1629b9c1b51eSKate Stone     // parameter)
1630afa91e33SGreg Clayton     lldb::EventSP event_sp;
1631d35031e1SPavel Labath     listener_sp->GetEvent(event_sp, llvm::None);
1632807b6b32SGreg Clayton   }
1633acee96aeSZachary Turner   return m_event_handler_thread.IsJoinable();
163444d93782SGreg Clayton }
163544d93782SGreg Clayton 
1636b9c1b51eSKate Stone void Debugger::StopEventHandlerThread() {
1637b9c1b51eSKate Stone   if (m_event_handler_thread.IsJoinable()) {
1638b9c1b51eSKate Stone     GetCommandInterpreter().BroadcastEvent(
1639b9c1b51eSKate Stone         CommandInterpreter::eBroadcastBitQuitCommandReceived);
164039de3110SZachary Turner     m_event_handler_thread.Join(nullptr);
164144d93782SGreg Clayton   }
164244d93782SGreg Clayton }
164344d93782SGreg Clayton 
1644b9c1b51eSKate Stone lldb::thread_result_t Debugger::IOHandlerThread(lldb::thread_arg_t arg) {
164544d93782SGreg Clayton   Debugger *debugger = (Debugger *)arg;
16469aaab558SSiva Chandra   debugger->ExecuteIOHandlers();
164744d93782SGreg Clayton   debugger->StopEventHandlerThread();
164844d93782SGreg Clayton   return NULL;
164944d93782SGreg Clayton }
165044d93782SGreg Clayton 
1651b9c1b51eSKate Stone bool Debugger::HasIOHandlerThread() { return m_io_handler_thread.IsJoinable(); }
16526681041dSSean Callanan 
1653b9c1b51eSKate Stone bool Debugger::StartIOHandlerThread() {
1654acee96aeSZachary Turner   if (!m_io_handler_thread.IsJoinable())
1655b9c1b51eSKate Stone     m_io_handler_thread = ThreadLauncher::LaunchThread(
1656b9c1b51eSKate Stone         "lldb.debugger.io-handler", IOHandlerThread, this, nullptr,
1657807b6b32SGreg Clayton         8 * 1024 * 1024); // Use larger 8MB stack for this thread
1658acee96aeSZachary Turner   return m_io_handler_thread.IsJoinable();
165944d93782SGreg Clayton }
166044d93782SGreg Clayton 
1661b9c1b51eSKate Stone void Debugger::StopIOHandlerThread() {
1662b9c1b51eSKate Stone   if (m_io_handler_thread.IsJoinable()) {
166344d93782SGreg Clayton     if (m_input_file_sp)
166444d93782SGreg Clayton       m_input_file_sp->GetFile().Close();
166539de3110SZachary Turner     m_io_handler_thread.Join(nullptr);
166644d93782SGreg Clayton   }
166744d93782SGreg Clayton }
166844d93782SGreg Clayton 
1669b9c1b51eSKate Stone void Debugger::JoinIOHandlerThread() {
1670b9c1b51eSKate Stone   if (HasIOHandlerThread()) {
16716681041dSSean Callanan     thread_result_t result;
16726681041dSSean Callanan     m_io_handler_thread.Join(&result);
16736681041dSSean Callanan     m_io_handler_thread = LLDB_INVALID_HOST_THREAD;
16746681041dSSean Callanan   }
16756681041dSSean Callanan }
16766681041dSSean Callanan 
1677b9c1b51eSKate Stone Target *Debugger::GetDummyTarget() {
1678893c932aSJim Ingham   return m_target_list.GetDummyTarget(*this).get();
1679893c932aSJim Ingham }
1680893c932aSJim Ingham 
1681b9c1b51eSKate Stone Target *Debugger::GetSelectedOrDummyTarget(bool prefer_dummy) {
168233df7cd3SJim Ingham   Target *target = nullptr;
1683b9c1b51eSKate Stone   if (!prefer_dummy) {
168433df7cd3SJim Ingham     target = m_target_list.GetSelectedTarget().get();
168533df7cd3SJim Ingham     if (target)
168633df7cd3SJim Ingham       return target;
168733df7cd3SJim Ingham   }
1688893c932aSJim Ingham 
1689893c932aSJim Ingham   return GetDummyTarget();
1690893c932aSJim Ingham }
169144d93782SGreg Clayton 
1692b9c1b51eSKate Stone Error Debugger::RunREPL(LanguageType language, const char *repl_options) {
16933e7e915dSSean Callanan   Error err;
16943e7e915dSSean Callanan   FileSpec repl_executable;
16953e7e915dSSean Callanan 
1696b9c1b51eSKate Stone   if (language == eLanguageTypeUnknown) {
169797f84e87SSean Callanan     std::set<LanguageType> repl_languages;
169897f84e87SSean Callanan 
169997f84e87SSean Callanan     Language::GetLanguagesSupportingREPLs(repl_languages);
170097f84e87SSean Callanan 
1701b9c1b51eSKate Stone     if (repl_languages.size() == 1) {
170297f84e87SSean Callanan       language = *repl_languages.begin();
1703b9c1b51eSKate Stone     } else if (repl_languages.empty()) {
1704b9c1b51eSKate Stone       err.SetErrorStringWithFormat(
1705b9c1b51eSKate Stone           "LLDB isn't configured with REPL support for any languages.");
170697f84e87SSean Callanan       return err;
1707b9c1b51eSKate Stone     } else {
1708b9c1b51eSKate Stone       err.SetErrorStringWithFormat(
1709b9c1b51eSKate Stone           "Multiple possible REPL languages.  Please specify a language.");
171097f84e87SSean Callanan       return err;
171197f84e87SSean Callanan     }
171297f84e87SSean Callanan   }
171397f84e87SSean Callanan 
1714b9c1b51eSKate Stone   Target *const target =
1715b9c1b51eSKate Stone       nullptr; // passing in an empty target means the REPL must create one
17163e7e915dSSean Callanan 
17173b682de6SSean Callanan   REPLSP repl_sp(REPL::Create(err, language, this, target, repl_options));
17183e7e915dSSean Callanan 
1719b9c1b51eSKate Stone   if (!err.Success()) {
17203e7e915dSSean Callanan     return err;
17213e7e915dSSean Callanan   }
17223e7e915dSSean Callanan 
1723b9c1b51eSKate Stone   if (!repl_sp) {
1724b9c1b51eSKate Stone     err.SetErrorStringWithFormat("couldn't find a REPL for %s",
1725b9c1b51eSKate Stone                                  Language::GetNameForLanguageType(language));
17263e7e915dSSean Callanan     return err;
17273e7e915dSSean Callanan   }
17283e7e915dSSean Callanan 
17293e7e915dSSean Callanan   repl_sp->SetCompilerOptions(repl_options);
17303e7e915dSSean Callanan   repl_sp->RunLoop();
17313e7e915dSSean Callanan 
17323e7e915dSSean Callanan   return err;
17333e7e915dSSean Callanan }
1734