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 
122f3df613SZachary Turner #include "lldb/Breakpoint/Breakpoint.h" // for Breakpoint, Brea...
132f3df613SZachary Turner #include "lldb/Core/Event.h"            // for Event, EventData...
14554f68d3SGreg Clayton #include "lldb/Core/FormatEntity.h"
152f3df613SZachary Turner #include "lldb/Core/Listener.h"   // for Listener
162f3df613SZachary Turner #include "lldb/Core/Mangled.h"    // for Mangled
17235354beSAdrian Prantl #include "lldb/Core/ModuleList.h" // for Mangled
18e8cd0c98SGreg Clayton #include "lldb/Core/PluginManager.h"
195b52f0c7SJim Ingham #include "lldb/Core/StreamAsynchronousIO.h"
2044d93782SGreg Clayton #include "lldb/Core/StreamFile.h"
215548cb50SEnrico Granata #include "lldb/DataFormatters/DataVisualization.h"
223e7e915dSSean Callanan #include "lldb/Expression/REPL.h"
232f3df613SZachary Turner #include "lldb/Host/File.h" // for File, File::kInv...
2442ff0ad8SZachary Turner #include "lldb/Host/HostInfo.h"
25a3406614SGreg Clayton #include "lldb/Host/Terminal.h"
2639de3110SZachary Turner #include "lldb/Host/ThreadLauncher.h"
276611103cSGreg Clayton #include "lldb/Interpreter/CommandInterpreter.h"
282f3df613SZachary Turner #include "lldb/Interpreter/OptionValue.h" // for OptionValue, Opt...
29633a29cfSZachary Turner #include "lldb/Interpreter/OptionValueProperties.h"
3067cc0636SGreg Clayton #include "lldb/Interpreter/OptionValueSInt64.h"
3167cc0636SGreg Clayton #include "lldb/Interpreter/OptionValueString.h"
322f3df613SZachary Turner #include "lldb/Interpreter/Property.h"          // for PropertyDefinition
332f3df613SZachary Turner #include "lldb/Interpreter/ScriptInterpreter.h" // for ScriptInterpreter
341f746071SGreg Clayton #include "lldb/Symbol/Function.h"
351f746071SGreg Clayton #include "lldb/Symbol/Symbol.h"
362f3df613SZachary Turner #include "lldb/Symbol/SymbolContext.h" // for SymbolContext
373e7e915dSSean Callanan #include "lldb/Target/Language.h"
3830fdc8d8SChris Lattner #include "lldb/Target/Process.h"
3975930019STodd Fiala #include "lldb/Target/StructuredDataPlugin.h"
4084a53dfbSEnrico Granata #include "lldb/Target/Target.h"
41b9c1b51eSKate Stone #include "lldb/Target/TargetList.h"
4230fdc8d8SChris Lattner #include "lldb/Target/Thread.h"
432f3df613SZachary Turner #include "lldb/Target/ThreadList.h" // for ThreadList
445a31471eSGreg Clayton #include "lldb/Utility/AnsiTerminal.h"
452f3df613SZachary Turner #include "lldb/Utility/Log.h" // for LLDB_LOG_OPTION_...
46d821c997SPavel Labath #include "lldb/Utility/State.h"
472f3df613SZachary Turner #include "lldb/Utility/Stream.h" // for Stream
48fb1a0a0dSZachary Turner #include "lldb/Utility/StreamCallback.h"
49bf9a7730SZachary Turner #include "lldb/Utility/StreamString.h"
502f3df613SZachary Turner 
51b1cb0b79SNico Weber #if defined(_WIN32)
522f3df613SZachary Turner #include "lldb/Host/windows/PosixApi.h" // for PATH_MAX
538aa23614SDavid Bolvansky #include "lldb/Host/windows/windows.h"
542f3df613SZachary Turner #endif
552f3df613SZachary Turner 
562f3df613SZachary Turner #include "llvm/ADT/None.h"      // for None
572f3df613SZachary Turner #include "llvm/ADT/STLExtras.h" // for make_unique
582f3df613SZachary Turner #include "llvm/ADT/StringRef.h"
592f3df613SZachary Turner #include "llvm/ADT/iterator.h" // for iterator_facade_...
602f3df613SZachary Turner #include "llvm/Support/DynamicLibrary.h"
612f3df613SZachary Turner #include "llvm/Support/FileSystem.h"
628aa23614SDavid Bolvansky #include "llvm/Support/Process.h"
632f3df613SZachary Turner #include "llvm/Support/Threading.h"
642f3df613SZachary Turner #include "llvm/Support/raw_ostream.h" // for raw_fd_ostream
652f3df613SZachary Turner 
662f3df613SZachary Turner #include <list>   // for list
672f3df613SZachary Turner #include <memory> // for make_shared
682f3df613SZachary Turner #include <mutex>
692f3df613SZachary Turner #include <set>          // for set
702f3df613SZachary Turner #include <stdio.h>      // for size_t, NULL
712f3df613SZachary Turner #include <stdlib.h>     // for getenv
722f3df613SZachary Turner #include <string.h>     // for strcmp
732f3df613SZachary Turner #include <string>       // for string
742f3df613SZachary Turner #include <system_error> // for error_code
752f3df613SZachary Turner 
762f3df613SZachary Turner namespace lldb_private {
772f3df613SZachary Turner class Address;
782f3df613SZachary Turner }
7930fdc8d8SChris Lattner 
8030fdc8d8SChris Lattner using namespace lldb;
8130fdc8d8SChris Lattner using namespace lldb_private;
8230fdc8d8SChris Lattner 
83ebc1bb27SCaroline Tice static lldb::user_id_t g_unique_id = 1;
847c2896a2SZachary Turner static size_t g_debugger_event_thread_stack_bytes = 8 * 1024 * 1024;
85ebc1bb27SCaroline Tice 
861b654882SGreg Clayton #pragma mark Static Functions
871b654882SGreg Clayton 
881b654882SGreg Clayton typedef std::vector<DebuggerSP> DebuggerList;
89b9c1b51eSKate Stone static std::recursive_mutex *g_debugger_list_mutex_ptr =
90b9c1b51eSKate Stone     nullptr; // NOTE: intentional leak to avoid issues with C++ destructor chain
91b9c1b51eSKate Stone static DebuggerList *g_debugger_list_ptr =
92b9c1b51eSKate Stone     nullptr; // NOTE: intentional leak to avoid issues with C++ destructor chain
93e372b98dSGreg Clayton 
948fe53c49STatyana Krasnukha static constexpr OptionEnumValueElement g_show_disassembly_enum_values[] = {
95b9c1b51eSKate Stone     {Debugger::eStopDisassemblyTypeNever, "never",
96b9c1b51eSKate Stone      "Never show disassembly when displaying a stop context."},
97b9c1b51eSKate Stone     {Debugger::eStopDisassemblyTypeNoDebugInfo, "no-debuginfo",
98b9c1b51eSKate Stone      "Show disassembly when there is no debug information."},
99b9c1b51eSKate Stone     {Debugger::eStopDisassemblyTypeNoSource, "no-source",
100b9c1b51eSKate Stone      "Show disassembly when there is no source information, or the source file "
101b9c1b51eSKate Stone      "is missing when displaying a stop context."},
102b9c1b51eSKate Stone     {Debugger::eStopDisassemblyTypeAlways, "always",
1038fe53c49STatyana Krasnukha      "Always show disassembly when displaying a stop context."} };
104e372b98dSGreg Clayton 
1058fe53c49STatyana Krasnukha static constexpr OptionEnumValueElement g_language_enumerators[] = {
10667cc0636SGreg Clayton     {eScriptLanguageNone, "none", "Disable scripting languages."},
107b9c1b51eSKate Stone     {eScriptLanguagePython, "python",
108b9c1b51eSKate Stone      "Select python as the default scripting language."},
109b9c1b51eSKate Stone     {eScriptLanguageDefault, "default",
1108fe53c49STatyana Krasnukha      "Select the lldb default as the default scripting language."} };
111e372b98dSGreg Clayton 
112b9c1b51eSKate Stone #define MODULE_WITH_FUNC                                                       \
113b9c1b51eSKate Stone   "{ "                                                                         \
1146a9767c7SJim Ingham   "${module.file.basename}{`${function.name-with-args}"                        \
1156a9767c7SJim Ingham   "{${frame.no-debug}${function.pc-offset}}}}"
1167f1c1211SPavel Labath 
1177f1c1211SPavel Labath #define MODULE_WITH_FUNC_NO_ARGS                                               \
1187f1c1211SPavel Labath   "{ "                                                                         \
1197f1c1211SPavel Labath   "${module.file.basename}{`${function.name-without-args}"                     \
1207f1c1211SPavel Labath   "{${frame.no-debug}${function.pc-offset}}}}"
1217f1c1211SPavel Labath 
1224954f6a5SAdrian Prantl #define FILE_AND_LINE                                                          \
1234954f6a5SAdrian Prantl   "{ at ${line.file.basename}:${line.number}{:${line.column}}}"
1246ab659a9SJason Molenda #define IS_OPTIMIZED "{${function.is-optimized} [opt]}"
12567cc0636SGreg Clayton 
126b9c1b51eSKate Stone #define DEFAULT_THREAD_FORMAT                                                  \
127b9c1b51eSKate Stone   "thread #${thread.index}: tid = ${thread.id%tid}"                            \
128b9c1b51eSKate Stone   "{, ${frame.pc}}" MODULE_WITH_FUNC FILE_AND_LINE                             \
1290769b2b1SMichael Sartain   "{, name = '${thread.name}'}"                                                \
1300769b2b1SMichael Sartain   "{, queue = '${thread.queue}'}"                                              \
131705b1809SJason Molenda   "{, activity = '${thread.info.activity.name}'}"                              \
132705b1809SJason Molenda   "{, ${thread.info.trace_messages} messages}"                                 \
13367cc0636SGreg Clayton   "{, stop reason = ${thread.stop-reason}}"                                    \
13467cc0636SGreg Clayton   "{\\nReturn value: ${thread.return-value}}"                                  \
13530fadafeSJim Ingham   "{\\nCompleted expression: ${thread.completed-expression}}"                  \
13667cc0636SGreg Clayton   "\\n"
13767cc0636SGreg Clayton 
1386a9767c7SJim Ingham #define DEFAULT_THREAD_STOP_FORMAT                                             \
1396a9767c7SJim Ingham   "thread #${thread.index}{, name = '${thread.name}'}"                         \
1406a9767c7SJim Ingham   "{, queue = '${thread.queue}'}"                                              \
1416a9767c7SJim Ingham   "{, activity = '${thread.info.activity.name}'}"                              \
1426a9767c7SJim Ingham   "{, ${thread.info.trace_messages} messages}"                                 \
1436a9767c7SJim Ingham   "{, stop reason = ${thread.stop-reason}}"                                    \
1446a9767c7SJim Ingham   "{\\nReturn value: ${thread.return-value}}"                                  \
1456a9767c7SJim Ingham   "{\\nCompleted expression: ${thread.completed-expression}}"                  \
1466a9767c7SJim Ingham   "\\n"
1476a9767c7SJim Ingham 
148b9c1b51eSKate Stone #define DEFAULT_FRAME_FORMAT                                                   \
149270e8228SJason Molenda   "frame #${frame.index}: ${frame.pc}" MODULE_WITH_FUNC FILE_AND_LINE          \
150b9c1b51eSKate Stone       IS_OPTIMIZED "\\n"
15167cc0636SGreg Clayton 
1527f1c1211SPavel Labath #define DEFAULT_FRAME_FORMAT_NO_ARGS                                           \
1537f1c1211SPavel Labath   "frame #${frame.index}: ${frame.pc}" MODULE_WITH_FUNC_NO_ARGS FILE_AND_LINE  \
1547f1c1211SPavel Labath       IS_OPTIMIZED "\\n"
1557f1c1211SPavel Labath 
156c980fa92SJason Molenda // Three parts to this disassembly format specification:
157c980fa92SJason Molenda //   1. If this is a new function/symbol (no previous symbol/function), print
158c980fa92SJason Molenda //      dylib`funcname:\n
159b9c1b51eSKate Stone //   2. If this is a symbol context change (different from previous
160b9c1b51eSKate Stone //   symbol/function), print
161c980fa92SJason Molenda //      dylib`funcname:\n
162c980fa92SJason Molenda //   3. print
163c980fa92SJason Molenda //      address <+offset>:
164b9c1b51eSKate Stone #define DEFAULT_DISASSEMBLY_FORMAT                                             \
165b9c1b51eSKate Stone   "{${function.initial-function}{${module.file.basename}`}{${function.name-"   \
166b9c1b51eSKate Stone   "without-args}}:\n}{${function.changed}\n{${module.file.basename}`}{${"      \
167b9c1b51eSKate Stone   "function.name-without-args}}:\n}{${current-pc-arrow} "                      \
168b9c1b51eSKate Stone   "}${addr-file-or-load}{ "                                                    \
169b9c1b51eSKate Stone   "<${function.concrete-only-addr-offset-no-padding}>}: "
170c980fa92SJason Molenda 
17105097246SAdrian Prantl // gdb's disassembly format can be emulated with ${current-pc-arrow}${addr-
17205097246SAdrian Prantl // file-or-load}{ <${function.name-without-args}${function.concrete-only-addr-
17305097246SAdrian Prantl // offset-no-padding}>}:
174c980fa92SJason Molenda 
175c980fa92SJason Molenda // lldb's original format for disassembly would look like this format string -
17605097246SAdrian Prantl // {${function.initial-function}{${module.file.basename}`}{${function.name-
17705097246SAdrian Prantl // without-
17805097246SAdrian Prantl // args}}:\n}{${function.changed}\n{${module.file.basename}`}{${function.name-
17905097246SAdrian Prantl // without-args}}:\n}{${current-pc-arrow} }{${addr-file-or-load}}:
180c980fa92SJason Molenda 
1818fe53c49STatyana Krasnukha static constexpr OptionEnumValueElement s_stop_show_column_values[] = {
1829666ba75STodd Fiala     {eStopShowColumnAnsiOrCaret, "ansi-or-caret",
1839666ba75STodd Fiala      "Highlight the stop column with ANSI terminal codes when color/ANSI mode "
1849666ba75STodd Fiala      "is enabled; otherwise, fall back to using a text-only caret (^) as if "
1859666ba75STodd Fiala      "\"caret-only\" mode was selected."},
1869666ba75STodd Fiala     {eStopShowColumnAnsi, "ansi", "Highlight the stop column with ANSI "
1879666ba75STodd Fiala                                   "terminal codes when running LLDB with "
1889666ba75STodd Fiala                                   "color/ANSI enabled."},
1899666ba75STodd Fiala     {eStopShowColumnCaret, "caret",
1909666ba75STodd Fiala      "Highlight the stop column with a caret character (^) underneath the stop "
1919666ba75STodd Fiala      "column. This method introduces a new line in source listings that "
1929666ba75STodd Fiala      "display thread stop locations."},
1938fe53c49STatyana Krasnukha     {eStopShowColumnNone, "none", "Do not highlight the stop column."}};
1949666ba75STodd Fiala 
1958fe53c49STatyana Krasnukha static constexpr PropertyDefinition g_properties[] = {
1968fe53c49STatyana Krasnukha     {"auto-confirm", OptionValue::eTypeBoolean, true, false, nullptr, {},
197b9c1b51eSKate Stone      "If true all confirmation prompts will receive their default reply."},
198b9c1b51eSKate Stone     {"disassembly-format", OptionValue::eTypeFormatEntity, true, 0,
1998fe53c49STatyana Krasnukha      DEFAULT_DISASSEMBLY_FORMAT, {},
2007f1c1211SPavel Labath      "The default disassembly format "
201b9c1b51eSKate Stone      "string to use when disassembling "
202b9c1b51eSKate Stone      "instruction sequences."},
203b9c1b51eSKate Stone     {"frame-format", OptionValue::eTypeFormatEntity, true, 0,
2048fe53c49STatyana Krasnukha      DEFAULT_FRAME_FORMAT, {},
2057f1c1211SPavel Labath      "The default frame format string to use "
206b9c1b51eSKate Stone      "when displaying stack frame information "
207b9c1b51eSKate Stone      "for threads."},
2088fe53c49STatyana Krasnukha     {"notify-void", OptionValue::eTypeBoolean, true, false, nullptr, {},
209b9c1b51eSKate Stone      "Notify the user explicitly if an expression returns void (default: "
210b9c1b51eSKate Stone      "false)."},
211b9c1b51eSKate Stone     {"prompt", OptionValue::eTypeString, true,
2128fe53c49STatyana Krasnukha      OptionValueString::eOptionEncodeCharacterEscapeSequences, "(lldb) ", {},
2138fe53c49STatyana Krasnukha      "The debugger command line prompt displayed for the user."},
214b9c1b51eSKate Stone     {"script-lang", OptionValue::eTypeEnum, true, eScriptLanguagePython,
2158fe53c49STatyana Krasnukha      nullptr, OptionEnumValues(g_language_enumerators),
216b9c1b51eSKate Stone      "The script language to be used for evaluating user-written scripts."},
2178fe53c49STatyana Krasnukha     {"stop-disassembly-count", OptionValue::eTypeSInt64, true, 4, nullptr, {},
2187f1c1211SPavel Labath      "The number of disassembly lines to show when displaying a "
219b9c1b51eSKate Stone      "stopped context."},
220b9c1b51eSKate Stone     {"stop-disassembly-display", OptionValue::eTypeEnum, true,
221b9c1b51eSKate Stone      Debugger::eStopDisassemblyTypeNoDebugInfo, nullptr,
2228fe53c49STatyana Krasnukha      OptionEnumValues(g_show_disassembly_enum_values),
223b9c1b51eSKate Stone      "Control when to display disassembly when displaying a stopped context."},
2248fe53c49STatyana Krasnukha     {"stop-line-count-after", OptionValue::eTypeSInt64, true, 3, nullptr, {},
2257f1c1211SPavel Labath      "The number of sources lines to display that come after the "
226b9c1b51eSKate Stone      "current source line when displaying a stopped context."},
2278fe53c49STatyana Krasnukha     {"stop-line-count-before", OptionValue::eTypeSInt64, true, 3, nullptr, {},
2287f1c1211SPavel Labath      "The number of sources lines to display that come before the "
229b9c1b51eSKate Stone      "current source line when displaying a stopped context."},
2308fe53c49STatyana Krasnukha     {"highlight-source", OptionValue::eTypeBoolean, true, true, nullptr, {},
2318fe53c49STatyana Krasnukha      "If true, LLDB will highlight the displayed source code."},
2329666ba75STodd Fiala     {"stop-show-column", OptionValue::eTypeEnum, false,
2338fe53c49STatyana Krasnukha      eStopShowColumnAnsiOrCaret, nullptr, OptionEnumValues(s_stop_show_column_values),
2349666ba75STodd Fiala      "If true, LLDB will use the column information from the debug info to "
2359666ba75STodd Fiala      "mark the current position when displaying a stopped context."},
23620786326SRaphael Isemann     {"stop-show-column-ansi-prefix", OptionValue::eTypeString, true, 0,
2378fe53c49STatyana Krasnukha      "${ansi.underline}", {},
2389666ba75STodd Fiala      "When displaying the column marker in a color-enabled (i.e. ANSI) "
2399666ba75STodd Fiala      "terminal, use the ANSI terminal code specified in this format at the "
2409666ba75STodd Fiala      "immediately before the column to be marked."},
24120786326SRaphael Isemann     {"stop-show-column-ansi-suffix", OptionValue::eTypeString, true, 0,
2428fe53c49STatyana Krasnukha      "${ansi.normal}", {},
2439666ba75STodd Fiala      "When displaying the column marker in a color-enabled (i.e. ANSI) "
2449666ba75STodd Fiala      "terminal, use the ANSI terminal code specified in this format "
2459666ba75STodd Fiala      "immediately after the column to be marked."},
2468fe53c49STatyana Krasnukha     {"term-width", OptionValue::eTypeSInt64, true, 80, nullptr, {},
247b9c1b51eSKate Stone      "The maximum number of columns to use for displaying text."},
248b9c1b51eSKate Stone     {"thread-format", OptionValue::eTypeFormatEntity, true, 0,
2498fe53c49STatyana Krasnukha      DEFAULT_THREAD_FORMAT, {},
2507f1c1211SPavel Labath      "The default thread format string to use "
251b9c1b51eSKate Stone      "when displaying thread information."},
2526a9767c7SJim Ingham     {"thread-stop-format", OptionValue::eTypeFormatEntity, true, 0,
2538fe53c49STatyana Krasnukha      DEFAULT_THREAD_STOP_FORMAT, {},
2547f1c1211SPavel Labath      "The default thread format  "
2556a9767c7SJim Ingham      "string to use when displaying thread "
2566a9767c7SJim Ingham      "information as part of the stop display."},
2578fe53c49STatyana Krasnukha     {"use-external-editor", OptionValue::eTypeBoolean, true, false, nullptr, {},
2588fe53c49STatyana Krasnukha      "Whether to use an external editor or not."},
2598fe53c49STatyana Krasnukha     {"use-color", OptionValue::eTypeBoolean, true, true, nullptr, {},
260b9c1b51eSKate Stone      "Whether to use Ansi color codes or not."},
261b9c1b51eSKate Stone     {"auto-one-line-summaries", OptionValue::eTypeBoolean, true, true, nullptr,
2628fe53c49STatyana Krasnukha      {},
2637f1c1211SPavel Labath      "If true, LLDB will automatically display small structs in "
264b9c1b51eSKate Stone      "one-liner format (default: true)."},
2658fe53c49STatyana Krasnukha     {"auto-indent", OptionValue::eTypeBoolean, true, true, nullptr, {},
266b9c1b51eSKate Stone      "If true, LLDB will auto indent/outdent code. Currently only supported in "
267b9c1b51eSKate Stone      "the REPL (default: true)."},
2688fe53c49STatyana Krasnukha     {"print-decls", OptionValue::eTypeBoolean, true, true, nullptr, {},
269b9c1b51eSKate Stone      "If true, LLDB will print the values of variables declared in an "
270b9c1b51eSKate Stone      "expression. Currently only supported in the REPL (default: true)."},
2718fe53c49STatyana Krasnukha     {"tab-size", OptionValue::eTypeUInt64, true, 4, nullptr, {},
272b9c1b51eSKate Stone      "The tab size to use when indenting code in multi-line input mode "
273b9c1b51eSKate Stone      "(default: 4)."},
274b9c1b51eSKate Stone     {"escape-non-printables", OptionValue::eTypeBoolean, true, true, nullptr,
2758fe53c49STatyana Krasnukha      {},
2767f1c1211SPavel Labath      "If true, LLDB will automatically escape non-printable and "
277b9c1b51eSKate Stone      "escape characters when formatting strings."},
2787f1c1211SPavel Labath     {"frame-format-unique", OptionValue::eTypeFormatEntity, true, 0,
2798fe53c49STatyana Krasnukha      DEFAULT_FRAME_FORMAT_NO_ARGS, {},
2807f1c1211SPavel Labath      "The default frame format string to use when displaying stack frame"
281*e40db05bSTatyana Krasnukha      "information for threads from thread backtrace unique."}};
28267cc0636SGreg Clayton 
283b9c1b51eSKate Stone enum {
28467cc0636SGreg Clayton   ePropertyAutoConfirm = 0,
285aff1b357SJason Molenda   ePropertyDisassemblyFormat,
28667cc0636SGreg Clayton   ePropertyFrameFormat,
28767cc0636SGreg Clayton   ePropertyNotiftVoid,
28867cc0636SGreg Clayton   ePropertyPrompt,
28967cc0636SGreg Clayton   ePropertyScriptLanguage,
29067cc0636SGreg Clayton   ePropertyStopDisassemblyCount,
29167cc0636SGreg Clayton   ePropertyStopDisassemblyDisplay,
29267cc0636SGreg Clayton   ePropertyStopLineCountAfter,
29367cc0636SGreg Clayton   ePropertyStopLineCountBefore,
294566afa0aSRaphael Isemann   ePropertyHighlightSource,
2959666ba75STodd Fiala   ePropertyStopShowColumn,
2969666ba75STodd Fiala   ePropertyStopShowColumnAnsiPrefix,
2979666ba75STodd Fiala   ePropertyStopShowColumnAnsiSuffix,
29867cc0636SGreg Clayton   ePropertyTerminalWidth,
29967cc0636SGreg Clayton   ePropertyThreadFormat,
3006a9767c7SJim Ingham   ePropertyThreadStopFormat,
301c3ce7f27SMichael Sartain   ePropertyUseExternalEditor,
302c3ce7f27SMichael Sartain   ePropertyUseColor,
303ebdc1ac0SEnrico Granata   ePropertyAutoOneLineSummaries,
3046681041dSSean Callanan   ePropertyAutoIndent,
3056681041dSSean Callanan   ePropertyPrintDecls,
3066681041dSSean Callanan   ePropertyTabSize,
3077f1c1211SPavel Labath   ePropertyEscapeNonPrintables,
3087f1c1211SPavel Labath   ePropertyFrameFormatUnique,
30967cc0636SGreg Clayton };
31067cc0636SGreg Clayton 
311df370550SEugene Zelenko LoadPluginCallbackType Debugger::g_load_plugin_callback = nullptr;
3124c05410fSGreg Clayton 
31397206d57SZachary Turner Status Debugger::SetPropertyValue(const ExecutionContext *exe_ctx,
3144c05410fSGreg Clayton                                   VarSetOperationType op,
31597206d57SZachary Turner                                   llvm::StringRef property_path,
31697206d57SZachary Turner                                   llvm::StringRef value) {
31731d97a5cSZachary Turner   bool is_load_script = (property_path == "target.load-script-from-symbol-file");
31831d97a5cSZachary Turner   bool is_escape_non_printables = (property_path == "escape-non-printables");
31984a53dfbSEnrico Granata   TargetSP target_sp;
320397ddd5fSEnrico Granata   LoadScriptFromSymFile load_script_old_value;
321b9c1b51eSKate Stone   if (is_load_script && exe_ctx->GetTargetSP()) {
32284a53dfbSEnrico Granata     target_sp = exe_ctx->GetTargetSP();
323b9c1b51eSKate Stone     load_script_old_value =
324b9c1b51eSKate Stone         target_sp->TargetProperties::GetLoadScriptFromSymbolFile();
32584a53dfbSEnrico Granata   }
32697206d57SZachary Turner   Status error(Properties::SetPropertyValue(exe_ctx, op, property_path, value));
327b9c1b51eSKate Stone   if (error.Success()) {
32884a53dfbSEnrico Granata     // FIXME it would be nice to have "on-change" callbacks for properties
32931d97a5cSZachary Turner     if (property_path == g_properties[ePropertyPrompt].name) {
330514d8cd8SZachary Turner       llvm::StringRef new_prompt = GetPrompt();
331b9c1b51eSKate Stone       std::string str = lldb_utility::ansi::FormatAnsiTerminalCodes(
332b9c1b51eSKate Stone           new_prompt, GetUseColor());
333c3ce7f27SMichael Sartain       if (str.length())
334771ef6d4SMalcolm Parsons         new_prompt = str;
33544d93782SGreg Clayton       GetCommandInterpreter().UpdatePrompt(new_prompt);
3362f3df613SZachary Turner       auto bytes = llvm::make_unique<EventDataBytes>(new_prompt);
3372f3df613SZachary Turner       auto prompt_change_event_sp = std::make_shared<Event>(
3382f3df613SZachary Turner           CommandInterpreter::eBroadcastBitResetPrompt, bytes.release());
3394c05410fSGreg Clayton       GetCommandInterpreter().BroadcastEvent(prompt_change_event_sp);
34031d97a5cSZachary Turner     } else if (property_path == g_properties[ePropertyUseColor].name) {
341b9c1b51eSKate Stone       // use-color changed. Ping the prompt so it can reset the ansi terminal
342b9c1b51eSKate Stone       // codes.
343c3ce7f27SMichael Sartain       SetPrompt(GetPrompt());
344b9c1b51eSKate Stone     } else if (is_load_script && target_sp &&
345b9c1b51eSKate Stone                load_script_old_value == eLoadScriptFromSymFileWarn) {
346b9c1b51eSKate Stone       if (target_sp->TargetProperties::GetLoadScriptFromSymbolFile() ==
347b9c1b51eSKate Stone           eLoadScriptFromSymFileTrue) {
34897206d57SZachary Turner         std::list<Status> errors;
3499730339bSEnrico Granata         StreamString feedback_stream;
350b9c1b51eSKate Stone         if (!target_sp->LoadScriptingResources(errors, &feedback_stream)) {
35144d93782SGreg Clayton           StreamFileSP stream_sp(GetErrorFile());
352b9c1b51eSKate Stone           if (stream_sp) {
353b9c1b51eSKate Stone             for (auto error : errors) {
35444d93782SGreg Clayton               stream_sp->Printf("%s\n", error.AsCString());
35584a53dfbSEnrico Granata             }
3569730339bSEnrico Granata             if (feedback_stream.GetSize())
357c156427dSZachary Turner               stream_sp->PutCString(feedback_stream.GetString());
35844d93782SGreg Clayton           }
35984a53dfbSEnrico Granata         }
36084a53dfbSEnrico Granata       }
361b9c1b51eSKate Stone     } else if (is_escape_non_printables) {
362ebdc1ac0SEnrico Granata       DataVisualization::ForceUpdate();
363ebdc1ac0SEnrico Granata     }
3644c05410fSGreg Clayton   }
3654c05410fSGreg Clayton   return error;
3664c05410fSGreg Clayton }
3674c05410fSGreg Clayton 
368b9c1b51eSKate Stone bool Debugger::GetAutoConfirm() const {
36967cc0636SGreg Clayton   const uint32_t idx = ePropertyAutoConfirm;
370b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsBoolean(
371b9c1b51eSKate Stone       nullptr, idx, g_properties[idx].default_uint_value != 0);
37267cc0636SGreg Clayton }
37367cc0636SGreg Clayton 
374b9c1b51eSKate Stone const FormatEntity::Entry *Debugger::GetDisassemblyFormat() const {
375aff1b357SJason Molenda   const uint32_t idx = ePropertyDisassemblyFormat;
376df370550SEugene Zelenko   return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
377aff1b357SJason Molenda }
378aff1b357SJason Molenda 
379b9c1b51eSKate Stone const FormatEntity::Entry *Debugger::GetFrameFormat() const {
38067cc0636SGreg Clayton   const uint32_t idx = ePropertyFrameFormat;
381df370550SEugene Zelenko   return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
38267cc0636SGreg Clayton }
38367cc0636SGreg Clayton 
3847f1c1211SPavel Labath const FormatEntity::Entry *Debugger::GetFrameFormatUnique() const {
3857f1c1211SPavel Labath   const uint32_t idx = ePropertyFrameFormatUnique;
3867f1c1211SPavel Labath   return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
3877f1c1211SPavel Labath }
3887f1c1211SPavel Labath 
389b9c1b51eSKate Stone bool Debugger::GetNotifyVoid() const {
39067cc0636SGreg Clayton   const uint32_t idx = ePropertyNotiftVoid;
391b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsBoolean(
392b9c1b51eSKate Stone       nullptr, idx, g_properties[idx].default_uint_value != 0);
39367cc0636SGreg Clayton }
39467cc0636SGreg Clayton 
395514d8cd8SZachary Turner llvm::StringRef Debugger::GetPrompt() const {
39667cc0636SGreg Clayton   const uint32_t idx = ePropertyPrompt;
397b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsString(
398b9c1b51eSKate Stone       nullptr, idx, g_properties[idx].default_cstr_value);
39967cc0636SGreg Clayton }
40067cc0636SGreg Clayton 
401514d8cd8SZachary Turner void Debugger::SetPrompt(llvm::StringRef p) {
40267cc0636SGreg Clayton   const uint32_t idx = ePropertyPrompt;
403df370550SEugene Zelenko   m_collection_sp->SetPropertyAtIndexAsString(nullptr, idx, p);
404514d8cd8SZachary Turner   llvm::StringRef new_prompt = GetPrompt();
405b9c1b51eSKate Stone   std::string str =
406b9c1b51eSKate Stone       lldb_utility::ansi::FormatAnsiTerminalCodes(new_prompt, GetUseColor());
407c3ce7f27SMichael Sartain   if (str.length())
408771ef6d4SMalcolm Parsons     new_prompt = str;
40944d93782SGreg Clayton   GetCommandInterpreter().UpdatePrompt(new_prompt);
41067cc0636SGreg Clayton }
41167cc0636SGreg Clayton 
412b9c1b51eSKate Stone const FormatEntity::Entry *Debugger::GetThreadFormat() const {
41367cc0636SGreg Clayton   const uint32_t idx = ePropertyThreadFormat;
414df370550SEugene Zelenko   return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
41567cc0636SGreg Clayton }
41667cc0636SGreg Clayton 
4176a9767c7SJim Ingham const FormatEntity::Entry *Debugger::GetThreadStopFormat() const {
4186a9767c7SJim Ingham   const uint32_t idx = ePropertyThreadStopFormat;
4196a9767c7SJim Ingham   return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
4206a9767c7SJim Ingham }
4216a9767c7SJim Ingham 
422b9c1b51eSKate Stone lldb::ScriptLanguage Debugger::GetScriptLanguage() const {
42367cc0636SGreg Clayton   const uint32_t idx = ePropertyScriptLanguage;
424b9c1b51eSKate Stone   return (lldb::ScriptLanguage)m_collection_sp->GetPropertyAtIndexAsEnumeration(
425b9c1b51eSKate Stone       nullptr, idx, g_properties[idx].default_uint_value);
42667cc0636SGreg Clayton }
42767cc0636SGreg Clayton 
428b9c1b51eSKate Stone bool Debugger::SetScriptLanguage(lldb::ScriptLanguage script_lang) {
42967cc0636SGreg Clayton   const uint32_t idx = ePropertyScriptLanguage;
430b9c1b51eSKate Stone   return m_collection_sp->SetPropertyAtIndexAsEnumeration(nullptr, idx,
431b9c1b51eSKate Stone                                                           script_lang);
43267cc0636SGreg Clayton }
43367cc0636SGreg Clayton 
434b9c1b51eSKate Stone uint32_t Debugger::GetTerminalWidth() const {
43567cc0636SGreg Clayton   const uint32_t idx = ePropertyTerminalWidth;
436b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsSInt64(
437b9c1b51eSKate Stone       nullptr, idx, g_properties[idx].default_uint_value);
43867cc0636SGreg Clayton }
43967cc0636SGreg Clayton 
440b9c1b51eSKate Stone bool Debugger::SetTerminalWidth(uint32_t term_width) {
44167cc0636SGreg Clayton   const uint32_t idx = ePropertyTerminalWidth;
442df370550SEugene Zelenko   return m_collection_sp->SetPropertyAtIndexAsSInt64(nullptr, idx, term_width);
44367cc0636SGreg Clayton }
44467cc0636SGreg Clayton 
445b9c1b51eSKate Stone bool Debugger::GetUseExternalEditor() const {
44667cc0636SGreg Clayton   const uint32_t idx = ePropertyUseExternalEditor;
447b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsBoolean(
448b9c1b51eSKate Stone       nullptr, idx, g_properties[idx].default_uint_value != 0);
44967cc0636SGreg Clayton }
45067cc0636SGreg Clayton 
451b9c1b51eSKate Stone bool Debugger::SetUseExternalEditor(bool b) {
45267cc0636SGreg Clayton   const uint32_t idx = ePropertyUseExternalEditor;
453df370550SEugene Zelenko   return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
45467cc0636SGreg Clayton }
45567cc0636SGreg Clayton 
456b9c1b51eSKate Stone bool Debugger::GetUseColor() const {
457c3ce7f27SMichael Sartain   const uint32_t idx = ePropertyUseColor;
458b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsBoolean(
459b9c1b51eSKate Stone       nullptr, idx, g_properties[idx].default_uint_value != 0);
460c3ce7f27SMichael Sartain }
461c3ce7f27SMichael Sartain 
462b9c1b51eSKate Stone bool Debugger::SetUseColor(bool b) {
463c3ce7f27SMichael Sartain   const uint32_t idx = ePropertyUseColor;
464df370550SEugene Zelenko   bool ret = m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
465c3ce7f27SMichael Sartain   SetPrompt(GetPrompt());
466c3ce7f27SMichael Sartain   return ret;
467c3ce7f27SMichael Sartain }
468c3ce7f27SMichael Sartain 
469566afa0aSRaphael Isemann bool Debugger::GetHighlightSource() const {
470566afa0aSRaphael Isemann   const uint32_t idx = ePropertyHighlightSource;
471566afa0aSRaphael Isemann   return m_collection_sp->GetPropertyAtIndexAsBoolean(
472566afa0aSRaphael Isemann       nullptr, idx, g_properties[idx].default_uint_value);
473566afa0aSRaphael Isemann }
474566afa0aSRaphael Isemann 
4759666ba75STodd Fiala StopShowColumn Debugger::GetStopShowColumn() const {
4769666ba75STodd Fiala   const uint32_t idx = ePropertyStopShowColumn;
4779666ba75STodd Fiala   return (lldb::StopShowColumn)m_collection_sp->GetPropertyAtIndexAsEnumeration(
4789666ba75STodd Fiala       nullptr, idx, g_properties[idx].default_uint_value);
4799666ba75STodd Fiala }
4809666ba75STodd Fiala 
48120786326SRaphael Isemann llvm::StringRef Debugger::GetStopShowColumnAnsiPrefix() const {
4829666ba75STodd Fiala   const uint32_t idx = ePropertyStopShowColumnAnsiPrefix;
48320786326SRaphael Isemann   return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, "");
4849666ba75STodd Fiala }
4859666ba75STodd Fiala 
48620786326SRaphael Isemann llvm::StringRef Debugger::GetStopShowColumnAnsiSuffix() const {
4879666ba75STodd Fiala   const uint32_t idx = ePropertyStopShowColumnAnsiSuffix;
48820786326SRaphael Isemann   return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, "");
4899666ba75STodd Fiala }
4909666ba75STodd Fiala 
491b9c1b51eSKate Stone uint32_t Debugger::GetStopSourceLineCount(bool before) const {
492b9c1b51eSKate Stone   const uint32_t idx =
493b9c1b51eSKate Stone       before ? ePropertyStopLineCountBefore : ePropertyStopLineCountAfter;
494b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsSInt64(
495b9c1b51eSKate Stone       nullptr, idx, g_properties[idx].default_uint_value);
49667cc0636SGreg Clayton }
49767cc0636SGreg Clayton 
498b9c1b51eSKate Stone Debugger::StopDisassemblyType Debugger::GetStopDisassemblyDisplay() const {
49967cc0636SGreg Clayton   const uint32_t idx = ePropertyStopDisassemblyDisplay;
500b9c1b51eSKate Stone   return (Debugger::StopDisassemblyType)
501b9c1b51eSKate Stone       m_collection_sp->GetPropertyAtIndexAsEnumeration(
502b9c1b51eSKate Stone           nullptr, idx, g_properties[idx].default_uint_value);
50367cc0636SGreg Clayton }
50467cc0636SGreg Clayton 
505b9c1b51eSKate Stone uint32_t Debugger::GetDisassemblyLineCount() const {
50667cc0636SGreg Clayton   const uint32_t idx = ePropertyStopDisassemblyCount;
507b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsSInt64(
508b9c1b51eSKate Stone       nullptr, idx, g_properties[idx].default_uint_value);
50967cc0636SGreg Clayton }
510e372b98dSGreg Clayton 
511b9c1b51eSKate Stone bool Debugger::GetAutoOneLineSummaries() const {
51290a8db30SEnrico Granata   const uint32_t idx = ePropertyAutoOneLineSummaries;
513df370550SEugene Zelenko   return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true);
514ebdc1ac0SEnrico Granata }
515553fad5cSEnrico Granata 
516b9c1b51eSKate Stone bool Debugger::GetEscapeNonPrintables() const {
517ebdc1ac0SEnrico Granata   const uint32_t idx = ePropertyEscapeNonPrintables;
518df370550SEugene Zelenko   return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true);
519553fad5cSEnrico Granata }
520553fad5cSEnrico Granata 
521b9c1b51eSKate Stone bool Debugger::GetAutoIndent() const {
5226681041dSSean Callanan   const uint32_t idx = ePropertyAutoIndent;
523df370550SEugene Zelenko   return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true);
5246681041dSSean Callanan }
5256681041dSSean Callanan 
526b9c1b51eSKate Stone bool Debugger::SetAutoIndent(bool b) {
5276681041dSSean Callanan   const uint32_t idx = ePropertyAutoIndent;
528df370550SEugene Zelenko   return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
5296681041dSSean Callanan }
5306681041dSSean Callanan 
531b9c1b51eSKate Stone bool Debugger::GetPrintDecls() const {
5326681041dSSean Callanan   const uint32_t idx = ePropertyPrintDecls;
533df370550SEugene Zelenko   return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true);
5346681041dSSean Callanan }
5356681041dSSean Callanan 
536b9c1b51eSKate Stone bool Debugger::SetPrintDecls(bool b) {
5376681041dSSean Callanan   const uint32_t idx = ePropertyPrintDecls;
538df370550SEugene Zelenko   return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
5396681041dSSean Callanan }
5406681041dSSean Callanan 
541b9c1b51eSKate Stone uint32_t Debugger::GetTabSize() const {
5426681041dSSean Callanan   const uint32_t idx = ePropertyTabSize;
543b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsUInt64(
544b9c1b51eSKate Stone       nullptr, idx, g_properties[idx].default_uint_value);
5456681041dSSean Callanan }
5466681041dSSean Callanan 
547b9c1b51eSKate Stone bool Debugger::SetTabSize(uint32_t tab_size) {
5486681041dSSean Callanan   const uint32_t idx = ePropertyTabSize;
549df370550SEugene Zelenko   return m_collection_sp->SetPropertyAtIndexAsUInt64(nullptr, idx, tab_size);
5506681041dSSean Callanan }
5516681041dSSean Callanan 
5521b654882SGreg Clayton #pragma mark Debugger
5531b654882SGreg Clayton 
55467cc0636SGreg Clayton // const DebuggerPropertiesSP &
55567cc0636SGreg Clayton // Debugger::GetSettings() const
55667cc0636SGreg Clayton //{
55767cc0636SGreg Clayton //    return m_properties_sp;
55867cc0636SGreg Clayton //}
55967cc0636SGreg Clayton //
56099d0faf2SGreg Clayton 
561b9c1b51eSKate Stone void Debugger::Initialize(LoadPluginCallbackType load_plugin_callback) {
562b9c1b51eSKate Stone   assert(g_debugger_list_ptr == nullptr &&
563b9c1b51eSKate Stone          "Debugger::Initialize called more than once!");
5646c42e063SGreg Clayton   g_debugger_list_mutex_ptr = new std::recursive_mutex();
5656c42e063SGreg Clayton   g_debugger_list_ptr = new DebuggerList();
5665fb8f797SGreg Clayton   g_load_plugin_callback = load_plugin_callback;
56799d0faf2SGreg Clayton }
56830fdc8d8SChris Lattner 
569b9c1b51eSKate Stone void Debugger::Terminate() {
570b9c1b51eSKate Stone   assert(g_debugger_list_ptr &&
571b9c1b51eSKate Stone          "Debugger::Terminate called without a matching Debugger::Initialize!");
572e6e2bb38SZachary Turner 
573b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
57499d0faf2SGreg Clayton     // Clear our master list of debugger objects
5756c42e063SGreg Clayton     {
5766c42e063SGreg Clayton       std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
5776c42e063SGreg Clayton       for (const auto &debugger : *g_debugger_list_ptr)
578f3cd1819SOleksiy Vyalov         debugger->Clear();
5796c42e063SGreg Clayton       g_debugger_list_ptr->clear();
5806c42e063SGreg Clayton     }
5816c42e063SGreg Clayton   }
58230fdc8d8SChris Lattner }
58330fdc8d8SChris Lattner 
584b9c1b51eSKate Stone void Debugger::SettingsInitialize() { Target::SettingsInitialize(); }
58520bd37f7SCaroline Tice 
586b9c1b51eSKate Stone void Debugger::SettingsTerminate() { Target::SettingsTerminate(); }
58720bd37f7SCaroline Tice 
58897206d57SZachary Turner bool Debugger::LoadPlugin(const FileSpec &spec, Status &error) {
589b9c1b51eSKate Stone   if (g_load_plugin_callback) {
590b9c1b51eSKate Stone     llvm::sys::DynamicLibrary dynlib =
591b9c1b51eSKate Stone         g_load_plugin_callback(shared_from_this(), spec, error);
592b9c1b51eSKate Stone     if (dynlib.isValid()) {
59358a559c0SZachary Turner       m_loaded_plugins.push_back(dynlib);
59421dfcd9dSEnrico Granata       return true;
59521dfcd9dSEnrico Granata     }
596b9c1b51eSKate Stone   } else {
59705097246SAdrian Prantl     // The g_load_plugin_callback is registered in SBDebugger::Initialize() and
59805097246SAdrian Prantl     // if the public API layer isn't available (code is linking against all of
59905097246SAdrian Prantl     // the internal LLDB static libraries), then we can't load plugins
6005fb8f797SGreg Clayton     error.SetErrorString("Public API layer is not available");
6015fb8f797SGreg Clayton   }
60221dfcd9dSEnrico Granata   return false;
60321dfcd9dSEnrico Granata }
60421dfcd9dSEnrico Granata 
60521dfcd9dSEnrico Granata static FileSpec::EnumerateDirectoryResult
6067d86ee5aSZachary Turner LoadPluginCallback(void *baton, llvm::sys::fs::file_type ft,
607b9c1b51eSKate Stone                    const FileSpec &file_spec) {
60897206d57SZachary Turner   Status error;
60921dfcd9dSEnrico Granata 
610ad8d48f9SJonas Devlieghere   static ConstString g_dylibext(".dylib");
611ad8d48f9SJonas Devlieghere   static ConstString g_solibext(".so");
61221dfcd9dSEnrico Granata 
61321dfcd9dSEnrico Granata   if (!baton)
61421dfcd9dSEnrico Granata     return FileSpec::eEnumerateDirectoryResultQuit;
61521dfcd9dSEnrico Granata 
61621dfcd9dSEnrico Granata   Debugger *debugger = (Debugger *)baton;
61721dfcd9dSEnrico Granata 
6187d86ee5aSZachary Turner   namespace fs = llvm::sys::fs;
61905097246SAdrian Prantl   // If we have a regular file, a symbolic link or unknown file type, try and
62005097246SAdrian Prantl   // process the file. We must handle unknown as sometimes the directory
62121dfcd9dSEnrico Granata   // enumeration might be enumerating a file system that doesn't have correct
62221dfcd9dSEnrico Granata   // file type information.
6237d86ee5aSZachary Turner   if (ft == fs::file_type::regular_file || ft == fs::file_type::symlink_file ||
6247d86ee5aSZachary Turner       ft == fs::file_type::type_unknown) {
62521dfcd9dSEnrico Granata     FileSpec plugin_file_spec(file_spec);
62621dfcd9dSEnrico Granata     plugin_file_spec.ResolvePath();
62721dfcd9dSEnrico Granata 
6283cf443ddSMichael Sartain     if (plugin_file_spec.GetFileNameExtension() != g_dylibext &&
629b9c1b51eSKate Stone         plugin_file_spec.GetFileNameExtension() != g_solibext) {
63021dfcd9dSEnrico Granata       return FileSpec::eEnumerateDirectoryResultNext;
6313cf443ddSMichael Sartain     }
63221dfcd9dSEnrico Granata 
63397206d57SZachary Turner     Status plugin_load_error;
634e743c782SEnrico Granata     debugger->LoadPlugin(plugin_file_spec, plugin_load_error);
63521dfcd9dSEnrico Granata 
63621dfcd9dSEnrico Granata     return FileSpec::eEnumerateDirectoryResultNext;
6377d86ee5aSZachary Turner   } else if (ft == fs::file_type::directory_file ||
6387d86ee5aSZachary Turner              ft == fs::file_type::symlink_file ||
6397d86ee5aSZachary Turner              ft == fs::file_type::type_unknown) {
64005097246SAdrian Prantl     // Try and recurse into anything that a directory or symbolic link. We must
64105097246SAdrian Prantl     // also do this for unknown as sometimes the directory enumeration might be
64205097246SAdrian Prantl     // enumerating a file system that doesn't have correct file type
64321dfcd9dSEnrico Granata     // information.
64421dfcd9dSEnrico Granata     return FileSpec::eEnumerateDirectoryResultEnter;
64521dfcd9dSEnrico Granata   }
64621dfcd9dSEnrico Granata 
64721dfcd9dSEnrico Granata   return FileSpec::eEnumerateDirectoryResultNext;
64821dfcd9dSEnrico Granata }
64921dfcd9dSEnrico Granata 
650b9c1b51eSKate Stone void Debugger::InstanceInitialize() {
65121dfcd9dSEnrico Granata   const bool find_directories = true;
65221dfcd9dSEnrico Granata   const bool find_files = true;
65321dfcd9dSEnrico Granata   const bool find_other = true;
65421dfcd9dSEnrico Granata   char dir_path[PATH_MAX];
65560f028ffSPavel Labath   if (FileSpec dir_spec = HostInfo::GetSystemPluginDir()) {
656b9c1b51eSKate Stone     if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path))) {
657b9c1b51eSKate Stone       FileSpec::EnumerateDirectory(dir_path, find_directories, find_files,
658b9c1b51eSKate Stone                                    find_other, LoadPluginCallback, this);
65921dfcd9dSEnrico Granata     }
66021dfcd9dSEnrico Granata   }
66121dfcd9dSEnrico Granata 
66260f028ffSPavel Labath   if (FileSpec dir_spec = HostInfo::GetUserPluginDir()) {
663b9c1b51eSKate Stone     if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path))) {
664b9c1b51eSKate Stone       FileSpec::EnumerateDirectory(dir_path, find_directories, find_files,
665b9c1b51eSKate Stone                                    find_other, LoadPluginCallback, this);
66621dfcd9dSEnrico Granata     }
66721dfcd9dSEnrico Granata   }
668e8cd0c98SGreg Clayton 
669e8cd0c98SGreg Clayton   PluginManager::DebuggerInitialize(*this);
67021dfcd9dSEnrico Granata }
67121dfcd9dSEnrico Granata 
672b9c1b51eSKate Stone DebuggerSP Debugger::CreateInstance(lldb::LogOutputCallback log_callback,
673b9c1b51eSKate Stone                                     void *baton) {
674228063cdSJim Ingham   DebuggerSP debugger_sp(new Debugger(log_callback, baton));
675b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
6766c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
6776c42e063SGreg Clayton     g_debugger_list_ptr->push_back(debugger_sp);
6786611103cSGreg Clayton   }
67921dfcd9dSEnrico Granata   debugger_sp->InstanceInitialize();
6806611103cSGreg Clayton   return debugger_sp;
6816611103cSGreg Clayton }
6826611103cSGreg Clayton 
683b9c1b51eSKate Stone void Debugger::Destroy(DebuggerSP &debugger_sp) {
684df370550SEugene Zelenko   if (!debugger_sp)
685e02657b1SCaroline Tice     return;
686e02657b1SCaroline Tice 
6878314c525SJim Ingham   debugger_sp->Clear();
6888314c525SJim Ingham 
689b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
6906c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
6916c42e063SGreg Clayton     DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
692b9c1b51eSKate Stone     for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
693b9c1b51eSKate Stone       if ((*pos).get() == debugger_sp.get()) {
6946c42e063SGreg Clayton         g_debugger_list_ptr->erase(pos);
695e02657b1SCaroline Tice         return;
696e02657b1SCaroline Tice       }
697e02657b1SCaroline Tice     }
698e02657b1SCaroline Tice   }
699c15f55e2SGreg Clayton }
700e02657b1SCaroline Tice 
7014d122c40SGreg Clayton DebuggerSP
702b9c1b51eSKate Stone Debugger::FindDebuggerWithInstanceName(const ConstString &instance_name) {
7034d122c40SGreg Clayton   DebuggerSP debugger_sp;
704b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
7056c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
7066c42e063SGreg Clayton     DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
707b9c1b51eSKate Stone     for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
708b9c1b51eSKate Stone       if ((*pos)->m_instance_name == instance_name) {
7096920b52bSGreg Clayton         debugger_sp = *pos;
7106920b52bSGreg Clayton         break;
7116920b52bSGreg Clayton       }
7126920b52bSGreg Clayton     }
7136920b52bSGreg Clayton   }
7143df9a8dfSCaroline Tice   return debugger_sp;
7153df9a8dfSCaroline Tice }
7166611103cSGreg Clayton 
717b9c1b51eSKate Stone TargetSP Debugger::FindTargetWithProcessID(lldb::pid_t pid) {
7184d122c40SGreg Clayton   TargetSP target_sp;
719b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
7206c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
7216c42e063SGreg Clayton     DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
722b9c1b51eSKate Stone     for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
7236611103cSGreg Clayton       target_sp = (*pos)->GetTargetList().FindTargetWithProcessID(pid);
7246611103cSGreg Clayton       if (target_sp)
7256611103cSGreg Clayton         break;
7266611103cSGreg Clayton     }
727c15f55e2SGreg Clayton   }
7286611103cSGreg Clayton   return target_sp;
7296611103cSGreg Clayton }
7306611103cSGreg Clayton 
731b9c1b51eSKate Stone TargetSP Debugger::FindTargetWithProcess(Process *process) {
732e4e45924SGreg Clayton   TargetSP target_sp;
733b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
7346c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
7356c42e063SGreg Clayton     DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
736b9c1b51eSKate Stone     for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
737e4e45924SGreg Clayton       target_sp = (*pos)->GetTargetList().FindTargetWithProcess(process);
738e4e45924SGreg Clayton       if (target_sp)
739e4e45924SGreg Clayton         break;
740e4e45924SGreg Clayton     }
741c15f55e2SGreg Clayton   }
742e4e45924SGreg Clayton   return target_sp;
743e4e45924SGreg Clayton }
744e4e45924SGreg Clayton 
745b9c1b51eSKate Stone Debugger::Debugger(lldb::LogOutputCallback log_callback, void *baton)
746b9c1b51eSKate Stone     : UserID(g_unique_id++),
7472f3df613SZachary Turner       Properties(std::make_shared<OptionValueProperties>()),
7482f3df613SZachary Turner       m_input_file_sp(std::make_shared<StreamFile>(stdin, false)),
7492f3df613SZachary Turner       m_output_file_sp(std::make_shared<StreamFile>(stdout, false)),
7502f3df613SZachary Turner       m_error_file_sp(std::make_shared<StreamFile>(stderr, false)),
751583bbb1dSJim Ingham       m_broadcaster_manager_sp(BroadcasterManager::MakeBroadcasterManager()),
752b9c1b51eSKate Stone       m_terminal_state(), m_target_list(*this), m_platform_list(),
753583bbb1dSJim Ingham       m_listener_sp(Listener::MakeListener("lldb.Debugger")),
754b9c1b51eSKate Stone       m_source_manager_ap(), m_source_file_cache(),
7552f3df613SZachary Turner       m_command_interpreter_ap(llvm::make_unique<CommandInterpreter>(
7562f3df613SZachary Turner           *this, eScriptLanguageDefault, false)),
757b9c1b51eSKate Stone       m_input_reader_stack(), m_instance_name(), m_loaded_plugins(),
758b9c1b51eSKate Stone       m_event_handler_thread(), m_io_handler_thread(),
7594329fe42SGreg Clayton       m_sync_broadcaster(nullptr, "lldb.debugger.sync"),
760b9c1b51eSKate Stone       m_forward_listener_sp(), m_clear_once() {
76167cc0636SGreg Clayton   char instance_cstr[256];
76267cc0636SGreg Clayton   snprintf(instance_cstr, sizeof(instance_cstr), "debugger_%d", (int)GetID());
76367cc0636SGreg Clayton   m_instance_name.SetCString(instance_cstr);
764228063cdSJim Ingham   if (log_callback)
7652f3df613SZachary Turner     m_log_callback_stream_sp =
7662f3df613SZachary Turner         std::make_shared<StreamCallback>(log_callback, baton);
7676611103cSGreg Clayton   m_command_interpreter_ap->Initialize();
768ded470d3SGreg Clayton   // Always add our default platform to the platform list
769615eb7e6SGreg Clayton   PlatformSP default_platform_sp(Platform::GetHostPlatform());
770df370550SEugene Zelenko   assert(default_platform_sp);
771ded470d3SGreg Clayton   m_platform_list.Append(default_platform_sp, true);
77267cc0636SGreg Clayton 
773754a9369SGreg Clayton   m_collection_sp->Initialize(g_properties);
774b9c1b51eSKate Stone   m_collection_sp->AppendProperty(
775b9c1b51eSKate Stone       ConstString("target"),
776b9c1b51eSKate Stone       ConstString("Settings specify to debugging targets."), true,
77767cc0636SGreg Clayton       Target::GetGlobalProperties()->GetValueProperties());
778b9c1b51eSKate Stone   m_collection_sp->AppendProperty(
779b9c1b51eSKate Stone       ConstString("platform"), ConstString("Platform settings."), true,
78063acdfdeSOleksiy Vyalov       Platform::GetGlobalPlatformProperties()->GetValueProperties());
781235354beSAdrian Prantl   m_collection_sp->AppendProperty(
7823cd29bcfSAdrian Prantl       ConstString("symbols"), ConstString("Symbol lookup and cache settings."),
7833cd29bcfSAdrian Prantl       true, ModuleList::GetGlobalModuleListProperties().GetValueProperties());
784b9c1b51eSKate Stone   if (m_command_interpreter_ap) {
785b9c1b51eSKate Stone     m_collection_sp->AppendProperty(
786b9c1b51eSKate Stone         ConstString("interpreter"),
787754a9369SGreg Clayton         ConstString("Settings specify to the debugger's command interpreter."),
788b9c1b51eSKate Stone         true, m_command_interpreter_ap->GetValueProperties());
789754a9369SGreg Clayton   }
790b9c1b51eSKate Stone   OptionValueSInt64 *term_width =
791b9c1b51eSKate Stone       m_collection_sp->GetPropertyAtIndexAsOptionValueSInt64(
792b9c1b51eSKate Stone           nullptr, ePropertyTerminalWidth);
79367cc0636SGreg Clayton   term_width->SetMinimumValue(10);
79467cc0636SGreg Clayton   term_width->SetMaximumValue(1024);
795c3ce7f27SMichael Sartain 
796c3ce7f27SMichael Sartain   // Turn off use-color if this is a dumb terminal.
797c3ce7f27SMichael Sartain   const char *term = getenv("TERM");
798c3ce7f27SMichael Sartain   if (term && !strcmp(term, "dumb"))
799c3ce7f27SMichael Sartain     SetUseColor(false);
800eca9ce14SRaphael Isemann   // Turn off use-color if we don't write to a terminal with color support.
801eca9ce14SRaphael Isemann   if (!m_output_file_sp->GetFile().GetIsTerminalWithColors())
802eca9ce14SRaphael Isemann     SetUseColor(false);
8038aa23614SDavid Bolvansky 
8048aa23614SDavid Bolvansky #if defined(_WIN32) && defined(ENABLE_VIRTUAL_TERMINAL_PROCESSING)
8058aa23614SDavid Bolvansky   // Enabling use of ANSI color codes because LLDB is using them to highlight
8068aa23614SDavid Bolvansky   // text.
8078aa23614SDavid Bolvansky   llvm::sys::Process::UseANSIEscapeCodes(true);
8088aa23614SDavid Bolvansky #endif
80930fdc8d8SChris Lattner }
81030fdc8d8SChris Lattner 
811b9c1b51eSKate Stone Debugger::~Debugger() { Clear(); }
8128314c525SJim Ingham 
813b9c1b51eSKate Stone void Debugger::Clear() {
8144329fe42SGreg Clayton   //----------------------------------------------------------------------
81505097246SAdrian Prantl   // Make sure we call this function only once. With the C++ global destructor
81605097246SAdrian Prantl   // chain having a list of debuggers and with code that can be running on
81705097246SAdrian Prantl   // other threads, we need to ensure this doesn't happen multiple times.
8184329fe42SGreg Clayton   //
8194329fe42SGreg Clayton   // The following functions call Debugger::Clear():
8204329fe42SGreg Clayton   //     Debugger::~Debugger();
8214329fe42SGreg Clayton   //     static void Debugger::Destroy(lldb::DebuggerSP &debugger_sp);
8224329fe42SGreg Clayton   //     static void Debugger::Terminate();
8234329fe42SGreg Clayton   //----------------------------------------------------------------------
824c5f28e2aSKamil Rytarowski   llvm::call_once(m_clear_once, [this]() {
82544d93782SGreg Clayton     ClearIOHandlers();
82644d93782SGreg Clayton     StopIOHandlerThread();
82744d93782SGreg Clayton     StopEventHandlerThread();
828583bbb1dSJim Ingham     m_listener_sp->Clear();
8296611103cSGreg Clayton     int num_targets = m_target_list.GetNumTargets();
830b9c1b51eSKate Stone     for (int i = 0; i < num_targets; i++) {
831ccbc08e6SGreg Clayton       TargetSP target_sp(m_target_list.GetTargetAtIndex(i));
832b9c1b51eSKate Stone       if (target_sp) {
833ccbc08e6SGreg Clayton         ProcessSP process_sp(target_sp->GetProcessSP());
8346611103cSGreg Clayton         if (process_sp)
8351fd07059SJim Ingham           process_sp->Finalize();
836ccbc08e6SGreg Clayton         target_sp->Destroy();
8376611103cSGreg Clayton       }
83830fdc8d8SChris Lattner     }
839583bbb1dSJim Ingham     m_broadcaster_manager_sp->Clear();
84030fdc8d8SChris Lattner 
841b9c1b51eSKate Stone     // Close the input file _before_ we close the input read communications
84205097246SAdrian Prantl     // class as it does NOT own the input file, our m_input_file does.
843c5917d9aSJim Ingham     m_terminal_state.Clear();
84444d93782SGreg Clayton     if (m_input_file_sp)
84544d93782SGreg Clayton       m_input_file_sp->GetFile().Close();
8460c4129f2SGreg Clayton 
8470c4129f2SGreg Clayton     m_command_interpreter_ap->Clear();
8484329fe42SGreg Clayton   });
8498314c525SJim Ingham }
85030fdc8d8SChris Lattner 
851b9c1b51eSKate Stone bool Debugger::GetCloseInputOnEOF() const {
85244d93782SGreg Clayton   //    return m_input_comm.GetCloseOnEOF();
85344d93782SGreg Clayton   return false;
854fc3f027dSGreg Clayton }
855fc3f027dSGreg Clayton 
856b9c1b51eSKate Stone void Debugger::SetCloseInputOnEOF(bool b) {
85744d93782SGreg Clayton   //    m_input_comm.SetCloseOnEOF(b);
858fc3f027dSGreg Clayton }
859fc3f027dSGreg Clayton 
860b9c1b51eSKate Stone bool Debugger::GetAsyncExecution() {
8616611103cSGreg Clayton   return !m_command_interpreter_ap->GetSynchronous();
86230fdc8d8SChris Lattner }
86330fdc8d8SChris Lattner 
864b9c1b51eSKate Stone void Debugger::SetAsyncExecution(bool async_execution) {
8656611103cSGreg Clayton   m_command_interpreter_ap->SetSynchronous(!async_execution);
86630fdc8d8SChris Lattner }
86730fdc8d8SChris Lattner 
868b9c1b51eSKate Stone void Debugger::SetInputFileHandle(FILE *fh, bool tranfer_ownership) {
86944d93782SGreg Clayton   if (m_input_file_sp)
87044d93782SGreg Clayton     m_input_file_sp->GetFile().SetStream(fh, tranfer_ownership);
87144d93782SGreg Clayton   else
8722f3df613SZachary Turner     m_input_file_sp = std::make_shared<StreamFile>(fh, tranfer_ownership);
87344d93782SGreg Clayton 
87444d93782SGreg Clayton   File &in_file = m_input_file_sp->GetFile();
875df370550SEugene Zelenko   if (!in_file.IsValid())
87651b1e2d2SGreg Clayton     in_file.SetStream(stdin, true);
87730fdc8d8SChris Lattner 
87805097246SAdrian Prantl   // Save away the terminal state if that is relevant, so that we can restore
87905097246SAdrian Prantl   // it in RestoreInputState.
880c5917d9aSJim Ingham   SaveInputTerminalState();
88130fdc8d8SChris Lattner }
88230fdc8d8SChris Lattner 
883b9c1b51eSKate Stone void Debugger::SetOutputFileHandle(FILE *fh, bool tranfer_ownership) {
88444d93782SGreg Clayton   if (m_output_file_sp)
88544d93782SGreg Clayton     m_output_file_sp->GetFile().SetStream(fh, tranfer_ownership);
88644d93782SGreg Clayton   else
8872f3df613SZachary Turner     m_output_file_sp = std::make_shared<StreamFile>(fh, tranfer_ownership);
88844d93782SGreg Clayton 
88944d93782SGreg Clayton   File &out_file = m_output_file_sp->GetFile();
890df370550SEugene Zelenko   if (!out_file.IsValid())
89151b1e2d2SGreg Clayton     out_file.SetStream(stdout, false);
8922f88aadfSCaroline Tice 
89305097246SAdrian Prantl   // do not create the ScriptInterpreter just for setting the output file
89405097246SAdrian Prantl   // handle as the constructor will know how to do the right thing on its own
895b588726eSEnrico Granata   const bool can_create = false;
896b9c1b51eSKate Stone   ScriptInterpreter *script_interpreter =
897b9c1b51eSKate Stone       GetCommandInterpreter().GetScriptInterpreter(can_create);
898b588726eSEnrico Granata   if (script_interpreter)
899b588726eSEnrico Granata     script_interpreter->ResetOutputFileHandle(fh);
90030fdc8d8SChris Lattner }
90130fdc8d8SChris Lattner 
902b9c1b51eSKate Stone void Debugger::SetErrorFileHandle(FILE *fh, bool tranfer_ownership) {
90344d93782SGreg Clayton   if (m_error_file_sp)
90444d93782SGreg Clayton     m_error_file_sp->GetFile().SetStream(fh, tranfer_ownership);
90544d93782SGreg Clayton   else
9062f3df613SZachary Turner     m_error_file_sp = std::make_shared<StreamFile>(fh, tranfer_ownership);
90744d93782SGreg Clayton 
90844d93782SGreg Clayton   File &err_file = m_error_file_sp->GetFile();
909df370550SEugene Zelenko   if (!err_file.IsValid())
91051b1e2d2SGreg Clayton     err_file.SetStream(stderr, false);
91130fdc8d8SChris Lattner }
91230fdc8d8SChris Lattner 
913b9c1b51eSKate Stone void Debugger::SaveInputTerminalState() {
914b9c1b51eSKate Stone   if (m_input_file_sp) {
91544d93782SGreg Clayton     File &in_file = m_input_file_sp->GetFile();
916c5917d9aSJim Ingham     if (in_file.GetDescriptor() != File::kInvalidDescriptor)
917c5917d9aSJim Ingham       m_terminal_state.Save(in_file.GetDescriptor(), true);
918c5917d9aSJim Ingham   }
91944d93782SGreg Clayton }
920c5917d9aSJim Ingham 
921b9c1b51eSKate Stone void Debugger::RestoreInputTerminalState() { m_terminal_state.Restore(); }
922c5917d9aSJim Ingham 
923b9c1b51eSKate Stone ExecutionContext Debugger::GetSelectedExecutionContext() {
92430fdc8d8SChris Lattner   ExecutionContext exe_ctx;
925c14ee32dSGreg Clayton   TargetSP target_sp(GetSelectedTarget());
926c14ee32dSGreg Clayton   exe_ctx.SetTargetSP(target_sp);
92730fdc8d8SChris Lattner 
928b9c1b51eSKate Stone   if (target_sp) {
929c14ee32dSGreg Clayton     ProcessSP process_sp(target_sp->GetProcessSP());
930c14ee32dSGreg Clayton     exe_ctx.SetProcessSP(process_sp);
931b9c1b51eSKate Stone     if (process_sp && !process_sp->IsRunning()) {
932c14ee32dSGreg Clayton       ThreadSP thread_sp(process_sp->GetThreadList().GetSelectedThread());
933b9c1b51eSKate Stone       if (thread_sp) {
934c14ee32dSGreg Clayton         exe_ctx.SetThreadSP(thread_sp);
935c14ee32dSGreg Clayton         exe_ctx.SetFrameSP(thread_sp->GetSelectedFrame());
936df370550SEugene Zelenko         if (exe_ctx.GetFramePtr() == nullptr)
937c14ee32dSGreg Clayton           exe_ctx.SetFrameSP(thread_sp->GetStackFrameAtIndex(0));
93830fdc8d8SChris Lattner       }
93930fdc8d8SChris Lattner     }
94030fdc8d8SChris Lattner   }
94130fdc8d8SChris Lattner   return exe_ctx;
94230fdc8d8SChris Lattner }
94330fdc8d8SChris Lattner 
944b9c1b51eSKate Stone void Debugger::DispatchInputInterrupt() {
94516ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex());
94644d93782SGreg Clayton   IOHandlerSP reader_sp(m_input_reader_stack.Top());
947efed6131SCaroline Tice   if (reader_sp)
94844d93782SGreg Clayton     reader_sp->Interrupt();
949efed6131SCaroline Tice }
950efed6131SCaroline Tice 
951b9c1b51eSKate Stone void Debugger::DispatchInputEndOfFile() {
95216ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex());
95344d93782SGreg Clayton   IOHandlerSP reader_sp(m_input_reader_stack.Top());
954efed6131SCaroline Tice   if (reader_sp)
95544d93782SGreg Clayton     reader_sp->GotEOF();
956efed6131SCaroline Tice }
957efed6131SCaroline Tice 
958b9c1b51eSKate Stone void Debugger::ClearIOHandlers() {
959b9c1b51eSKate Stone   // The bottom input reader should be the main debugger input reader.  We do
960b9c1b51eSKate Stone   // not want to close that one here.
96116ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex());
962b9c1b51eSKate Stone   while (m_input_reader_stack.GetSize() > 1) {
96344d93782SGreg Clayton     IOHandlerSP reader_sp(m_input_reader_stack.Top());
9643d6086f6SCaroline Tice     if (reader_sp)
9654446487dSPavel Labath       PopIOHandler(reader_sp);
9663d6086f6SCaroline Tice   }
9673d6086f6SCaroline Tice }
9683d6086f6SCaroline Tice 
969b9c1b51eSKate Stone void Debugger::ExecuteIOHandlers() {
970b9c1b51eSKate Stone   while (true) {
97144d93782SGreg Clayton     IOHandlerSP reader_sp(m_input_reader_stack.Top());
97230fdc8d8SChris Lattner     if (!reader_sp)
97330fdc8d8SChris Lattner       break;
97430fdc8d8SChris Lattner 
97544d93782SGreg Clayton     reader_sp->Run();
97644d93782SGreg Clayton 
97744d93782SGreg Clayton     // Remove all input readers that are done from the top of the stack
978b9c1b51eSKate Stone     while (true) {
97944d93782SGreg Clayton       IOHandlerSP top_reader_sp = m_input_reader_stack.Top();
98044d93782SGreg Clayton       if (top_reader_sp && top_reader_sp->GetIsDone())
9814446487dSPavel Labath         PopIOHandler(top_reader_sp);
98230fdc8d8SChris Lattner       else
98330fdc8d8SChris Lattner         break;
98430fdc8d8SChris Lattner     }
98530fdc8d8SChris Lattner   }
98644d93782SGreg Clayton   ClearIOHandlers();
98744d93782SGreg Clayton }
98830fdc8d8SChris Lattner 
989b9c1b51eSKate Stone bool Debugger::IsTopIOHandler(const lldb::IOHandlerSP &reader_sp) {
99044d93782SGreg Clayton   return m_input_reader_stack.IsTop(reader_sp);
99144d93782SGreg Clayton }
99230fdc8d8SChris Lattner 
993b9c1b51eSKate Stone bool Debugger::CheckTopIOHandlerTypes(IOHandler::Type top_type,
994b9c1b51eSKate Stone                                       IOHandler::Type second_top_type) {
9956681041dSSean Callanan   return m_input_reader_stack.CheckTopIOHandlerTypes(top_type, second_top_type);
9966681041dSSean Callanan }
9976681041dSSean Callanan 
998b9c1b51eSKate Stone void Debugger::PrintAsync(const char *s, size_t len, bool is_stdout) {
9994446487dSPavel Labath   lldb::StreamFileSP stream = is_stdout ? GetOutputFile() : GetErrorFile();
10004446487dSPavel Labath   m_input_reader_stack.PrintAsync(stream.get(), s, len);
10014446487dSPavel Labath }
100244d93782SGreg Clayton 
1003b9c1b51eSKate Stone ConstString Debugger::GetTopIOHandlerControlSequence(char ch) {
100444d93782SGreg Clayton   return m_input_reader_stack.GetTopIOHandlerControlSequence(ch);
100530fdc8d8SChris Lattner }
100630fdc8d8SChris Lattner 
1007b9c1b51eSKate Stone const char *Debugger::GetIOHandlerCommandPrefix() {
1008a487aa4cSKate Stone   return m_input_reader_stack.GetTopIOHandlerCommandPrefix();
1009a487aa4cSKate Stone }
1010a487aa4cSKate Stone 
1011b9c1b51eSKate Stone const char *Debugger::GetIOHandlerHelpPrologue() {
1012a487aa4cSKate Stone   return m_input_reader_stack.GetTopIOHandlerHelpPrologue();
1013a487aa4cSKate Stone }
1014a487aa4cSKate Stone 
1015b9c1b51eSKate Stone void Debugger::RunIOHandler(const IOHandlerSP &reader_sp) {
101644d93782SGreg Clayton   PushIOHandler(reader_sp);
1017577508dfSGreg Clayton 
1018577508dfSGreg Clayton   IOHandlerSP top_reader_sp = reader_sp;
1019b9c1b51eSKate Stone   while (top_reader_sp) {
1020577508dfSGreg Clayton     top_reader_sp->Run();
1021577508dfSGreg Clayton 
1022b9c1b51eSKate Stone     if (top_reader_sp.get() == reader_sp.get()) {
1023577508dfSGreg Clayton       if (PopIOHandler(reader_sp))
1024577508dfSGreg Clayton         break;
1025577508dfSGreg Clayton     }
1026577508dfSGreg Clayton 
1027b9c1b51eSKate Stone     while (true) {
1028577508dfSGreg Clayton       top_reader_sp = m_input_reader_stack.Top();
1029577508dfSGreg Clayton       if (top_reader_sp && top_reader_sp->GetIsDone())
10304446487dSPavel Labath         PopIOHandler(top_reader_sp);
1031577508dfSGreg Clayton       else
1032577508dfSGreg Clayton         break;
1033577508dfSGreg Clayton     }
1034577508dfSGreg Clayton   }
103544d93782SGreg Clayton }
103644d93782SGreg Clayton 
1037b9c1b51eSKate Stone void Debugger::AdoptTopIOHandlerFilesIfInvalid(StreamFileSP &in,
1038b9c1b51eSKate Stone                                                StreamFileSP &out,
1039b9c1b51eSKate Stone                                                StreamFileSP &err) {
104005097246SAdrian Prantl   // Before an IOHandler runs, it must have in/out/err streams. This function
104105097246SAdrian Prantl   // is called when one ore more of the streams are nullptr. We use the top
104205097246SAdrian Prantl   // input reader's in/out/err streams, or fall back to the debugger file
104305097246SAdrian Prantl   // handles, or we fall back onto stdin/stdout/stderr as a last resort.
104444d93782SGreg Clayton 
104516ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex());
104644d93782SGreg Clayton   IOHandlerSP top_reader_sp(m_input_reader_stack.Top());
104744d93782SGreg Clayton   // If no STDIN has been set, then set it appropriately
1048b9c1b51eSKate Stone   if (!in) {
104944d93782SGreg Clayton     if (top_reader_sp)
105044d93782SGreg Clayton       in = top_reader_sp->GetInputStreamFile();
105144d93782SGreg Clayton     else
105244d93782SGreg Clayton       in = GetInputFile();
105344d93782SGreg Clayton 
105444d93782SGreg Clayton     // If there is nothing, use stdin
105544d93782SGreg Clayton     if (!in)
10562f3df613SZachary Turner       in = std::make_shared<StreamFile>(stdin, false);
105744d93782SGreg Clayton   }
105844d93782SGreg Clayton   // If no STDOUT has been set, then set it appropriately
1059b9c1b51eSKate Stone   if (!out) {
106044d93782SGreg Clayton     if (top_reader_sp)
106144d93782SGreg Clayton       out = top_reader_sp->GetOutputStreamFile();
106244d93782SGreg Clayton     else
106344d93782SGreg Clayton       out = GetOutputFile();
106444d93782SGreg Clayton 
106544d93782SGreg Clayton     // If there is nothing, use stdout
106644d93782SGreg Clayton     if (!out)
10672f3df613SZachary Turner       out = std::make_shared<StreamFile>(stdout, false);
106844d93782SGreg Clayton   }
106944d93782SGreg Clayton   // If no STDERR has been set, then set it appropriately
1070b9c1b51eSKate Stone   if (!err) {
107144d93782SGreg Clayton     if (top_reader_sp)
107244d93782SGreg Clayton       err = top_reader_sp->GetErrorStreamFile();
107344d93782SGreg Clayton     else
107444d93782SGreg Clayton       err = GetErrorFile();
107544d93782SGreg Clayton 
107644d93782SGreg Clayton     // If there is nothing, use stderr
107744d93782SGreg Clayton     if (!err)
10782f3df613SZachary Turner       err = std::make_shared<StreamFile>(stdout, false);
107944d93782SGreg Clayton   }
108044d93782SGreg Clayton }
108144d93782SGreg Clayton 
1082c01783a8SRaphael Isemann void Debugger::PushIOHandler(const IOHandlerSP &reader_sp,
1083c01783a8SRaphael Isemann                              bool cancel_top_handler) {
108430fdc8d8SChris Lattner   if (!reader_sp)
108530fdc8d8SChris Lattner     return;
1086b44880caSCaroline Tice 
108716ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex());
10884446487dSPavel Labath 
10894446487dSPavel Labath   // Get the current top input reader...
109044d93782SGreg Clayton   IOHandlerSP top_reader_sp(m_input_reader_stack.Top());
1091b44880caSCaroline Tice 
1092b4874f1aSGreg Clayton   // Don't push the same IO handler twice...
10934446487dSPavel Labath   if (reader_sp == top_reader_sp)
10944446487dSPavel Labath     return;
10954446487dSPavel Labath 
109644d93782SGreg Clayton   // Push our new input reader
1097d5a0a01bSCaroline Tice   m_input_reader_stack.Push(reader_sp);
10984446487dSPavel Labath   reader_sp->Activate();
109944d93782SGreg Clayton 
110005097246SAdrian Prantl   // Interrupt the top input reader to it will exit its Run() function and let
110105097246SAdrian Prantl   // this new input reader take over
1102b9c1b51eSKate Stone   if (top_reader_sp) {
110344d93782SGreg Clayton     top_reader_sp->Deactivate();
1104c01783a8SRaphael Isemann     if (cancel_top_handler)
11054446487dSPavel Labath       top_reader_sp->Cancel();
110630fdc8d8SChris Lattner   }
1107b4874f1aSGreg Clayton }
110830fdc8d8SChris Lattner 
1109b9c1b51eSKate Stone bool Debugger::PopIOHandler(const IOHandlerSP &pop_reader_sp) {
11104446487dSPavel Labath   if (!pop_reader_sp)
11114446487dSPavel Labath     return false;
111230fdc8d8SChris Lattner 
111316ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex());
111444d93782SGreg Clayton 
111505097246SAdrian Prantl   // The reader on the stop of the stack is done, so let the next read on the
111605097246SAdrian Prantl   // stack refresh its prompt and if there is one...
11174446487dSPavel Labath   if (m_input_reader_stack.IsEmpty())
11184446487dSPavel Labath     return false;
11194446487dSPavel Labath 
112044d93782SGreg Clayton   IOHandlerSP reader_sp(m_input_reader_stack.Top());
112130fdc8d8SChris Lattner 
11224446487dSPavel Labath   if (pop_reader_sp != reader_sp)
11234446487dSPavel Labath     return false;
11244446487dSPavel Labath 
112544d93782SGreg Clayton   reader_sp->Deactivate();
1126b4874f1aSGreg Clayton   reader_sp->Cancel();
1127d5a0a01bSCaroline Tice   m_input_reader_stack.Pop();
112830fdc8d8SChris Lattner 
1129d5a0a01bSCaroline Tice   reader_sp = m_input_reader_stack.Top();
113030fdc8d8SChris Lattner   if (reader_sp)
113144d93782SGreg Clayton     reader_sp->Activate();
113244d93782SGreg Clayton 
113344d93782SGreg Clayton   return true;
113430fdc8d8SChris Lattner }
11356611103cSGreg Clayton 
1136b9c1b51eSKate Stone StreamSP Debugger::GetAsyncOutputStream() {
11372f3df613SZachary Turner   return std::make_shared<StreamAsynchronousIO>(*this, true);
11385b52f0c7SJim Ingham }
11395b52f0c7SJim Ingham 
1140b9c1b51eSKate Stone StreamSP Debugger::GetAsyncErrorStream() {
11412f3df613SZachary Turner   return std::make_shared<StreamAsynchronousIO>(*this, false);
11425b52f0c7SJim Ingham }
11435b52f0c7SJim Ingham 
1144b9c1b51eSKate Stone size_t Debugger::GetNumDebuggers() {
1145b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
11466c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
11476c42e063SGreg Clayton     return g_debugger_list_ptr->size();
1148061858ceSEnrico Granata   }
1149c15f55e2SGreg Clayton   return 0;
1150c15f55e2SGreg Clayton }
1151061858ceSEnrico Granata 
1152b9c1b51eSKate Stone lldb::DebuggerSP Debugger::GetDebuggerAtIndex(size_t index) {
1153061858ceSEnrico Granata   DebuggerSP debugger_sp;
1154061858ceSEnrico Granata 
1155b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
11566c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
11576c42e063SGreg Clayton     if (index < g_debugger_list_ptr->size())
11586c42e063SGreg Clayton       debugger_sp = g_debugger_list_ptr->at(index);
1159c15f55e2SGreg Clayton   }
1160061858ceSEnrico Granata 
1161061858ceSEnrico Granata   return debugger_sp;
1162061858ceSEnrico Granata }
1163061858ceSEnrico Granata 
1164b9c1b51eSKate Stone DebuggerSP Debugger::FindDebuggerWithID(lldb::user_id_t id) {
11654d122c40SGreg Clayton   DebuggerSP debugger_sp;
1166ebc1bb27SCaroline Tice 
1167b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
11686c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
11696c42e063SGreg Clayton     DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
1170b9c1b51eSKate Stone     for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
1171b9c1b51eSKate Stone       if ((*pos)->GetID() == id) {
1172ebc1bb27SCaroline Tice         debugger_sp = *pos;
1173ebc1bb27SCaroline Tice         break;
1174ebc1bb27SCaroline Tice       }
1175ebc1bb27SCaroline Tice     }
1176c15f55e2SGreg Clayton   }
1177ebc1bb27SCaroline Tice   return debugger_sp;
1178ebc1bb27SCaroline Tice }
11793df9a8dfSCaroline Tice 
1180b9c1b51eSKate Stone bool Debugger::FormatDisassemblerAddress(const FormatEntity::Entry *format,
1181aff1b357SJason Molenda                                          const SymbolContext *sc,
1182aff1b357SJason Molenda                                          const SymbolContext *prev_sc,
1183aff1b357SJason Molenda                                          const ExecutionContext *exe_ctx,
1184b9c1b51eSKate Stone                                          const Address *addr, Stream &s) {
1185554f68d3SGreg Clayton   FormatEntity::Entry format_entry;
1186554f68d3SGreg Clayton 
1187b9c1b51eSKate Stone   if (format == nullptr) {
1188df370550SEugene Zelenko     if (exe_ctx != nullptr && exe_ctx->HasTargetScope())
1189aff1b357SJason Molenda       format = exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat();
1190b9c1b51eSKate Stone     if (format == nullptr) {
1191554f68d3SGreg Clayton       FormatEntity::Parse("${addr}: ", format_entry);
1192554f68d3SGreg Clayton       format = &format_entry;
1193554f68d3SGreg Clayton     }
1194aff1b357SJason Molenda   }
1195aff1b357SJason Molenda   bool function_changed = false;
1196aff1b357SJason Molenda   bool initial_function = false;
1197b9c1b51eSKate Stone   if (prev_sc && (prev_sc->function || prev_sc->symbol)) {
1198b9c1b51eSKate Stone     if (sc && (sc->function || sc->symbol)) {
1199b9c1b51eSKate Stone       if (prev_sc->symbol && sc->symbol) {
1200b9c1b51eSKate Stone         if (!sc->symbol->Compare(prev_sc->symbol->GetName(),
1201b9c1b51eSKate Stone                                  prev_sc->symbol->GetType())) {
1202aff1b357SJason Molenda           function_changed = true;
1203aff1b357SJason Molenda         }
1204b9c1b51eSKate Stone       } else if (prev_sc->function && sc->function) {
1205b9c1b51eSKate Stone         if (prev_sc->function->GetMangled() != sc->function->GetMangled()) {
1206aff1b357SJason Molenda           function_changed = true;
1207aff1b357SJason Molenda         }
1208aff1b357SJason Molenda       }
1209aff1b357SJason Molenda     }
1210aff1b357SJason Molenda   }
121105097246SAdrian Prantl   // The first context on a list of instructions will have a prev_sc that has
121205097246SAdrian Prantl   // no Function or Symbol -- if SymbolContext had an IsValid() method, it
1213aff1b357SJason Molenda   // would return false.  But we do get a prev_sc pointer.
1214b9c1b51eSKate Stone   if ((sc && (sc->function || sc->symbol)) && prev_sc &&
1215b9c1b51eSKate Stone       (prev_sc->function == nullptr && prev_sc->symbol == nullptr)) {
1216aff1b357SJason Molenda     initial_function = true;
1217aff1b357SJason Molenda   }
1218b9c1b51eSKate Stone   return FormatEntity::Format(*format, s, sc, exe_ctx, addr, nullptr,
1219b9c1b51eSKate Stone                               function_changed, initial_function);
1220aff1b357SJason Molenda }
1221aff1b357SJason Molenda 
1222b9c1b51eSKate Stone void Debugger::SetLoggingCallback(lldb::LogOutputCallback log_callback,
1223b9c1b51eSKate Stone                                   void *baton) {
12244f02b22dSJim Ingham   // For simplicity's sake, I am not going to deal with how to close down any
12254f02b22dSJim Ingham   // open logging streams, I just redirect everything from here on out to the
12264f02b22dSJim Ingham   // callback.
12272f3df613SZachary Turner   m_log_callback_stream_sp =
12282f3df613SZachary Turner       std::make_shared<StreamCallback>(log_callback, baton);
1229228063cdSJim Ingham }
1230228063cdSJim Ingham 
12315e336903SPavel Labath bool Debugger::EnableLog(llvm::StringRef channel,
12325e336903SPavel Labath                          llvm::ArrayRef<const char *> categories,
12335e336903SPavel Labath                          llvm::StringRef log_file, uint32_t log_options,
1234775588c0SPavel Labath                          llvm::raw_ostream &error_stream) {
12355fae71c5SPavel Labath   const bool should_close = true;
12365fae71c5SPavel Labath   const bool unbuffered = true;
12375fae71c5SPavel Labath 
12385fae71c5SPavel Labath   std::shared_ptr<llvm::raw_ostream> log_stream_sp;
1239b9c1b51eSKate Stone   if (m_log_callback_stream_sp) {
1240228063cdSJim Ingham     log_stream_sp = m_log_callback_stream_sp;
1241228063cdSJim Ingham     // For now when using the callback mode you always get thread & timestamp.
1242b9c1b51eSKate Stone     log_options |=
1243b9c1b51eSKate Stone         LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_THREAD_NAME;
12445e336903SPavel Labath   } else if (log_file.empty()) {
12455fae71c5SPavel Labath     log_stream_sp = std::make_shared<llvm::raw_fd_ostream>(
12465fae71c5SPavel Labath         GetOutputFile()->GetFile().GetDescriptor(), !should_close, unbuffered);
1247b9c1b51eSKate Stone   } else {
12485fae71c5SPavel Labath     auto pos = m_log_streams.find(log_file);
1249c1b2ccfdSGreg Clayton     if (pos != m_log_streams.end())
1250c1b2ccfdSGreg Clayton       log_stream_sp = pos->second.lock();
1251b9c1b51eSKate Stone     if (!log_stream_sp) {
12525fae71c5SPavel Labath       llvm::sys::fs::OpenFlags flags = llvm::sys::fs::F_Text;
12535fae71c5SPavel Labath       if (log_options & LLDB_LOG_OPTION_APPEND)
12545fae71c5SPavel Labath         flags |= llvm::sys::fs::F_Append;
12555fae71c5SPavel Labath       int FD;
12561f67a3cbSZachary Turner       if (std::error_code ec = llvm::sys::fs::openFileForWrite(
12571f67a3cbSZachary Turner               log_file, FD, llvm::sys::fs::CD_CreateAlways, flags)) {
1258775588c0SPavel Labath         error_stream << "Unable to open log file: " << ec.message();
12595fae71c5SPavel Labath         return false;
12605fae71c5SPavel Labath       }
12612f3df613SZachary Turner       log_stream_sp =
12622f3df613SZachary Turner           std::make_shared<llvm::raw_fd_ostream>(FD, should_close, unbuffered);
1263228063cdSJim Ingham       m_log_streams[log_file] = log_stream_sp;
1264228063cdSJim Ingham     }
1265228063cdSJim Ingham   }
1266df370550SEugene Zelenko   assert(log_stream_sp);
1267228063cdSJim Ingham 
1268228063cdSJim Ingham   if (log_options == 0)
1269b9c1b51eSKate Stone     log_options =
1270b9c1b51eSKate Stone         LLDB_LOG_OPTION_PREPEND_THREAD_NAME | LLDB_LOG_OPTION_THREADSAFE;
1271228063cdSJim Ingham 
1272b9c1b51eSKate Stone   return Log::EnableLogChannel(log_stream_sp, log_options, channel, categories,
1273b9c1b51eSKate Stone                                error_stream);
1274228063cdSJim Ingham }
1275228063cdSJim Ingham 
1276b9c1b51eSKate Stone SourceManager &Debugger::GetSourceManager() {
1277df370550SEugene Zelenko   if (!m_source_manager_ap)
12782f3df613SZachary Turner     m_source_manager_ap = llvm::make_unique<SourceManager>(shared_from_this());
12799585fbfcSGreg Clayton   return *m_source_manager_ap;
12809585fbfcSGreg Clayton }
12819585fbfcSGreg Clayton 
128244d93782SGreg Clayton // This function handles events that were broadcast by the process.
1283b9c1b51eSKate Stone void Debugger::HandleBreakpointEvent(const EventSP &event_sp) {
128444d93782SGreg Clayton   using namespace lldb;
1285b9c1b51eSKate Stone   const uint32_t event_type =
1286b9c1b51eSKate Stone       Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent(
1287b9c1b51eSKate Stone           event_sp);
128844d93782SGreg Clayton 
128944d93782SGreg Clayton   //    if (event_type & eBreakpointEventTypeAdded
129044d93782SGreg Clayton   //        || event_type & eBreakpointEventTypeRemoved
129144d93782SGreg Clayton   //        || event_type & eBreakpointEventTypeEnabled
129244d93782SGreg Clayton   //        || event_type & eBreakpointEventTypeDisabled
129344d93782SGreg Clayton   //        || event_type & eBreakpointEventTypeCommandChanged
129444d93782SGreg Clayton   //        || event_type & eBreakpointEventTypeConditionChanged
129544d93782SGreg Clayton   //        || event_type & eBreakpointEventTypeIgnoreChanged
129644d93782SGreg Clayton   //        || event_type & eBreakpointEventTypeLocationsResolved)
129744d93782SGreg Clayton   //    {
1298b9c1b51eSKate Stone   //        // Don't do anything about these events, since the breakpoint
1299b9c1b51eSKate Stone   //        commands already echo these actions.
130044d93782SGreg Clayton   //    }
130144d93782SGreg Clayton   //
1302b9c1b51eSKate Stone   if (event_type & eBreakpointEventTypeLocationsAdded) {
1303b9c1b51eSKate Stone     uint32_t num_new_locations =
1304b9c1b51eSKate Stone         Breakpoint::BreakpointEventData::GetNumBreakpointLocationsFromEvent(
1305b9c1b51eSKate Stone             event_sp);
1306b9c1b51eSKate Stone     if (num_new_locations > 0) {
1307b9c1b51eSKate Stone       BreakpointSP breakpoint =
1308b9c1b51eSKate Stone           Breakpoint::BreakpointEventData::GetBreakpointFromEvent(event_sp);
13094446487dSPavel Labath       StreamSP output_sp(GetAsyncOutputStream());
1310b9c1b51eSKate Stone       if (output_sp) {
131144d93782SGreg Clayton         output_sp->Printf("%d location%s added to breakpoint %d\n",
1312b9c1b51eSKate Stone                           num_new_locations, num_new_locations == 1 ? "" : "s",
131344d93782SGreg Clayton                           breakpoint->GetID());
13144446487dSPavel Labath         output_sp->Flush();
131544d93782SGreg Clayton       }
131644d93782SGreg Clayton     }
131744d93782SGreg Clayton   }
131844d93782SGreg Clayton   //    else if (event_type & eBreakpointEventTypeLocationsRemoved)
131944d93782SGreg Clayton   //    {
1320b9c1b51eSKate Stone   //        // These locations just get disabled, not sure it is worth spamming
1321b9c1b51eSKate Stone   //        folks about this on the command line.
132244d93782SGreg Clayton   //    }
132344d93782SGreg Clayton   //    else if (event_type & eBreakpointEventTypeLocationsResolved)
132444d93782SGreg Clayton   //    {
1325b9c1b51eSKate Stone   //        // This might be an interesting thing to note, but I'm going to
1326b9c1b51eSKate Stone   //        leave it quiet for now, it just looked noisy.
132744d93782SGreg Clayton   //    }
132844d93782SGreg Clayton }
132944d93782SGreg Clayton 
1330b9c1b51eSKate Stone size_t Debugger::GetProcessSTDOUT(Process *process, Stream *stream) {
133144d93782SGreg Clayton   size_t total_bytes = 0;
1332df370550SEugene Zelenko   if (stream == nullptr)
133344d93782SGreg Clayton     stream = GetOutputFile().get();
133444d93782SGreg Clayton 
1335b9c1b51eSKate Stone   if (stream) {
1336b9c1b51eSKate Stone     //  The process has stuff waiting for stdout; get it and write it out to the
1337b9c1b51eSKate Stone     //  appropriate place.
1338b9c1b51eSKate Stone     if (process == nullptr) {
133944d93782SGreg Clayton       TargetSP target_sp = GetTargetList().GetSelectedTarget();
134044d93782SGreg Clayton       if (target_sp)
134144d93782SGreg Clayton         process = target_sp->GetProcessSP().get();
134244d93782SGreg Clayton     }
1343b9c1b51eSKate Stone     if (process) {
134497206d57SZachary Turner       Status error;
134544d93782SGreg Clayton       size_t len;
134644d93782SGreg Clayton       char stdio_buffer[1024];
1347b9c1b51eSKate Stone       while ((len = process->GetSTDOUT(stdio_buffer, sizeof(stdio_buffer),
1348b9c1b51eSKate Stone                                        error)) > 0) {
134944d93782SGreg Clayton         stream->Write(stdio_buffer, len);
135044d93782SGreg Clayton         total_bytes += len;
135144d93782SGreg Clayton       }
135244d93782SGreg Clayton     }
135344d93782SGreg Clayton     stream->Flush();
135444d93782SGreg Clayton   }
135544d93782SGreg Clayton   return total_bytes;
135644d93782SGreg Clayton }
135744d93782SGreg Clayton 
1358b9c1b51eSKate Stone size_t Debugger::GetProcessSTDERR(Process *process, Stream *stream) {
135944d93782SGreg Clayton   size_t total_bytes = 0;
1360df370550SEugene Zelenko   if (stream == nullptr)
136144d93782SGreg Clayton     stream = GetOutputFile().get();
136244d93782SGreg Clayton 
1363b9c1b51eSKate Stone   if (stream) {
1364b9c1b51eSKate Stone     //  The process has stuff waiting for stderr; get it and write it out to the
1365b9c1b51eSKate Stone     //  appropriate place.
1366b9c1b51eSKate Stone     if (process == nullptr) {
136744d93782SGreg Clayton       TargetSP target_sp = GetTargetList().GetSelectedTarget();
136844d93782SGreg Clayton       if (target_sp)
136944d93782SGreg Clayton         process = target_sp->GetProcessSP().get();
137044d93782SGreg Clayton     }
1371b9c1b51eSKate Stone     if (process) {
137297206d57SZachary Turner       Status error;
137344d93782SGreg Clayton       size_t len;
137444d93782SGreg Clayton       char stdio_buffer[1024];
1375b9c1b51eSKate Stone       while ((len = process->GetSTDERR(stdio_buffer, sizeof(stdio_buffer),
1376b9c1b51eSKate Stone                                        error)) > 0) {
137744d93782SGreg Clayton         stream->Write(stdio_buffer, len);
137844d93782SGreg Clayton         total_bytes += len;
137944d93782SGreg Clayton       }
138044d93782SGreg Clayton     }
138144d93782SGreg Clayton     stream->Flush();
138244d93782SGreg Clayton   }
138344d93782SGreg Clayton   return total_bytes;
138444d93782SGreg Clayton }
138544d93782SGreg Clayton 
138644d93782SGreg Clayton // This function handles events that were broadcast by the process.
1387b9c1b51eSKate Stone void Debugger::HandleProcessEvent(const EventSP &event_sp) {
138844d93782SGreg Clayton   using namespace lldb;
138944d93782SGreg Clayton   const uint32_t event_type = event_sp->GetType();
1390b9c1b51eSKate Stone   ProcessSP process_sp =
1391b9c1b51eSKate Stone       (event_type == Process::eBroadcastBitStructuredData)
139275930019STodd Fiala           ? EventDataStructuredData::GetProcessFromEvent(event_sp.get())
139375930019STodd Fiala           : Process::ProcessEventData::GetProcessFromEvent(event_sp.get());
139444d93782SGreg Clayton 
13954446487dSPavel Labath   StreamSP output_stream_sp = GetAsyncOutputStream();
13964446487dSPavel Labath   StreamSP error_stream_sp = GetAsyncErrorStream();
139744d93782SGreg Clayton   const bool gui_enabled = IsForwardingEvents();
139844d93782SGreg Clayton 
1399b9c1b51eSKate Stone   if (!gui_enabled) {
1400b4874f1aSGreg Clayton     bool pop_process_io_handler = false;
140144d93782SGreg Clayton     assert(process_sp);
140244d93782SGreg Clayton 
14034446487dSPavel Labath     bool state_is_stopped = false;
1404b9c1b51eSKate Stone     const bool got_state_changed =
1405b9c1b51eSKate Stone         (event_type & Process::eBroadcastBitStateChanged) != 0;
14064446487dSPavel Labath     const bool got_stdout = (event_type & Process::eBroadcastBitSTDOUT) != 0;
14074446487dSPavel Labath     const bool got_stderr = (event_type & Process::eBroadcastBitSTDERR) != 0;
1408b9c1b51eSKate Stone     const bool got_structured_data =
1409b9c1b51eSKate Stone         (event_type & Process::eBroadcastBitStructuredData) != 0;
141075930019STodd Fiala 
1411b9c1b51eSKate Stone     if (got_state_changed) {
1412b9c1b51eSKate Stone       StateType event_state =
1413b9c1b51eSKate Stone           Process::ProcessEventData::GetStateFromEvent(event_sp.get());
14144446487dSPavel Labath       state_is_stopped = StateIsStoppedState(event_state, false);
141544d93782SGreg Clayton     }
1416b4874f1aSGreg Clayton 
14174446487dSPavel Labath     // Display running state changes first before any STDIO
1418b9c1b51eSKate Stone     if (got_state_changed && !state_is_stopped) {
1419b9c1b51eSKate Stone       Process::HandleProcessStateChangedEvent(event_sp, output_stream_sp.get(),
1420b9c1b51eSKate Stone                                               pop_process_io_handler);
142144d93782SGreg Clayton     }
1422b4874f1aSGreg Clayton 
14234446487dSPavel Labath     // Now display and STDOUT
1424b9c1b51eSKate Stone     if (got_stdout || got_state_changed) {
14254446487dSPavel Labath       GetProcessSTDOUT(process_sp.get(), output_stream_sp.get());
142644d93782SGreg Clayton     }
1427b4874f1aSGreg Clayton 
14284446487dSPavel Labath     // Now display and STDERR
1429b9c1b51eSKate Stone     if (got_stderr || got_state_changed) {
14304446487dSPavel Labath       GetProcessSTDERR(process_sp.get(), error_stream_sp.get());
1431b4874f1aSGreg Clayton     }
1432b4874f1aSGreg Clayton 
143375930019STodd Fiala     // Give structured data events an opportunity to display.
1434b9c1b51eSKate Stone     if (got_structured_data) {
143575930019STodd Fiala       StructuredDataPluginSP plugin_sp =
143675930019STodd Fiala           EventDataStructuredData::GetPluginFromEvent(event_sp.get());
1437b9c1b51eSKate Stone       if (plugin_sp) {
143875930019STodd Fiala         auto structured_data_sp =
143975930019STodd Fiala             EventDataStructuredData::GetObjectFromEvent(event_sp.get());
1440b9c1b51eSKate Stone         if (output_stream_sp) {
144175930019STodd Fiala           StreamString content_stream;
144297206d57SZachary Turner           Status error =
1443b9c1b51eSKate Stone               plugin_sp->GetDescription(structured_data_sp, content_stream);
1444b9c1b51eSKate Stone           if (error.Success()) {
1445b9c1b51eSKate Stone             if (!content_stream.GetString().empty()) {
144675930019STodd Fiala               // Add newline.
144775930019STodd Fiala               content_stream.PutChar('\n');
144875930019STodd Fiala               content_stream.Flush();
144975930019STodd Fiala 
145075930019STodd Fiala               // Print it.
1451771ef6d4SMalcolm Parsons               output_stream_sp->PutCString(content_stream.GetString());
145275930019STodd Fiala             }
1453b9c1b51eSKate Stone           } else {
145475930019STodd Fiala             error_stream_sp->Printf("Failed to print structured "
145575930019STodd Fiala                                     "data with plugin %s: %s",
1456b9c1b51eSKate Stone                                     plugin_sp->GetPluginName().AsCString(),
145775930019STodd Fiala                                     error.AsCString());
145875930019STodd Fiala           }
145975930019STodd Fiala         }
146075930019STodd Fiala       }
146175930019STodd Fiala     }
146275930019STodd Fiala 
14634446487dSPavel Labath     // Now display any stopped state changes after any STDIO
1464b9c1b51eSKate Stone     if (got_state_changed && state_is_stopped) {
1465b9c1b51eSKate Stone       Process::HandleProcessStateChangedEvent(event_sp, output_stream_sp.get(),
1466b9c1b51eSKate Stone                                               pop_process_io_handler);
146744d93782SGreg Clayton     }
146844d93782SGreg Clayton 
14694446487dSPavel Labath     output_stream_sp->Flush();
14704446487dSPavel Labath     error_stream_sp->Flush();
147144d93782SGreg Clayton 
1472b4874f1aSGreg Clayton     if (pop_process_io_handler)
1473b4874f1aSGreg Clayton       process_sp->PopProcessIOHandler();
1474b4874f1aSGreg Clayton   }
1475b4874f1aSGreg Clayton }
1476b4874f1aSGreg Clayton 
1477b9c1b51eSKate Stone void Debugger::HandleThreadEvent(const EventSP &event_sp) {
147805097246SAdrian Prantl   // At present the only thread event we handle is the Frame Changed event, and
147905097246SAdrian Prantl   // all we do for that is just reprint the thread status for that thread.
148044d93782SGreg Clayton   using namespace lldb;
148144d93782SGreg Clayton   const uint32_t event_type = event_sp->GetType();
14826a9767c7SJim Ingham   const bool stop_format = true;
148344d93782SGreg Clayton   if (event_type == Thread::eBroadcastBitStackChanged ||
1484b9c1b51eSKate Stone       event_type == Thread::eBroadcastBitThreadSelected) {
1485b9c1b51eSKate Stone     ThreadSP thread_sp(
1486b9c1b51eSKate Stone         Thread::ThreadEventData::GetThreadFromEvent(event_sp.get()));
1487b9c1b51eSKate Stone     if (thread_sp) {
14886a9767c7SJim Ingham       thread_sp->GetStatus(*GetAsyncOutputStream(), 0, 1, 1, stop_format);
148944d93782SGreg Clayton     }
149044d93782SGreg Clayton   }
149144d93782SGreg Clayton }
149244d93782SGreg Clayton 
1493b9c1b51eSKate Stone bool Debugger::IsForwardingEvents() { return (bool)m_forward_listener_sp; }
149444d93782SGreg Clayton 
1495b9c1b51eSKate Stone void Debugger::EnableForwardEvents(const ListenerSP &listener_sp) {
149644d93782SGreg Clayton   m_forward_listener_sp = listener_sp;
149744d93782SGreg Clayton }
149844d93782SGreg Clayton 
1499b9c1b51eSKate Stone void Debugger::CancelForwardEvents(const ListenerSP &listener_sp) {
150044d93782SGreg Clayton   m_forward_listener_sp.reset();
150144d93782SGreg Clayton }
150244d93782SGreg Clayton 
1503b9c1b51eSKate Stone void Debugger::DefaultEventHandler() {
1504583bbb1dSJim Ingham   ListenerSP listener_sp(GetListener());
150544d93782SGreg Clayton   ConstString broadcaster_class_target(Target::GetStaticBroadcasterClass());
150644d93782SGreg Clayton   ConstString broadcaster_class_process(Process::GetStaticBroadcasterClass());
150744d93782SGreg Clayton   ConstString broadcaster_class_thread(Thread::GetStaticBroadcasterClass());
150844d93782SGreg Clayton   BroadcastEventSpec target_event_spec(broadcaster_class_target,
150944d93782SGreg Clayton                                        Target::eBroadcastBitBreakpointChanged);
151044d93782SGreg Clayton 
1511b9c1b51eSKate Stone   BroadcastEventSpec process_event_spec(
1512b9c1b51eSKate Stone       broadcaster_class_process,
1513b9c1b51eSKate Stone       Process::eBroadcastBitStateChanged | Process::eBroadcastBitSTDOUT |
1514b9c1b51eSKate Stone           Process::eBroadcastBitSTDERR | Process::eBroadcastBitStructuredData);
151544d93782SGreg Clayton 
151644d93782SGreg Clayton   BroadcastEventSpec thread_event_spec(broadcaster_class_thread,
151744d93782SGreg Clayton                                        Thread::eBroadcastBitStackChanged |
151844d93782SGreg Clayton                                            Thread::eBroadcastBitThreadSelected);
151944d93782SGreg Clayton 
1520b9c1b51eSKate Stone   listener_sp->StartListeningForEventSpec(m_broadcaster_manager_sp,
1521b9c1b51eSKate Stone                                           target_event_spec);
1522b9c1b51eSKate Stone   listener_sp->StartListeningForEventSpec(m_broadcaster_manager_sp,
1523b9c1b51eSKate Stone                                           process_event_spec);
1524b9c1b51eSKate Stone   listener_sp->StartListeningForEventSpec(m_broadcaster_manager_sp,
1525b9c1b51eSKate Stone                                           thread_event_spec);
1526b9c1b51eSKate Stone   listener_sp->StartListeningForEvents(
1527b9c1b51eSKate Stone       m_command_interpreter_ap.get(),
152844d93782SGreg Clayton       CommandInterpreter::eBroadcastBitQuitCommandReceived |
152944d93782SGreg Clayton           CommandInterpreter::eBroadcastBitAsynchronousOutputData |
153044d93782SGreg Clayton           CommandInterpreter::eBroadcastBitAsynchronousErrorData);
153144d93782SGreg Clayton 
153205097246SAdrian Prantl   // Let the thread that spawned us know that we have started up and that we
153305097246SAdrian Prantl   // are now listening to all required events so no events get missed
1534afa91e33SGreg Clayton   m_sync_broadcaster.BroadcastEvent(eBroadcastBitEventThreadIsListening);
1535afa91e33SGreg Clayton 
153644d93782SGreg Clayton   bool done = false;
1537b9c1b51eSKate Stone   while (!done) {
153844d93782SGreg Clayton     EventSP event_sp;
1539d35031e1SPavel Labath     if (listener_sp->GetEvent(event_sp, llvm::None)) {
1540b9c1b51eSKate Stone       if (event_sp) {
154144d93782SGreg Clayton         Broadcaster *broadcaster = event_sp->GetBroadcaster();
1542b9c1b51eSKate Stone         if (broadcaster) {
154344d93782SGreg Clayton           uint32_t event_type = event_sp->GetType();
154444d93782SGreg Clayton           ConstString broadcaster_class(broadcaster->GetBroadcasterClass());
1545b9c1b51eSKate Stone           if (broadcaster_class == broadcaster_class_process) {
154644d93782SGreg Clayton             HandleProcessEvent(event_sp);
1547b9c1b51eSKate Stone           } else if (broadcaster_class == broadcaster_class_target) {
1548b9c1b51eSKate Stone             if (Breakpoint::BreakpointEventData::GetEventDataFromEvent(
1549b9c1b51eSKate Stone                     event_sp.get())) {
155044d93782SGreg Clayton               HandleBreakpointEvent(event_sp);
155144d93782SGreg Clayton             }
1552b9c1b51eSKate Stone           } else if (broadcaster_class == broadcaster_class_thread) {
155344d93782SGreg Clayton             HandleThreadEvent(event_sp);
1554b9c1b51eSKate Stone           } else if (broadcaster == m_command_interpreter_ap.get()) {
1555b9c1b51eSKate Stone             if (event_type &
1556b9c1b51eSKate Stone                 CommandInterpreter::eBroadcastBitQuitCommandReceived) {
155744d93782SGreg Clayton               done = true;
1558b9c1b51eSKate Stone             } else if (event_type &
1559b9c1b51eSKate Stone                        CommandInterpreter::eBroadcastBitAsynchronousErrorData) {
1560b9c1b51eSKate Stone               const char *data = reinterpret_cast<const char *>(
1561b9c1b51eSKate Stone                   EventDataBytes::GetBytesFromEvent(event_sp.get()));
1562b9c1b51eSKate Stone               if (data && data[0]) {
15634446487dSPavel Labath                 StreamSP error_sp(GetAsyncErrorStream());
1564b9c1b51eSKate Stone                 if (error_sp) {
156544d93782SGreg Clayton                   error_sp->PutCString(data);
156644d93782SGreg Clayton                   error_sp->Flush();
156744d93782SGreg Clayton                 }
156844d93782SGreg Clayton               }
1569b9c1b51eSKate Stone             } else if (event_type & CommandInterpreter::
1570b9c1b51eSKate Stone                                         eBroadcastBitAsynchronousOutputData) {
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 output_sp(GetAsyncOutputStream());
1575b9c1b51eSKate Stone                 if (output_sp) {
157644d93782SGreg Clayton                   output_sp->PutCString(data);
157744d93782SGreg Clayton                   output_sp->Flush();
157844d93782SGreg Clayton                 }
157944d93782SGreg Clayton               }
158044d93782SGreg Clayton             }
158144d93782SGreg Clayton           }
158244d93782SGreg Clayton         }
158344d93782SGreg Clayton 
158444d93782SGreg Clayton         if (m_forward_listener_sp)
158544d93782SGreg Clayton           m_forward_listener_sp->AddEvent(event_sp);
158644d93782SGreg Clayton       }
158744d93782SGreg Clayton     }
158844d93782SGreg Clayton   }
158944d93782SGreg Clayton }
159044d93782SGreg Clayton 
1591b9c1b51eSKate Stone lldb::thread_result_t Debugger::EventHandlerThread(lldb::thread_arg_t arg) {
159244d93782SGreg Clayton   ((Debugger *)arg)->DefaultEventHandler();
159344d93782SGreg Clayton   return NULL;
159444d93782SGreg Clayton }
159544d93782SGreg Clayton 
1596b9c1b51eSKate Stone bool Debugger::StartEventHandlerThread() {
1597b9c1b51eSKate Stone   if (!m_event_handler_thread.IsJoinable()) {
159805097246SAdrian Prantl     // We must synchronize with the DefaultEventHandler() thread to ensure it
159905097246SAdrian Prantl     // is up and running and listening to events before we return from this
160005097246SAdrian Prantl     // function. We do this by listening to events for the
1601afa91e33SGreg Clayton     // eBroadcastBitEventThreadIsListening from the m_sync_broadcaster
16021a728f66STatyana Krasnukha     ConstString full_name("lldb.debugger.event-handler");
16031a728f66STatyana Krasnukha     ListenerSP listener_sp(Listener::MakeListener(full_name.AsCString()));
1604b9c1b51eSKate Stone     listener_sp->StartListeningForEvents(&m_sync_broadcaster,
1605b9c1b51eSKate Stone                                          eBroadcastBitEventThreadIsListening);
1606afa91e33SGreg Clayton 
16071a728f66STatyana Krasnukha     auto thread_name =
16081a728f66STatyana Krasnukha         full_name.GetLength() < llvm::get_max_thread_name_length() ?
16091a728f66STatyana Krasnukha         full_name.AsCString() : "dbg.evt-handler";
16101a728f66STatyana Krasnukha 
16117c2896a2SZachary Turner     // Use larger 8MB stack for this thread
16121a728f66STatyana Krasnukha     m_event_handler_thread = ThreadLauncher::LaunchThread(thread_name,
16131a728f66STatyana Krasnukha         EventHandlerThread, this, nullptr, g_debugger_event_thread_stack_bytes);
1614afa91e33SGreg Clayton 
161505097246SAdrian Prantl     // Make sure DefaultEventHandler() is running and listening to events
161605097246SAdrian Prantl     // before we return from this function. We are only listening for events of
161705097246SAdrian Prantl     // type eBroadcastBitEventThreadIsListening so we don't need to check the
161805097246SAdrian Prantl     // event, we just need to wait an infinite amount of time for it (nullptr
161905097246SAdrian Prantl     // timeout as the first parameter)
1620afa91e33SGreg Clayton     lldb::EventSP event_sp;
1621d35031e1SPavel Labath     listener_sp->GetEvent(event_sp, llvm::None);
1622807b6b32SGreg Clayton   }
1623acee96aeSZachary Turner   return m_event_handler_thread.IsJoinable();
162444d93782SGreg Clayton }
162544d93782SGreg Clayton 
1626b9c1b51eSKate Stone void Debugger::StopEventHandlerThread() {
1627b9c1b51eSKate Stone   if (m_event_handler_thread.IsJoinable()) {
1628b9c1b51eSKate Stone     GetCommandInterpreter().BroadcastEvent(
1629b9c1b51eSKate Stone         CommandInterpreter::eBroadcastBitQuitCommandReceived);
163039de3110SZachary Turner     m_event_handler_thread.Join(nullptr);
163144d93782SGreg Clayton   }
163244d93782SGreg Clayton }
163344d93782SGreg Clayton 
1634b9c1b51eSKate Stone lldb::thread_result_t Debugger::IOHandlerThread(lldb::thread_arg_t arg) {
163544d93782SGreg Clayton   Debugger *debugger = (Debugger *)arg;
16369aaab558SSiva Chandra   debugger->ExecuteIOHandlers();
163744d93782SGreg Clayton   debugger->StopEventHandlerThread();
163844d93782SGreg Clayton   return NULL;
163944d93782SGreg Clayton }
164044d93782SGreg Clayton 
1641b9c1b51eSKate Stone bool Debugger::HasIOHandlerThread() { return m_io_handler_thread.IsJoinable(); }
16426681041dSSean Callanan 
1643b9c1b51eSKate Stone bool Debugger::StartIOHandlerThread() {
1644acee96aeSZachary Turner   if (!m_io_handler_thread.IsJoinable())
1645b9c1b51eSKate Stone     m_io_handler_thread = ThreadLauncher::LaunchThread(
1646b9c1b51eSKate Stone         "lldb.debugger.io-handler", IOHandlerThread, this, nullptr,
1647807b6b32SGreg Clayton         8 * 1024 * 1024); // Use larger 8MB stack for this thread
1648acee96aeSZachary Turner   return m_io_handler_thread.IsJoinable();
164944d93782SGreg Clayton }
165044d93782SGreg Clayton 
1651b9c1b51eSKate Stone void Debugger::StopIOHandlerThread() {
1652b9c1b51eSKate Stone   if (m_io_handler_thread.IsJoinable()) {
165344d93782SGreg Clayton     if (m_input_file_sp)
165444d93782SGreg Clayton       m_input_file_sp->GetFile().Close();
165539de3110SZachary Turner     m_io_handler_thread.Join(nullptr);
165644d93782SGreg Clayton   }
165744d93782SGreg Clayton }
165844d93782SGreg Clayton 
1659b9c1b51eSKate Stone void Debugger::JoinIOHandlerThread() {
1660b9c1b51eSKate Stone   if (HasIOHandlerThread()) {
16616681041dSSean Callanan     thread_result_t result;
16626681041dSSean Callanan     m_io_handler_thread.Join(&result);
16636681041dSSean Callanan     m_io_handler_thread = LLDB_INVALID_HOST_THREAD;
16646681041dSSean Callanan   }
16656681041dSSean Callanan }
16666681041dSSean Callanan 
1667b9c1b51eSKate Stone Target *Debugger::GetDummyTarget() {
1668893c932aSJim Ingham   return m_target_list.GetDummyTarget(*this).get();
1669893c932aSJim Ingham }
1670893c932aSJim Ingham 
1671b9c1b51eSKate Stone Target *Debugger::GetSelectedOrDummyTarget(bool prefer_dummy) {
167233df7cd3SJim Ingham   Target *target = nullptr;
1673b9c1b51eSKate Stone   if (!prefer_dummy) {
167433df7cd3SJim Ingham     target = m_target_list.GetSelectedTarget().get();
167533df7cd3SJim Ingham     if (target)
167633df7cd3SJim Ingham       return target;
167733df7cd3SJim Ingham   }
1678893c932aSJim Ingham 
1679893c932aSJim Ingham   return GetDummyTarget();
1680893c932aSJim Ingham }
168144d93782SGreg Clayton 
168297206d57SZachary Turner Status Debugger::RunREPL(LanguageType language, const char *repl_options) {
168397206d57SZachary Turner   Status err;
16843e7e915dSSean Callanan   FileSpec repl_executable;
16853e7e915dSSean Callanan 
1686b9c1b51eSKate Stone   if (language == eLanguageTypeUnknown) {
168797f84e87SSean Callanan     std::set<LanguageType> repl_languages;
168897f84e87SSean Callanan 
168997f84e87SSean Callanan     Language::GetLanguagesSupportingREPLs(repl_languages);
169097f84e87SSean Callanan 
1691b9c1b51eSKate Stone     if (repl_languages.size() == 1) {
169297f84e87SSean Callanan       language = *repl_languages.begin();
1693b9c1b51eSKate Stone     } else if (repl_languages.empty()) {
1694b9c1b51eSKate Stone       err.SetErrorStringWithFormat(
1695b9c1b51eSKate Stone           "LLDB isn't configured with REPL support for any languages.");
169697f84e87SSean Callanan       return err;
1697b9c1b51eSKate Stone     } else {
1698b9c1b51eSKate Stone       err.SetErrorStringWithFormat(
1699b9c1b51eSKate Stone           "Multiple possible REPL languages.  Please specify a language.");
170097f84e87SSean Callanan       return err;
170197f84e87SSean Callanan     }
170297f84e87SSean Callanan   }
170397f84e87SSean Callanan 
1704b9c1b51eSKate Stone   Target *const target =
1705b9c1b51eSKate Stone       nullptr; // passing in an empty target means the REPL must create one
17063e7e915dSSean Callanan 
17073b682de6SSean Callanan   REPLSP repl_sp(REPL::Create(err, language, this, target, repl_options));
17083e7e915dSSean Callanan 
1709b9c1b51eSKate Stone   if (!err.Success()) {
17103e7e915dSSean Callanan     return err;
17113e7e915dSSean Callanan   }
17123e7e915dSSean Callanan 
1713b9c1b51eSKate Stone   if (!repl_sp) {
1714b9c1b51eSKate Stone     err.SetErrorStringWithFormat("couldn't find a REPL for %s",
1715b9c1b51eSKate Stone                                  Language::GetNameForLanguageType(language));
17163e7e915dSSean Callanan     return err;
17173e7e915dSSean Callanan   }
17183e7e915dSSean Callanan 
17193e7e915dSSean Callanan   repl_sp->SetCompilerOptions(repl_options);
17203e7e915dSSean Callanan   repl_sp->RunLoop();
17213e7e915dSSean Callanan 
17223e7e915dSSean Callanan   return err;
17233e7e915dSSean Callanan }
1724