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...
2435e4c84cSJonas Devlieghere #include "lldb/Host/FileSystem.h"
2542ff0ad8SZachary Turner #include "lldb/Host/HostInfo.h"
26a3406614SGreg Clayton #include "lldb/Host/Terminal.h"
2739de3110SZachary Turner #include "lldb/Host/ThreadLauncher.h"
286611103cSGreg Clayton #include "lldb/Interpreter/CommandInterpreter.h"
292f3df613SZachary Turner #include "lldb/Interpreter/OptionValue.h" // for OptionValue, Opt...
30633a29cfSZachary Turner #include "lldb/Interpreter/OptionValueProperties.h"
3167cc0636SGreg Clayton #include "lldb/Interpreter/OptionValueSInt64.h"
3267cc0636SGreg Clayton #include "lldb/Interpreter/OptionValueString.h"
332f3df613SZachary Turner #include "lldb/Interpreter/Property.h"          // for PropertyDefinition
342f3df613SZachary Turner #include "lldb/Interpreter/ScriptInterpreter.h" // for ScriptInterpreter
351f746071SGreg Clayton #include "lldb/Symbol/Function.h"
361f746071SGreg Clayton #include "lldb/Symbol/Symbol.h"
372f3df613SZachary Turner #include "lldb/Symbol/SymbolContext.h" // for SymbolContext
383e7e915dSSean Callanan #include "lldb/Target/Language.h"
3930fdc8d8SChris Lattner #include "lldb/Target/Process.h"
4075930019STodd Fiala #include "lldb/Target/StructuredDataPlugin.h"
4184a53dfbSEnrico Granata #include "lldb/Target/Target.h"
42b9c1b51eSKate Stone #include "lldb/Target/TargetList.h"
4330fdc8d8SChris Lattner #include "lldb/Target/Thread.h"
442f3df613SZachary Turner #include "lldb/Target/ThreadList.h" // for ThreadList
455a31471eSGreg Clayton #include "lldb/Utility/AnsiTerminal.h"
462f3df613SZachary Turner #include "lldb/Utility/Log.h" // for LLDB_LOG_OPTION_...
47d821c997SPavel Labath #include "lldb/Utility/State.h"
482f3df613SZachary Turner #include "lldb/Utility/Stream.h" // for Stream
49fb1a0a0dSZachary Turner #include "lldb/Utility/StreamCallback.h"
50bf9a7730SZachary Turner #include "lldb/Utility/StreamString.h"
512f3df613SZachary Turner 
52b1cb0b79SNico Weber #if defined(_WIN32)
532f3df613SZachary Turner #include "lldb/Host/windows/PosixApi.h" // for PATH_MAX
548aa23614SDavid Bolvansky #include "lldb/Host/windows/windows.h"
552f3df613SZachary Turner #endif
562f3df613SZachary Turner 
572f3df613SZachary Turner #include "llvm/ADT/None.h"      // for None
582f3df613SZachary Turner #include "llvm/ADT/STLExtras.h" // for make_unique
592f3df613SZachary Turner #include "llvm/ADT/StringRef.h"
602f3df613SZachary Turner #include "llvm/ADT/iterator.h" // for iterator_facade_...
612f3df613SZachary Turner #include "llvm/Support/DynamicLibrary.h"
622f3df613SZachary Turner #include "llvm/Support/FileSystem.h"
638aa23614SDavid Bolvansky #include "llvm/Support/Process.h"
642f3df613SZachary Turner #include "llvm/Support/Threading.h"
652f3df613SZachary Turner #include "llvm/Support/raw_ostream.h" // for raw_fd_ostream
662f3df613SZachary Turner 
672f3df613SZachary Turner #include <list>   // for list
682f3df613SZachary Turner #include <memory> // for make_shared
692f3df613SZachary Turner #include <mutex>
702f3df613SZachary Turner #include <set>          // for set
712f3df613SZachary Turner #include <stdio.h>      // for size_t, NULL
722f3df613SZachary Turner #include <stdlib.h>     // for getenv
732f3df613SZachary Turner #include <string.h>     // for strcmp
742f3df613SZachary Turner #include <string>       // for string
752f3df613SZachary Turner #include <system_error> // for error_code
762f3df613SZachary Turner 
772f3df613SZachary Turner namespace lldb_private {
782f3df613SZachary Turner class Address;
792f3df613SZachary Turner }
8030fdc8d8SChris Lattner 
8130fdc8d8SChris Lattner using namespace lldb;
8230fdc8d8SChris Lattner using namespace lldb_private;
8330fdc8d8SChris Lattner 
84ebc1bb27SCaroline Tice static lldb::user_id_t g_unique_id = 1;
857c2896a2SZachary Turner static size_t g_debugger_event_thread_stack_bytes = 8 * 1024 * 1024;
86ebc1bb27SCaroline Tice 
871b654882SGreg Clayton #pragma mark Static Functions
881b654882SGreg Clayton 
891b654882SGreg Clayton typedef std::vector<DebuggerSP> DebuggerList;
90b9c1b51eSKate Stone static std::recursive_mutex *g_debugger_list_mutex_ptr =
91b9c1b51eSKate Stone     nullptr; // NOTE: intentional leak to avoid issues with C++ destructor chain
92b9c1b51eSKate Stone static DebuggerList *g_debugger_list_ptr =
93b9c1b51eSKate Stone     nullptr; // NOTE: intentional leak to avoid issues with C++ destructor chain
94e372b98dSGreg Clayton 
958fe53c49STatyana Krasnukha static constexpr OptionEnumValueElement g_show_disassembly_enum_values[] = {
96b9c1b51eSKate Stone     {Debugger::eStopDisassemblyTypeNever, "never",
97b9c1b51eSKate Stone      "Never show disassembly when displaying a stop context."},
98b9c1b51eSKate Stone     {Debugger::eStopDisassemblyTypeNoDebugInfo, "no-debuginfo",
99b9c1b51eSKate Stone      "Show disassembly when there is no debug information."},
100b9c1b51eSKate Stone     {Debugger::eStopDisassemblyTypeNoSource, "no-source",
101b9c1b51eSKate Stone      "Show disassembly when there is no source information, or the source file "
102b9c1b51eSKate Stone      "is missing when displaying a stop context."},
103b9c1b51eSKate Stone     {Debugger::eStopDisassemblyTypeAlways, "always",
1048fe53c49STatyana Krasnukha      "Always show disassembly when displaying a stop context."} };
105e372b98dSGreg Clayton 
1068fe53c49STatyana Krasnukha static constexpr OptionEnumValueElement g_language_enumerators[] = {
10767cc0636SGreg Clayton     {eScriptLanguageNone, "none", "Disable scripting languages."},
108b9c1b51eSKate Stone     {eScriptLanguagePython, "python",
109b9c1b51eSKate Stone      "Select python as the default scripting language."},
110b9c1b51eSKate Stone     {eScriptLanguageDefault, "default",
1118fe53c49STatyana Krasnukha      "Select the lldb default as the default scripting language."} };
112e372b98dSGreg Clayton 
113b9c1b51eSKate Stone #define MODULE_WITH_FUNC                                                       \
114b9c1b51eSKate Stone   "{ "                                                                         \
1156a9767c7SJim Ingham   "${module.file.basename}{`${function.name-with-args}"                        \
1166a9767c7SJim Ingham   "{${frame.no-debug}${function.pc-offset}}}}"
1177f1c1211SPavel Labath 
1187f1c1211SPavel Labath #define MODULE_WITH_FUNC_NO_ARGS                                               \
1197f1c1211SPavel Labath   "{ "                                                                         \
1207f1c1211SPavel Labath   "${module.file.basename}{`${function.name-without-args}"                     \
1217f1c1211SPavel Labath   "{${frame.no-debug}${function.pc-offset}}}}"
1227f1c1211SPavel Labath 
1234954f6a5SAdrian Prantl #define FILE_AND_LINE                                                          \
1244954f6a5SAdrian Prantl   "{ at ${line.file.basename}:${line.number}{:${line.column}}}"
1256ab659a9SJason Molenda #define IS_OPTIMIZED "{${function.is-optimized} [opt]}"
12667cc0636SGreg Clayton 
1274b36f791SVedant Kumar #define IS_ARTIFICIAL "{${frame.is-artificial} [artificial]}"
1284b36f791SVedant Kumar 
129b9c1b51eSKate Stone #define DEFAULT_THREAD_FORMAT                                                  \
130b9c1b51eSKate Stone   "thread #${thread.index}: tid = ${thread.id%tid}"                            \
131b9c1b51eSKate Stone   "{, ${frame.pc}}" MODULE_WITH_FUNC FILE_AND_LINE                             \
1320769b2b1SMichael Sartain   "{, name = '${thread.name}'}"                                                \
1330769b2b1SMichael Sartain   "{, queue = '${thread.queue}'}"                                              \
134705b1809SJason Molenda   "{, activity = '${thread.info.activity.name}'}"                              \
135705b1809SJason Molenda   "{, ${thread.info.trace_messages} messages}"                                 \
13667cc0636SGreg Clayton   "{, stop reason = ${thread.stop-reason}}"                                    \
13767cc0636SGreg Clayton   "{\\nReturn value: ${thread.return-value}}"                                  \
13830fadafeSJim Ingham   "{\\nCompleted expression: ${thread.completed-expression}}"                  \
13967cc0636SGreg Clayton   "\\n"
14067cc0636SGreg Clayton 
1416a9767c7SJim Ingham #define DEFAULT_THREAD_STOP_FORMAT                                             \
1426a9767c7SJim Ingham   "thread #${thread.index}{, name = '${thread.name}'}"                         \
1436a9767c7SJim Ingham   "{, queue = '${thread.queue}'}"                                              \
1446a9767c7SJim Ingham   "{, activity = '${thread.info.activity.name}'}"                              \
1456a9767c7SJim Ingham   "{, ${thread.info.trace_messages} messages}"                                 \
1466a9767c7SJim Ingham   "{, stop reason = ${thread.stop-reason}}"                                    \
1476a9767c7SJim Ingham   "{\\nReturn value: ${thread.return-value}}"                                  \
1486a9767c7SJim Ingham   "{\\nCompleted expression: ${thread.completed-expression}}"                  \
1496a9767c7SJim Ingham   "\\n"
1506a9767c7SJim Ingham 
151b9c1b51eSKate Stone #define DEFAULT_FRAME_FORMAT                                                   \
152270e8228SJason Molenda   "frame #${frame.index}: ${frame.pc}" MODULE_WITH_FUNC FILE_AND_LINE          \
1534b36f791SVedant Kumar       IS_OPTIMIZED IS_ARTIFICIAL "\\n"
15467cc0636SGreg Clayton 
1557f1c1211SPavel Labath #define DEFAULT_FRAME_FORMAT_NO_ARGS                                           \
1567f1c1211SPavel Labath   "frame #${frame.index}: ${frame.pc}" MODULE_WITH_FUNC_NO_ARGS FILE_AND_LINE  \
1574b36f791SVedant Kumar       IS_OPTIMIZED IS_ARTIFICIAL "\\n"
1587f1c1211SPavel Labath 
159c980fa92SJason Molenda // Three parts to this disassembly format specification:
160c980fa92SJason Molenda //   1. If this is a new function/symbol (no previous symbol/function), print
161c980fa92SJason Molenda //      dylib`funcname:\n
162b9c1b51eSKate Stone //   2. If this is a symbol context change (different from previous
163b9c1b51eSKate Stone //   symbol/function), print
164c980fa92SJason Molenda //      dylib`funcname:\n
165c980fa92SJason Molenda //   3. print
166c980fa92SJason Molenda //      address <+offset>:
167b9c1b51eSKate Stone #define DEFAULT_DISASSEMBLY_FORMAT                                             \
168b9c1b51eSKate Stone   "{${function.initial-function}{${module.file.basename}`}{${function.name-"   \
169e43be156SJonas Devlieghere   "without-args}}:\\n}{${function.changed}\\n{${module.file.basename}`}{${"    \
170e43be156SJonas Devlieghere   "function.name-without-args}}:\\n}{${current-pc-arrow} "                     \
171b9c1b51eSKate Stone   "}${addr-file-or-load}{ "                                                    \
172b9c1b51eSKate Stone   "<${function.concrete-only-addr-offset-no-padding}>}: "
173c980fa92SJason Molenda 
17405097246SAdrian Prantl // gdb's disassembly format can be emulated with ${current-pc-arrow}${addr-
17505097246SAdrian Prantl // file-or-load}{ <${function.name-without-args}${function.concrete-only-addr-
17605097246SAdrian Prantl // offset-no-padding}>}:
177c980fa92SJason Molenda 
178c980fa92SJason Molenda // lldb's original format for disassembly would look like this format string -
17905097246SAdrian Prantl // {${function.initial-function}{${module.file.basename}`}{${function.name-
18005097246SAdrian Prantl // without-
18105097246SAdrian Prantl // args}}:\n}{${function.changed}\n{${module.file.basename}`}{${function.name-
18205097246SAdrian Prantl // without-args}}:\n}{${current-pc-arrow} }{${addr-file-or-load}}:
183c980fa92SJason Molenda 
1848fe53c49STatyana Krasnukha static constexpr OptionEnumValueElement s_stop_show_column_values[] = {
1859666ba75STodd Fiala     {eStopShowColumnAnsiOrCaret, "ansi-or-caret",
1869666ba75STodd Fiala      "Highlight the stop column with ANSI terminal codes when color/ANSI mode "
1879666ba75STodd Fiala      "is enabled; otherwise, fall back to using a text-only caret (^) as if "
1889666ba75STodd Fiala      "\"caret-only\" mode was selected."},
1899666ba75STodd Fiala     {eStopShowColumnAnsi, "ansi", "Highlight the stop column with ANSI "
1909666ba75STodd Fiala                                   "terminal codes when running LLDB with "
1919666ba75STodd Fiala                                   "color/ANSI enabled."},
1929666ba75STodd Fiala     {eStopShowColumnCaret, "caret",
1939666ba75STodd Fiala      "Highlight the stop column with a caret character (^) underneath the stop "
1949666ba75STodd Fiala      "column. This method introduces a new line in source listings that "
1959666ba75STodd Fiala      "display thread stop locations."},
1968fe53c49STatyana Krasnukha     {eStopShowColumnNone, "none", "Do not highlight the stop column."}};
1979666ba75STodd Fiala 
1988fe53c49STatyana Krasnukha static constexpr PropertyDefinition g_properties[] = {
1998fe53c49STatyana Krasnukha     {"auto-confirm", OptionValue::eTypeBoolean, true, false, nullptr, {},
200b9c1b51eSKate Stone      "If true all confirmation prompts will receive their default reply."},
201b9c1b51eSKate Stone     {"disassembly-format", OptionValue::eTypeFormatEntity, true, 0,
2028fe53c49STatyana Krasnukha      DEFAULT_DISASSEMBLY_FORMAT, {},
2037f1c1211SPavel Labath      "The default disassembly format "
204b9c1b51eSKate Stone      "string to use when disassembling "
205b9c1b51eSKate Stone      "instruction sequences."},
206b9c1b51eSKate Stone     {"frame-format", OptionValue::eTypeFormatEntity, true, 0,
2078fe53c49STatyana Krasnukha      DEFAULT_FRAME_FORMAT, {},
2087f1c1211SPavel Labath      "The default frame format string to use "
209b9c1b51eSKate Stone      "when displaying stack frame information "
210b9c1b51eSKate Stone      "for threads."},
2118fe53c49STatyana Krasnukha     {"notify-void", OptionValue::eTypeBoolean, true, false, nullptr, {},
212b9c1b51eSKate Stone      "Notify the user explicitly if an expression returns void (default: "
213b9c1b51eSKate Stone      "false)."},
214b9c1b51eSKate Stone     {"prompt", OptionValue::eTypeString, true,
2158fe53c49STatyana Krasnukha      OptionValueString::eOptionEncodeCharacterEscapeSequences, "(lldb) ", {},
2168fe53c49STatyana Krasnukha      "The debugger command line prompt displayed for the user."},
217b9c1b51eSKate Stone     {"script-lang", OptionValue::eTypeEnum, true, eScriptLanguagePython,
2188fe53c49STatyana Krasnukha      nullptr, OptionEnumValues(g_language_enumerators),
219b9c1b51eSKate Stone      "The script language to be used for evaluating user-written scripts."},
2208fe53c49STatyana Krasnukha     {"stop-disassembly-count", OptionValue::eTypeSInt64, true, 4, nullptr, {},
2217f1c1211SPavel Labath      "The number of disassembly lines to show when displaying a "
222b9c1b51eSKate Stone      "stopped context."},
223b9c1b51eSKate Stone     {"stop-disassembly-display", OptionValue::eTypeEnum, true,
224b9c1b51eSKate Stone      Debugger::eStopDisassemblyTypeNoDebugInfo, nullptr,
2258fe53c49STatyana Krasnukha      OptionEnumValues(g_show_disassembly_enum_values),
226b9c1b51eSKate Stone      "Control when to display disassembly when displaying a stopped context."},
2278fe53c49STatyana Krasnukha     {"stop-line-count-after", OptionValue::eTypeSInt64, true, 3, nullptr, {},
2287f1c1211SPavel Labath      "The number of sources lines to display that come after the "
229b9c1b51eSKate Stone      "current source line when displaying a stopped context."},
2308fe53c49STatyana Krasnukha     {"stop-line-count-before", OptionValue::eTypeSInt64, true, 3, nullptr, {},
2317f1c1211SPavel Labath      "The number of sources lines to display that come before the "
232b9c1b51eSKate Stone      "current source line when displaying a stopped context."},
2338fe53c49STatyana Krasnukha     {"highlight-source", OptionValue::eTypeBoolean, true, true, nullptr, {},
2348fe53c49STatyana Krasnukha      "If true, LLDB will highlight the displayed source code."},
2359666ba75STodd Fiala     {"stop-show-column", OptionValue::eTypeEnum, false,
2368fe53c49STatyana Krasnukha      eStopShowColumnAnsiOrCaret, nullptr, OptionEnumValues(s_stop_show_column_values),
2379666ba75STodd Fiala      "If true, LLDB will use the column information from the debug info to "
2389666ba75STodd Fiala      "mark the current position when displaying a stopped context."},
23920786326SRaphael Isemann     {"stop-show-column-ansi-prefix", OptionValue::eTypeString, true, 0,
2408fe53c49STatyana Krasnukha      "${ansi.underline}", {},
2419666ba75STodd Fiala      "When displaying the column marker in a color-enabled (i.e. ANSI) "
2429666ba75STodd Fiala      "terminal, use the ANSI terminal code specified in this format at the "
2439666ba75STodd Fiala      "immediately before the column to be marked."},
24420786326SRaphael Isemann     {"stop-show-column-ansi-suffix", OptionValue::eTypeString, true, 0,
2458fe53c49STatyana Krasnukha      "${ansi.normal}", {},
2469666ba75STodd Fiala      "When displaying the column marker in a color-enabled (i.e. ANSI) "
2479666ba75STodd Fiala      "terminal, use the ANSI terminal code specified in this format "
2489666ba75STodd Fiala      "immediately after the column to be marked."},
2498fe53c49STatyana Krasnukha     {"term-width", OptionValue::eTypeSInt64, true, 80, nullptr, {},
250b9c1b51eSKate Stone      "The maximum number of columns to use for displaying text."},
251b9c1b51eSKate Stone     {"thread-format", OptionValue::eTypeFormatEntity, true, 0,
2528fe53c49STatyana Krasnukha      DEFAULT_THREAD_FORMAT, {},
2537f1c1211SPavel Labath      "The default thread format string to use "
254b9c1b51eSKate Stone      "when displaying thread information."},
2556a9767c7SJim Ingham     {"thread-stop-format", OptionValue::eTypeFormatEntity, true, 0,
2568fe53c49STatyana Krasnukha      DEFAULT_THREAD_STOP_FORMAT, {},
2577f1c1211SPavel Labath      "The default thread format  "
2586a9767c7SJim Ingham      "string to use when displaying thread "
2596a9767c7SJim Ingham      "information as part of the stop display."},
2608fe53c49STatyana Krasnukha     {"use-external-editor", OptionValue::eTypeBoolean, true, false, nullptr, {},
2618fe53c49STatyana Krasnukha      "Whether to use an external editor or not."},
2628fe53c49STatyana Krasnukha     {"use-color", OptionValue::eTypeBoolean, true, true, nullptr, {},
263b9c1b51eSKate Stone      "Whether to use Ansi color codes or not."},
264b9c1b51eSKate Stone     {"auto-one-line-summaries", OptionValue::eTypeBoolean, true, true, nullptr,
2658fe53c49STatyana Krasnukha      {},
2667f1c1211SPavel Labath      "If true, LLDB will automatically display small structs in "
267b9c1b51eSKate Stone      "one-liner format (default: true)."},
2688fe53c49STatyana Krasnukha     {"auto-indent", OptionValue::eTypeBoolean, true, true, nullptr, {},
269b9c1b51eSKate Stone      "If true, LLDB will auto indent/outdent code. Currently only supported in "
270b9c1b51eSKate Stone      "the REPL (default: true)."},
2718fe53c49STatyana Krasnukha     {"print-decls", OptionValue::eTypeBoolean, true, true, nullptr, {},
272b9c1b51eSKate Stone      "If true, LLDB will print the values of variables declared in an "
273b9c1b51eSKate Stone      "expression. Currently only supported in the REPL (default: true)."},
2748fe53c49STatyana Krasnukha     {"tab-size", OptionValue::eTypeUInt64, true, 4, nullptr, {},
275b9c1b51eSKate Stone      "The tab size to use when indenting code in multi-line input mode "
276b9c1b51eSKate Stone      "(default: 4)."},
277b9c1b51eSKate Stone     {"escape-non-printables", OptionValue::eTypeBoolean, true, true, nullptr,
2788fe53c49STatyana Krasnukha      {},
2797f1c1211SPavel Labath      "If true, LLDB will automatically escape non-printable and "
280b9c1b51eSKate Stone      "escape characters when formatting strings."},
2817f1c1211SPavel Labath     {"frame-format-unique", OptionValue::eTypeFormatEntity, true, 0,
2828fe53c49STatyana Krasnukha      DEFAULT_FRAME_FORMAT_NO_ARGS, {},
2837f1c1211SPavel Labath      "The default frame format string to use when displaying stack frame"
284e40db05bSTatyana Krasnukha      "information for threads from thread backtrace unique."}};
28567cc0636SGreg Clayton 
286b9c1b51eSKate Stone enum {
28767cc0636SGreg Clayton   ePropertyAutoConfirm = 0,
288aff1b357SJason Molenda   ePropertyDisassemblyFormat,
28967cc0636SGreg Clayton   ePropertyFrameFormat,
29067cc0636SGreg Clayton   ePropertyNotiftVoid,
29167cc0636SGreg Clayton   ePropertyPrompt,
29267cc0636SGreg Clayton   ePropertyScriptLanguage,
29367cc0636SGreg Clayton   ePropertyStopDisassemblyCount,
29467cc0636SGreg Clayton   ePropertyStopDisassemblyDisplay,
29567cc0636SGreg Clayton   ePropertyStopLineCountAfter,
29667cc0636SGreg Clayton   ePropertyStopLineCountBefore,
297566afa0aSRaphael Isemann   ePropertyHighlightSource,
2989666ba75STodd Fiala   ePropertyStopShowColumn,
2999666ba75STodd Fiala   ePropertyStopShowColumnAnsiPrefix,
3009666ba75STodd Fiala   ePropertyStopShowColumnAnsiSuffix,
30167cc0636SGreg Clayton   ePropertyTerminalWidth,
30267cc0636SGreg Clayton   ePropertyThreadFormat,
3036a9767c7SJim Ingham   ePropertyThreadStopFormat,
304c3ce7f27SMichael Sartain   ePropertyUseExternalEditor,
305c3ce7f27SMichael Sartain   ePropertyUseColor,
306ebdc1ac0SEnrico Granata   ePropertyAutoOneLineSummaries,
3076681041dSSean Callanan   ePropertyAutoIndent,
3086681041dSSean Callanan   ePropertyPrintDecls,
3096681041dSSean Callanan   ePropertyTabSize,
3107f1c1211SPavel Labath   ePropertyEscapeNonPrintables,
3117f1c1211SPavel Labath   ePropertyFrameFormatUnique,
31267cc0636SGreg Clayton };
31367cc0636SGreg Clayton 
314df370550SEugene Zelenko LoadPluginCallbackType Debugger::g_load_plugin_callback = nullptr;
3154c05410fSGreg Clayton 
31697206d57SZachary Turner Status Debugger::SetPropertyValue(const ExecutionContext *exe_ctx,
3174c05410fSGreg Clayton                                   VarSetOperationType op,
31897206d57SZachary Turner                                   llvm::StringRef property_path,
31997206d57SZachary Turner                                   llvm::StringRef value) {
32031d97a5cSZachary Turner   bool is_load_script = (property_path == "target.load-script-from-symbol-file");
32131d97a5cSZachary Turner   bool is_escape_non_printables = (property_path == "escape-non-printables");
32284a53dfbSEnrico Granata   TargetSP target_sp;
323397ddd5fSEnrico Granata   LoadScriptFromSymFile load_script_old_value;
324b9c1b51eSKate Stone   if (is_load_script && exe_ctx->GetTargetSP()) {
32584a53dfbSEnrico Granata     target_sp = exe_ctx->GetTargetSP();
326b9c1b51eSKate Stone     load_script_old_value =
327b9c1b51eSKate Stone         target_sp->TargetProperties::GetLoadScriptFromSymbolFile();
32884a53dfbSEnrico Granata   }
32997206d57SZachary Turner   Status error(Properties::SetPropertyValue(exe_ctx, op, property_path, value));
330b9c1b51eSKate Stone   if (error.Success()) {
33184a53dfbSEnrico Granata     // FIXME it would be nice to have "on-change" callbacks for properties
33231d97a5cSZachary Turner     if (property_path == g_properties[ePropertyPrompt].name) {
333514d8cd8SZachary Turner       llvm::StringRef new_prompt = GetPrompt();
334b9c1b51eSKate Stone       std::string str = lldb_utility::ansi::FormatAnsiTerminalCodes(
335b9c1b51eSKate Stone           new_prompt, GetUseColor());
336c3ce7f27SMichael Sartain       if (str.length())
337771ef6d4SMalcolm Parsons         new_prompt = str;
33844d93782SGreg Clayton       GetCommandInterpreter().UpdatePrompt(new_prompt);
3392f3df613SZachary Turner       auto bytes = llvm::make_unique<EventDataBytes>(new_prompt);
3402f3df613SZachary Turner       auto prompt_change_event_sp = std::make_shared<Event>(
3412f3df613SZachary Turner           CommandInterpreter::eBroadcastBitResetPrompt, bytes.release());
3424c05410fSGreg Clayton       GetCommandInterpreter().BroadcastEvent(prompt_change_event_sp);
34331d97a5cSZachary Turner     } else if (property_path == g_properties[ePropertyUseColor].name) {
344b9c1b51eSKate Stone       // use-color changed. Ping the prompt so it can reset the ansi terminal
345b9c1b51eSKate Stone       // codes.
346c3ce7f27SMichael Sartain       SetPrompt(GetPrompt());
347b9c1b51eSKate Stone     } else if (is_load_script && target_sp &&
348b9c1b51eSKate Stone                load_script_old_value == eLoadScriptFromSymFileWarn) {
349b9c1b51eSKate Stone       if (target_sp->TargetProperties::GetLoadScriptFromSymbolFile() ==
350b9c1b51eSKate Stone           eLoadScriptFromSymFileTrue) {
35197206d57SZachary Turner         std::list<Status> errors;
3529730339bSEnrico Granata         StreamString feedback_stream;
353b9c1b51eSKate Stone         if (!target_sp->LoadScriptingResources(errors, &feedback_stream)) {
35444d93782SGreg Clayton           StreamFileSP stream_sp(GetErrorFile());
355b9c1b51eSKate Stone           if (stream_sp) {
356b9c1b51eSKate Stone             for (auto error : errors) {
35744d93782SGreg Clayton               stream_sp->Printf("%s\n", error.AsCString());
35884a53dfbSEnrico Granata             }
3599730339bSEnrico Granata             if (feedback_stream.GetSize())
360c156427dSZachary Turner               stream_sp->PutCString(feedback_stream.GetString());
36144d93782SGreg Clayton           }
36284a53dfbSEnrico Granata         }
36384a53dfbSEnrico Granata       }
364b9c1b51eSKate Stone     } else if (is_escape_non_printables) {
365ebdc1ac0SEnrico Granata       DataVisualization::ForceUpdate();
366ebdc1ac0SEnrico Granata     }
3674c05410fSGreg Clayton   }
3684c05410fSGreg Clayton   return error;
3694c05410fSGreg Clayton }
3704c05410fSGreg Clayton 
371b9c1b51eSKate Stone bool Debugger::GetAutoConfirm() const {
37267cc0636SGreg Clayton   const uint32_t idx = ePropertyAutoConfirm;
373b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsBoolean(
374b9c1b51eSKate Stone       nullptr, idx, g_properties[idx].default_uint_value != 0);
37567cc0636SGreg Clayton }
37667cc0636SGreg Clayton 
377b9c1b51eSKate Stone const FormatEntity::Entry *Debugger::GetDisassemblyFormat() const {
378aff1b357SJason Molenda   const uint32_t idx = ePropertyDisassemblyFormat;
379df370550SEugene Zelenko   return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
380aff1b357SJason Molenda }
381aff1b357SJason Molenda 
382b9c1b51eSKate Stone const FormatEntity::Entry *Debugger::GetFrameFormat() const {
38367cc0636SGreg Clayton   const uint32_t idx = ePropertyFrameFormat;
384df370550SEugene Zelenko   return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
38567cc0636SGreg Clayton }
38667cc0636SGreg Clayton 
3877f1c1211SPavel Labath const FormatEntity::Entry *Debugger::GetFrameFormatUnique() const {
3887f1c1211SPavel Labath   const uint32_t idx = ePropertyFrameFormatUnique;
3897f1c1211SPavel Labath   return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
3907f1c1211SPavel Labath }
3917f1c1211SPavel Labath 
392b9c1b51eSKate Stone bool Debugger::GetNotifyVoid() const {
39367cc0636SGreg Clayton   const uint32_t idx = ePropertyNotiftVoid;
394b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsBoolean(
395b9c1b51eSKate Stone       nullptr, idx, g_properties[idx].default_uint_value != 0);
39667cc0636SGreg Clayton }
39767cc0636SGreg Clayton 
398514d8cd8SZachary Turner llvm::StringRef Debugger::GetPrompt() const {
39967cc0636SGreg Clayton   const uint32_t idx = ePropertyPrompt;
400b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsString(
401b9c1b51eSKate Stone       nullptr, idx, g_properties[idx].default_cstr_value);
40267cc0636SGreg Clayton }
40367cc0636SGreg Clayton 
404514d8cd8SZachary Turner void Debugger::SetPrompt(llvm::StringRef p) {
40567cc0636SGreg Clayton   const uint32_t idx = ePropertyPrompt;
406df370550SEugene Zelenko   m_collection_sp->SetPropertyAtIndexAsString(nullptr, idx, p);
407514d8cd8SZachary Turner   llvm::StringRef new_prompt = GetPrompt();
408b9c1b51eSKate Stone   std::string str =
409b9c1b51eSKate Stone       lldb_utility::ansi::FormatAnsiTerminalCodes(new_prompt, GetUseColor());
410c3ce7f27SMichael Sartain   if (str.length())
411771ef6d4SMalcolm Parsons     new_prompt = str;
41244d93782SGreg Clayton   GetCommandInterpreter().UpdatePrompt(new_prompt);
41367cc0636SGreg Clayton }
41467cc0636SGreg Clayton 
415b9c1b51eSKate Stone const FormatEntity::Entry *Debugger::GetThreadFormat() const {
41667cc0636SGreg Clayton   const uint32_t idx = ePropertyThreadFormat;
417df370550SEugene Zelenko   return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
41867cc0636SGreg Clayton }
41967cc0636SGreg Clayton 
4206a9767c7SJim Ingham const FormatEntity::Entry *Debugger::GetThreadStopFormat() const {
4216a9767c7SJim Ingham   const uint32_t idx = ePropertyThreadStopFormat;
4226a9767c7SJim Ingham   return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
4236a9767c7SJim Ingham }
4246a9767c7SJim Ingham 
425b9c1b51eSKate Stone lldb::ScriptLanguage Debugger::GetScriptLanguage() const {
42667cc0636SGreg Clayton   const uint32_t idx = ePropertyScriptLanguage;
427b9c1b51eSKate Stone   return (lldb::ScriptLanguage)m_collection_sp->GetPropertyAtIndexAsEnumeration(
428b9c1b51eSKate Stone       nullptr, idx, g_properties[idx].default_uint_value);
42967cc0636SGreg Clayton }
43067cc0636SGreg Clayton 
431b9c1b51eSKate Stone bool Debugger::SetScriptLanguage(lldb::ScriptLanguage script_lang) {
43267cc0636SGreg Clayton   const uint32_t idx = ePropertyScriptLanguage;
433b9c1b51eSKate Stone   return m_collection_sp->SetPropertyAtIndexAsEnumeration(nullptr, idx,
434b9c1b51eSKate Stone                                                           script_lang);
43567cc0636SGreg Clayton }
43667cc0636SGreg Clayton 
437b9c1b51eSKate Stone uint32_t Debugger::GetTerminalWidth() const {
43867cc0636SGreg Clayton   const uint32_t idx = ePropertyTerminalWidth;
439b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsSInt64(
440b9c1b51eSKate Stone       nullptr, idx, g_properties[idx].default_uint_value);
44167cc0636SGreg Clayton }
44267cc0636SGreg Clayton 
443b9c1b51eSKate Stone bool Debugger::SetTerminalWidth(uint32_t term_width) {
44467cc0636SGreg Clayton   const uint32_t idx = ePropertyTerminalWidth;
445df370550SEugene Zelenko   return m_collection_sp->SetPropertyAtIndexAsSInt64(nullptr, idx, term_width);
44667cc0636SGreg Clayton }
44767cc0636SGreg Clayton 
448b9c1b51eSKate Stone bool Debugger::GetUseExternalEditor() const {
44967cc0636SGreg Clayton   const uint32_t idx = ePropertyUseExternalEditor;
450b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsBoolean(
451b9c1b51eSKate Stone       nullptr, idx, g_properties[idx].default_uint_value != 0);
45267cc0636SGreg Clayton }
45367cc0636SGreg Clayton 
454b9c1b51eSKate Stone bool Debugger::SetUseExternalEditor(bool b) {
45567cc0636SGreg Clayton   const uint32_t idx = ePropertyUseExternalEditor;
456df370550SEugene Zelenko   return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
45767cc0636SGreg Clayton }
45867cc0636SGreg Clayton 
459b9c1b51eSKate Stone bool Debugger::GetUseColor() const {
460c3ce7f27SMichael Sartain   const uint32_t idx = ePropertyUseColor;
461b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsBoolean(
462b9c1b51eSKate Stone       nullptr, idx, g_properties[idx].default_uint_value != 0);
463c3ce7f27SMichael Sartain }
464c3ce7f27SMichael Sartain 
465b9c1b51eSKate Stone bool Debugger::SetUseColor(bool b) {
466c3ce7f27SMichael Sartain   const uint32_t idx = ePropertyUseColor;
467df370550SEugene Zelenko   bool ret = m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
468c3ce7f27SMichael Sartain   SetPrompt(GetPrompt());
469c3ce7f27SMichael Sartain   return ret;
470c3ce7f27SMichael Sartain }
471c3ce7f27SMichael Sartain 
472566afa0aSRaphael Isemann bool Debugger::GetHighlightSource() const {
473566afa0aSRaphael Isemann   const uint32_t idx = ePropertyHighlightSource;
474566afa0aSRaphael Isemann   return m_collection_sp->GetPropertyAtIndexAsBoolean(
475566afa0aSRaphael Isemann       nullptr, idx, g_properties[idx].default_uint_value);
476566afa0aSRaphael Isemann }
477566afa0aSRaphael Isemann 
4789666ba75STodd Fiala StopShowColumn Debugger::GetStopShowColumn() const {
4799666ba75STodd Fiala   const uint32_t idx = ePropertyStopShowColumn;
4809666ba75STodd Fiala   return (lldb::StopShowColumn)m_collection_sp->GetPropertyAtIndexAsEnumeration(
4819666ba75STodd Fiala       nullptr, idx, g_properties[idx].default_uint_value);
4829666ba75STodd Fiala }
4839666ba75STodd Fiala 
48420786326SRaphael Isemann llvm::StringRef Debugger::GetStopShowColumnAnsiPrefix() const {
4859666ba75STodd Fiala   const uint32_t idx = ePropertyStopShowColumnAnsiPrefix;
48620786326SRaphael Isemann   return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, "");
4879666ba75STodd Fiala }
4889666ba75STodd Fiala 
48920786326SRaphael Isemann llvm::StringRef Debugger::GetStopShowColumnAnsiSuffix() const {
4909666ba75STodd Fiala   const uint32_t idx = ePropertyStopShowColumnAnsiSuffix;
49120786326SRaphael Isemann   return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, "");
4929666ba75STodd Fiala }
4939666ba75STodd Fiala 
494b9c1b51eSKate Stone uint32_t Debugger::GetStopSourceLineCount(bool before) const {
495b9c1b51eSKate Stone   const uint32_t idx =
496b9c1b51eSKate Stone       before ? ePropertyStopLineCountBefore : ePropertyStopLineCountAfter;
497b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsSInt64(
498b9c1b51eSKate Stone       nullptr, idx, g_properties[idx].default_uint_value);
49967cc0636SGreg Clayton }
50067cc0636SGreg Clayton 
501b9c1b51eSKate Stone Debugger::StopDisassemblyType Debugger::GetStopDisassemblyDisplay() const {
50267cc0636SGreg Clayton   const uint32_t idx = ePropertyStopDisassemblyDisplay;
503b9c1b51eSKate Stone   return (Debugger::StopDisassemblyType)
504b9c1b51eSKate Stone       m_collection_sp->GetPropertyAtIndexAsEnumeration(
505b9c1b51eSKate Stone           nullptr, idx, g_properties[idx].default_uint_value);
50667cc0636SGreg Clayton }
50767cc0636SGreg Clayton 
508b9c1b51eSKate Stone uint32_t Debugger::GetDisassemblyLineCount() const {
50967cc0636SGreg Clayton   const uint32_t idx = ePropertyStopDisassemblyCount;
510b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsSInt64(
511b9c1b51eSKate Stone       nullptr, idx, g_properties[idx].default_uint_value);
51267cc0636SGreg Clayton }
513e372b98dSGreg Clayton 
514b9c1b51eSKate Stone bool Debugger::GetAutoOneLineSummaries() const {
51590a8db30SEnrico Granata   const uint32_t idx = ePropertyAutoOneLineSummaries;
516df370550SEugene Zelenko   return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true);
517ebdc1ac0SEnrico Granata }
518553fad5cSEnrico Granata 
519b9c1b51eSKate Stone bool Debugger::GetEscapeNonPrintables() const {
520ebdc1ac0SEnrico Granata   const uint32_t idx = ePropertyEscapeNonPrintables;
521df370550SEugene Zelenko   return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true);
522553fad5cSEnrico Granata }
523553fad5cSEnrico Granata 
524b9c1b51eSKate Stone bool Debugger::GetAutoIndent() const {
5256681041dSSean Callanan   const uint32_t idx = ePropertyAutoIndent;
526df370550SEugene Zelenko   return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true);
5276681041dSSean Callanan }
5286681041dSSean Callanan 
529b9c1b51eSKate Stone bool Debugger::SetAutoIndent(bool b) {
5306681041dSSean Callanan   const uint32_t idx = ePropertyAutoIndent;
531df370550SEugene Zelenko   return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
5326681041dSSean Callanan }
5336681041dSSean Callanan 
534b9c1b51eSKate Stone bool Debugger::GetPrintDecls() const {
5356681041dSSean Callanan   const uint32_t idx = ePropertyPrintDecls;
536df370550SEugene Zelenko   return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true);
5376681041dSSean Callanan }
5386681041dSSean Callanan 
539b9c1b51eSKate Stone bool Debugger::SetPrintDecls(bool b) {
5406681041dSSean Callanan   const uint32_t idx = ePropertyPrintDecls;
541df370550SEugene Zelenko   return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
5426681041dSSean Callanan }
5436681041dSSean Callanan 
544b9c1b51eSKate Stone uint32_t Debugger::GetTabSize() const {
5456681041dSSean Callanan   const uint32_t idx = ePropertyTabSize;
546b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsUInt64(
547b9c1b51eSKate Stone       nullptr, idx, g_properties[idx].default_uint_value);
5486681041dSSean Callanan }
5496681041dSSean Callanan 
550b9c1b51eSKate Stone bool Debugger::SetTabSize(uint32_t tab_size) {
5516681041dSSean Callanan   const uint32_t idx = ePropertyTabSize;
552df370550SEugene Zelenko   return m_collection_sp->SetPropertyAtIndexAsUInt64(nullptr, idx, tab_size);
5536681041dSSean Callanan }
5546681041dSSean Callanan 
5551b654882SGreg Clayton #pragma mark Debugger
5561b654882SGreg Clayton 
55767cc0636SGreg Clayton // const DebuggerPropertiesSP &
55867cc0636SGreg Clayton // Debugger::GetSettings() const
55967cc0636SGreg Clayton //{
56067cc0636SGreg Clayton //    return m_properties_sp;
56167cc0636SGreg Clayton //}
56267cc0636SGreg Clayton //
56399d0faf2SGreg Clayton 
564b9c1b51eSKate Stone void Debugger::Initialize(LoadPluginCallbackType load_plugin_callback) {
565b9c1b51eSKate Stone   assert(g_debugger_list_ptr == nullptr &&
566b9c1b51eSKate Stone          "Debugger::Initialize called more than once!");
5676c42e063SGreg Clayton   g_debugger_list_mutex_ptr = new std::recursive_mutex();
5686c42e063SGreg Clayton   g_debugger_list_ptr = new DebuggerList();
5695fb8f797SGreg Clayton   g_load_plugin_callback = load_plugin_callback;
57099d0faf2SGreg Clayton }
57130fdc8d8SChris Lattner 
572b9c1b51eSKate Stone void Debugger::Terminate() {
573b9c1b51eSKate Stone   assert(g_debugger_list_ptr &&
574b9c1b51eSKate Stone          "Debugger::Terminate called without a matching Debugger::Initialize!");
575e6e2bb38SZachary Turner 
576b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
57799d0faf2SGreg Clayton     // Clear our master list of debugger objects
5786c42e063SGreg Clayton     {
5796c42e063SGreg Clayton       std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
5806c42e063SGreg Clayton       for (const auto &debugger : *g_debugger_list_ptr)
581f3cd1819SOleksiy Vyalov         debugger->Clear();
5826c42e063SGreg Clayton       g_debugger_list_ptr->clear();
5836c42e063SGreg Clayton     }
5846c42e063SGreg Clayton   }
58530fdc8d8SChris Lattner }
58630fdc8d8SChris Lattner 
587b9c1b51eSKate Stone void Debugger::SettingsInitialize() { Target::SettingsInitialize(); }
58820bd37f7SCaroline Tice 
589b9c1b51eSKate Stone void Debugger::SettingsTerminate() { Target::SettingsTerminate(); }
59020bd37f7SCaroline Tice 
59197206d57SZachary Turner bool Debugger::LoadPlugin(const FileSpec &spec, Status &error) {
592b9c1b51eSKate Stone   if (g_load_plugin_callback) {
593b9c1b51eSKate Stone     llvm::sys::DynamicLibrary dynlib =
594b9c1b51eSKate Stone         g_load_plugin_callback(shared_from_this(), spec, error);
595b9c1b51eSKate Stone     if (dynlib.isValid()) {
59658a559c0SZachary Turner       m_loaded_plugins.push_back(dynlib);
59721dfcd9dSEnrico Granata       return true;
59821dfcd9dSEnrico Granata     }
599b9c1b51eSKate Stone   } else {
60005097246SAdrian Prantl     // The g_load_plugin_callback is registered in SBDebugger::Initialize() and
60105097246SAdrian Prantl     // if the public API layer isn't available (code is linking against all of
60205097246SAdrian Prantl     // the internal LLDB static libraries), then we can't load plugins
6035fb8f797SGreg Clayton     error.SetErrorString("Public API layer is not available");
6045fb8f797SGreg Clayton   }
60521dfcd9dSEnrico Granata   return false;
60621dfcd9dSEnrico Granata }
60721dfcd9dSEnrico Granata 
60835e4c84cSJonas Devlieghere static FileSystem::EnumerateDirectoryResult
6097d86ee5aSZachary Turner LoadPluginCallback(void *baton, llvm::sys::fs::file_type ft,
61035e4c84cSJonas Devlieghere                    llvm::StringRef path) {
61197206d57SZachary Turner   Status error;
61221dfcd9dSEnrico Granata 
613ad8d48f9SJonas Devlieghere   static ConstString g_dylibext(".dylib");
614ad8d48f9SJonas Devlieghere   static ConstString g_solibext(".so");
61521dfcd9dSEnrico Granata 
61621dfcd9dSEnrico Granata   if (!baton)
61735e4c84cSJonas Devlieghere     return FileSystem::eEnumerateDirectoryResultQuit;
61821dfcd9dSEnrico Granata 
61921dfcd9dSEnrico Granata   Debugger *debugger = (Debugger *)baton;
62021dfcd9dSEnrico Granata 
6217d86ee5aSZachary Turner   namespace fs = llvm::sys::fs;
62205097246SAdrian Prantl   // If we have a regular file, a symbolic link or unknown file type, try and
62305097246SAdrian Prantl   // process the file. We must handle unknown as sometimes the directory
62421dfcd9dSEnrico Granata   // enumeration might be enumerating a file system that doesn't have correct
62521dfcd9dSEnrico Granata   // file type information.
6267d86ee5aSZachary Turner   if (ft == fs::file_type::regular_file || ft == fs::file_type::symlink_file ||
6277d86ee5aSZachary Turner       ft == fs::file_type::type_unknown) {
62835e4c84cSJonas Devlieghere     FileSpec plugin_file_spec(path, false);
62921dfcd9dSEnrico Granata     plugin_file_spec.ResolvePath();
63021dfcd9dSEnrico Granata 
6313cf443ddSMichael Sartain     if (plugin_file_spec.GetFileNameExtension() != g_dylibext &&
632b9c1b51eSKate Stone         plugin_file_spec.GetFileNameExtension() != g_solibext) {
63335e4c84cSJonas Devlieghere       return FileSystem::eEnumerateDirectoryResultNext;
6343cf443ddSMichael Sartain     }
63521dfcd9dSEnrico Granata 
63697206d57SZachary Turner     Status plugin_load_error;
637e743c782SEnrico Granata     debugger->LoadPlugin(plugin_file_spec, plugin_load_error);
63821dfcd9dSEnrico Granata 
63935e4c84cSJonas Devlieghere     return FileSystem::eEnumerateDirectoryResultNext;
6407d86ee5aSZachary Turner   } else if (ft == fs::file_type::directory_file ||
6417d86ee5aSZachary Turner              ft == fs::file_type::symlink_file ||
6427d86ee5aSZachary Turner              ft == fs::file_type::type_unknown) {
64305097246SAdrian Prantl     // Try and recurse into anything that a directory or symbolic link. We must
64405097246SAdrian Prantl     // also do this for unknown as sometimes the directory enumeration might be
64505097246SAdrian Prantl     // enumerating a file system that doesn't have correct file type
64621dfcd9dSEnrico Granata     // information.
64735e4c84cSJonas Devlieghere     return FileSystem::eEnumerateDirectoryResultEnter;
64821dfcd9dSEnrico Granata   }
64921dfcd9dSEnrico Granata 
65035e4c84cSJonas Devlieghere   return FileSystem::eEnumerateDirectoryResultNext;
65121dfcd9dSEnrico Granata }
65221dfcd9dSEnrico Granata 
653b9c1b51eSKate Stone void Debugger::InstanceInitialize() {
65421dfcd9dSEnrico Granata   const bool find_directories = true;
65521dfcd9dSEnrico Granata   const bool find_files = true;
65621dfcd9dSEnrico Granata   const bool find_other = true;
65721dfcd9dSEnrico Granata   char dir_path[PATH_MAX];
65860f028ffSPavel Labath   if (FileSpec dir_spec = HostInfo::GetSystemPluginDir()) {
659*dbd7fabaSJonas Devlieghere     if (FileSystem::Instance().Exists(dir_spec) &&
660*dbd7fabaSJonas Devlieghere         dir_spec.GetPath(dir_path, sizeof(dir_path))) {
66135e4c84cSJonas Devlieghere       FileSystem::Instance().EnumerateDirectory(dir_path, find_directories,
66235e4c84cSJonas Devlieghere                                                 find_files, find_other,
66335e4c84cSJonas Devlieghere                                                 LoadPluginCallback, this);
66421dfcd9dSEnrico Granata     }
66521dfcd9dSEnrico Granata   }
66621dfcd9dSEnrico Granata 
66760f028ffSPavel Labath   if (FileSpec dir_spec = HostInfo::GetUserPluginDir()) {
668*dbd7fabaSJonas Devlieghere     if (FileSystem::Instance().Exists(dir_spec) &&
669*dbd7fabaSJonas Devlieghere         dir_spec.GetPath(dir_path, sizeof(dir_path))) {
67035e4c84cSJonas Devlieghere       FileSystem::Instance().EnumerateDirectory(dir_path, find_directories,
67135e4c84cSJonas Devlieghere                                                 find_files, find_other,
67235e4c84cSJonas Devlieghere                                                 LoadPluginCallback, this);
67321dfcd9dSEnrico Granata     }
67421dfcd9dSEnrico Granata   }
675e8cd0c98SGreg Clayton 
676e8cd0c98SGreg Clayton   PluginManager::DebuggerInitialize(*this);
67721dfcd9dSEnrico Granata }
67821dfcd9dSEnrico Granata 
679b9c1b51eSKate Stone DebuggerSP Debugger::CreateInstance(lldb::LogOutputCallback log_callback,
680b9c1b51eSKate Stone                                     void *baton) {
681228063cdSJim Ingham   DebuggerSP debugger_sp(new Debugger(log_callback, baton));
682b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
6836c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
6846c42e063SGreg Clayton     g_debugger_list_ptr->push_back(debugger_sp);
6856611103cSGreg Clayton   }
68621dfcd9dSEnrico Granata   debugger_sp->InstanceInitialize();
6876611103cSGreg Clayton   return debugger_sp;
6886611103cSGreg Clayton }
6896611103cSGreg Clayton 
690b9c1b51eSKate Stone void Debugger::Destroy(DebuggerSP &debugger_sp) {
691df370550SEugene Zelenko   if (!debugger_sp)
692e02657b1SCaroline Tice     return;
693e02657b1SCaroline Tice 
6948314c525SJim Ingham   debugger_sp->Clear();
6958314c525SJim Ingham 
696b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
6976c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
6986c42e063SGreg Clayton     DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
699b9c1b51eSKate Stone     for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
700b9c1b51eSKate Stone       if ((*pos).get() == debugger_sp.get()) {
7016c42e063SGreg Clayton         g_debugger_list_ptr->erase(pos);
702e02657b1SCaroline Tice         return;
703e02657b1SCaroline Tice       }
704e02657b1SCaroline Tice     }
705e02657b1SCaroline Tice   }
706c15f55e2SGreg Clayton }
707e02657b1SCaroline Tice 
7084d122c40SGreg Clayton DebuggerSP
709b9c1b51eSKate Stone Debugger::FindDebuggerWithInstanceName(const ConstString &instance_name) {
7104d122c40SGreg Clayton   DebuggerSP debugger_sp;
711b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
7126c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
7136c42e063SGreg Clayton     DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
714b9c1b51eSKate Stone     for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
715b9c1b51eSKate Stone       if ((*pos)->m_instance_name == instance_name) {
7166920b52bSGreg Clayton         debugger_sp = *pos;
7176920b52bSGreg Clayton         break;
7186920b52bSGreg Clayton       }
7196920b52bSGreg Clayton     }
7206920b52bSGreg Clayton   }
7213df9a8dfSCaroline Tice   return debugger_sp;
7223df9a8dfSCaroline Tice }
7236611103cSGreg Clayton 
724b9c1b51eSKate Stone TargetSP Debugger::FindTargetWithProcessID(lldb::pid_t pid) {
7254d122c40SGreg Clayton   TargetSP target_sp;
726b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
7276c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
7286c42e063SGreg Clayton     DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
729b9c1b51eSKate Stone     for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
7306611103cSGreg Clayton       target_sp = (*pos)->GetTargetList().FindTargetWithProcessID(pid);
7316611103cSGreg Clayton       if (target_sp)
7326611103cSGreg Clayton         break;
7336611103cSGreg Clayton     }
734c15f55e2SGreg Clayton   }
7356611103cSGreg Clayton   return target_sp;
7366611103cSGreg Clayton }
7376611103cSGreg Clayton 
738b9c1b51eSKate Stone TargetSP Debugger::FindTargetWithProcess(Process *process) {
739e4e45924SGreg Clayton   TargetSP target_sp;
740b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
7416c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
7426c42e063SGreg Clayton     DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
743b9c1b51eSKate Stone     for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
744e4e45924SGreg Clayton       target_sp = (*pos)->GetTargetList().FindTargetWithProcess(process);
745e4e45924SGreg Clayton       if (target_sp)
746e4e45924SGreg Clayton         break;
747e4e45924SGreg Clayton     }
748c15f55e2SGreg Clayton   }
749e4e45924SGreg Clayton   return target_sp;
750e4e45924SGreg Clayton }
751e4e45924SGreg Clayton 
752b9c1b51eSKate Stone Debugger::Debugger(lldb::LogOutputCallback log_callback, void *baton)
753b9c1b51eSKate Stone     : UserID(g_unique_id++),
7542f3df613SZachary Turner       Properties(std::make_shared<OptionValueProperties>()),
7552f3df613SZachary Turner       m_input_file_sp(std::make_shared<StreamFile>(stdin, false)),
7562f3df613SZachary Turner       m_output_file_sp(std::make_shared<StreamFile>(stdout, false)),
7572f3df613SZachary Turner       m_error_file_sp(std::make_shared<StreamFile>(stderr, false)),
758583bbb1dSJim Ingham       m_broadcaster_manager_sp(BroadcasterManager::MakeBroadcasterManager()),
759b9c1b51eSKate Stone       m_terminal_state(), m_target_list(*this), m_platform_list(),
760583bbb1dSJim Ingham       m_listener_sp(Listener::MakeListener("lldb.Debugger")),
761b9c1b51eSKate Stone       m_source_manager_ap(), m_source_file_cache(),
7622f3df613SZachary Turner       m_command_interpreter_ap(llvm::make_unique<CommandInterpreter>(
7632f3df613SZachary Turner           *this, eScriptLanguageDefault, false)),
764b9c1b51eSKate Stone       m_input_reader_stack(), m_instance_name(), m_loaded_plugins(),
765b9c1b51eSKate Stone       m_event_handler_thread(), m_io_handler_thread(),
7664329fe42SGreg Clayton       m_sync_broadcaster(nullptr, "lldb.debugger.sync"),
767b9c1b51eSKate Stone       m_forward_listener_sp(), m_clear_once() {
76867cc0636SGreg Clayton   char instance_cstr[256];
76967cc0636SGreg Clayton   snprintf(instance_cstr, sizeof(instance_cstr), "debugger_%d", (int)GetID());
77067cc0636SGreg Clayton   m_instance_name.SetCString(instance_cstr);
771228063cdSJim Ingham   if (log_callback)
7722f3df613SZachary Turner     m_log_callback_stream_sp =
7732f3df613SZachary Turner         std::make_shared<StreamCallback>(log_callback, baton);
7746611103cSGreg Clayton   m_command_interpreter_ap->Initialize();
775ded470d3SGreg Clayton   // Always add our default platform to the platform list
776615eb7e6SGreg Clayton   PlatformSP default_platform_sp(Platform::GetHostPlatform());
777df370550SEugene Zelenko   assert(default_platform_sp);
778ded470d3SGreg Clayton   m_platform_list.Append(default_platform_sp, true);
77967cc0636SGreg Clayton 
780754a9369SGreg Clayton   m_collection_sp->Initialize(g_properties);
781b9c1b51eSKate Stone   m_collection_sp->AppendProperty(
782b9c1b51eSKate Stone       ConstString("target"),
783b9c1b51eSKate Stone       ConstString("Settings specify to debugging targets."), true,
78467cc0636SGreg Clayton       Target::GetGlobalProperties()->GetValueProperties());
785b9c1b51eSKate Stone   m_collection_sp->AppendProperty(
786b9c1b51eSKate Stone       ConstString("platform"), ConstString("Platform settings."), true,
78763acdfdeSOleksiy Vyalov       Platform::GetGlobalPlatformProperties()->GetValueProperties());
788235354beSAdrian Prantl   m_collection_sp->AppendProperty(
7893cd29bcfSAdrian Prantl       ConstString("symbols"), ConstString("Symbol lookup and cache settings."),
7903cd29bcfSAdrian Prantl       true, ModuleList::GetGlobalModuleListProperties().GetValueProperties());
791b9c1b51eSKate Stone   if (m_command_interpreter_ap) {
792b9c1b51eSKate Stone     m_collection_sp->AppendProperty(
793b9c1b51eSKate Stone         ConstString("interpreter"),
794754a9369SGreg Clayton         ConstString("Settings specify to the debugger's command interpreter."),
795b9c1b51eSKate Stone         true, m_command_interpreter_ap->GetValueProperties());
796754a9369SGreg Clayton   }
797b9c1b51eSKate Stone   OptionValueSInt64 *term_width =
798b9c1b51eSKate Stone       m_collection_sp->GetPropertyAtIndexAsOptionValueSInt64(
799b9c1b51eSKate Stone           nullptr, ePropertyTerminalWidth);
80067cc0636SGreg Clayton   term_width->SetMinimumValue(10);
80167cc0636SGreg Clayton   term_width->SetMaximumValue(1024);
802c3ce7f27SMichael Sartain 
803c3ce7f27SMichael Sartain   // Turn off use-color if this is a dumb terminal.
804c3ce7f27SMichael Sartain   const char *term = getenv("TERM");
805c3ce7f27SMichael Sartain   if (term && !strcmp(term, "dumb"))
806c3ce7f27SMichael Sartain     SetUseColor(false);
807eca9ce14SRaphael Isemann   // Turn off use-color if we don't write to a terminal with color support.
808eca9ce14SRaphael Isemann   if (!m_output_file_sp->GetFile().GetIsTerminalWithColors())
809eca9ce14SRaphael Isemann     SetUseColor(false);
8108aa23614SDavid Bolvansky 
8118aa23614SDavid Bolvansky #if defined(_WIN32) && defined(ENABLE_VIRTUAL_TERMINAL_PROCESSING)
8128aa23614SDavid Bolvansky   // Enabling use of ANSI color codes because LLDB is using them to highlight
8138aa23614SDavid Bolvansky   // text.
8148aa23614SDavid Bolvansky   llvm::sys::Process::UseANSIEscapeCodes(true);
8158aa23614SDavid Bolvansky #endif
81630fdc8d8SChris Lattner }
81730fdc8d8SChris Lattner 
818b9c1b51eSKate Stone Debugger::~Debugger() { Clear(); }
8198314c525SJim Ingham 
820b9c1b51eSKate Stone void Debugger::Clear() {
8214329fe42SGreg Clayton   //----------------------------------------------------------------------
82205097246SAdrian Prantl   // Make sure we call this function only once. With the C++ global destructor
82305097246SAdrian Prantl   // chain having a list of debuggers and with code that can be running on
82405097246SAdrian Prantl   // other threads, we need to ensure this doesn't happen multiple times.
8254329fe42SGreg Clayton   //
8264329fe42SGreg Clayton   // The following functions call Debugger::Clear():
8274329fe42SGreg Clayton   //     Debugger::~Debugger();
8284329fe42SGreg Clayton   //     static void Debugger::Destroy(lldb::DebuggerSP &debugger_sp);
8294329fe42SGreg Clayton   //     static void Debugger::Terminate();
8304329fe42SGreg Clayton   //----------------------------------------------------------------------
831c5f28e2aSKamil Rytarowski   llvm::call_once(m_clear_once, [this]() {
83244d93782SGreg Clayton     ClearIOHandlers();
83344d93782SGreg Clayton     StopIOHandlerThread();
83444d93782SGreg Clayton     StopEventHandlerThread();
835583bbb1dSJim Ingham     m_listener_sp->Clear();
8366611103cSGreg Clayton     int num_targets = m_target_list.GetNumTargets();
837b9c1b51eSKate Stone     for (int i = 0; i < num_targets; i++) {
838ccbc08e6SGreg Clayton       TargetSP target_sp(m_target_list.GetTargetAtIndex(i));
839b9c1b51eSKate Stone       if (target_sp) {
840ccbc08e6SGreg Clayton         ProcessSP process_sp(target_sp->GetProcessSP());
8416611103cSGreg Clayton         if (process_sp)
8421fd07059SJim Ingham           process_sp->Finalize();
843ccbc08e6SGreg Clayton         target_sp->Destroy();
8446611103cSGreg Clayton       }
84530fdc8d8SChris Lattner     }
846583bbb1dSJim Ingham     m_broadcaster_manager_sp->Clear();
84730fdc8d8SChris Lattner 
848b9c1b51eSKate Stone     // Close the input file _before_ we close the input read communications
84905097246SAdrian Prantl     // class as it does NOT own the input file, our m_input_file does.
850c5917d9aSJim Ingham     m_terminal_state.Clear();
85144d93782SGreg Clayton     if (m_input_file_sp)
85244d93782SGreg Clayton       m_input_file_sp->GetFile().Close();
8530c4129f2SGreg Clayton 
8540c4129f2SGreg Clayton     m_command_interpreter_ap->Clear();
8554329fe42SGreg Clayton   });
8568314c525SJim Ingham }
85730fdc8d8SChris Lattner 
858b9c1b51eSKate Stone bool Debugger::GetCloseInputOnEOF() const {
85944d93782SGreg Clayton   //    return m_input_comm.GetCloseOnEOF();
86044d93782SGreg Clayton   return false;
861fc3f027dSGreg Clayton }
862fc3f027dSGreg Clayton 
863b9c1b51eSKate Stone void Debugger::SetCloseInputOnEOF(bool b) {
86444d93782SGreg Clayton   //    m_input_comm.SetCloseOnEOF(b);
865fc3f027dSGreg Clayton }
866fc3f027dSGreg Clayton 
867b9c1b51eSKate Stone bool Debugger::GetAsyncExecution() {
8686611103cSGreg Clayton   return !m_command_interpreter_ap->GetSynchronous();
86930fdc8d8SChris Lattner }
87030fdc8d8SChris Lattner 
871b9c1b51eSKate Stone void Debugger::SetAsyncExecution(bool async_execution) {
8726611103cSGreg Clayton   m_command_interpreter_ap->SetSynchronous(!async_execution);
87330fdc8d8SChris Lattner }
87430fdc8d8SChris Lattner 
875b9c1b51eSKate Stone void Debugger::SetInputFileHandle(FILE *fh, bool tranfer_ownership) {
87644d93782SGreg Clayton   if (m_input_file_sp)
87744d93782SGreg Clayton     m_input_file_sp->GetFile().SetStream(fh, tranfer_ownership);
87844d93782SGreg Clayton   else
8792f3df613SZachary Turner     m_input_file_sp = std::make_shared<StreamFile>(fh, tranfer_ownership);
88044d93782SGreg Clayton 
88144d93782SGreg Clayton   File &in_file = m_input_file_sp->GetFile();
882df370550SEugene Zelenko   if (!in_file.IsValid())
88351b1e2d2SGreg Clayton     in_file.SetStream(stdin, true);
88430fdc8d8SChris Lattner 
88505097246SAdrian Prantl   // Save away the terminal state if that is relevant, so that we can restore
88605097246SAdrian Prantl   // it in RestoreInputState.
887c5917d9aSJim Ingham   SaveInputTerminalState();
88830fdc8d8SChris Lattner }
88930fdc8d8SChris Lattner 
890b9c1b51eSKate Stone void Debugger::SetOutputFileHandle(FILE *fh, bool tranfer_ownership) {
89144d93782SGreg Clayton   if (m_output_file_sp)
89244d93782SGreg Clayton     m_output_file_sp->GetFile().SetStream(fh, tranfer_ownership);
89344d93782SGreg Clayton   else
8942f3df613SZachary Turner     m_output_file_sp = std::make_shared<StreamFile>(fh, tranfer_ownership);
89544d93782SGreg Clayton 
89644d93782SGreg Clayton   File &out_file = m_output_file_sp->GetFile();
897df370550SEugene Zelenko   if (!out_file.IsValid())
89851b1e2d2SGreg Clayton     out_file.SetStream(stdout, false);
8992f88aadfSCaroline Tice 
90005097246SAdrian Prantl   // do not create the ScriptInterpreter just for setting the output file
90105097246SAdrian Prantl   // handle as the constructor will know how to do the right thing on its own
902b588726eSEnrico Granata   const bool can_create = false;
903b9c1b51eSKate Stone   ScriptInterpreter *script_interpreter =
904b9c1b51eSKate Stone       GetCommandInterpreter().GetScriptInterpreter(can_create);
905b588726eSEnrico Granata   if (script_interpreter)
906b588726eSEnrico Granata     script_interpreter->ResetOutputFileHandle(fh);
90730fdc8d8SChris Lattner }
90830fdc8d8SChris Lattner 
909b9c1b51eSKate Stone void Debugger::SetErrorFileHandle(FILE *fh, bool tranfer_ownership) {
91044d93782SGreg Clayton   if (m_error_file_sp)
91144d93782SGreg Clayton     m_error_file_sp->GetFile().SetStream(fh, tranfer_ownership);
91244d93782SGreg Clayton   else
9132f3df613SZachary Turner     m_error_file_sp = std::make_shared<StreamFile>(fh, tranfer_ownership);
91444d93782SGreg Clayton 
91544d93782SGreg Clayton   File &err_file = m_error_file_sp->GetFile();
916df370550SEugene Zelenko   if (!err_file.IsValid())
91751b1e2d2SGreg Clayton     err_file.SetStream(stderr, false);
91830fdc8d8SChris Lattner }
91930fdc8d8SChris Lattner 
920b9c1b51eSKate Stone void Debugger::SaveInputTerminalState() {
921b9c1b51eSKate Stone   if (m_input_file_sp) {
92244d93782SGreg Clayton     File &in_file = m_input_file_sp->GetFile();
923c5917d9aSJim Ingham     if (in_file.GetDescriptor() != File::kInvalidDescriptor)
924c5917d9aSJim Ingham       m_terminal_state.Save(in_file.GetDescriptor(), true);
925c5917d9aSJim Ingham   }
92644d93782SGreg Clayton }
927c5917d9aSJim Ingham 
928b9c1b51eSKate Stone void Debugger::RestoreInputTerminalState() { m_terminal_state.Restore(); }
929c5917d9aSJim Ingham 
930b9c1b51eSKate Stone ExecutionContext Debugger::GetSelectedExecutionContext() {
93130fdc8d8SChris Lattner   ExecutionContext exe_ctx;
932c14ee32dSGreg Clayton   TargetSP target_sp(GetSelectedTarget());
933c14ee32dSGreg Clayton   exe_ctx.SetTargetSP(target_sp);
93430fdc8d8SChris Lattner 
935b9c1b51eSKate Stone   if (target_sp) {
936c14ee32dSGreg Clayton     ProcessSP process_sp(target_sp->GetProcessSP());
937c14ee32dSGreg Clayton     exe_ctx.SetProcessSP(process_sp);
938b9c1b51eSKate Stone     if (process_sp && !process_sp->IsRunning()) {
939c14ee32dSGreg Clayton       ThreadSP thread_sp(process_sp->GetThreadList().GetSelectedThread());
940b9c1b51eSKate Stone       if (thread_sp) {
941c14ee32dSGreg Clayton         exe_ctx.SetThreadSP(thread_sp);
942c14ee32dSGreg Clayton         exe_ctx.SetFrameSP(thread_sp->GetSelectedFrame());
943df370550SEugene Zelenko         if (exe_ctx.GetFramePtr() == nullptr)
944c14ee32dSGreg Clayton           exe_ctx.SetFrameSP(thread_sp->GetStackFrameAtIndex(0));
94530fdc8d8SChris Lattner       }
94630fdc8d8SChris Lattner     }
94730fdc8d8SChris Lattner   }
94830fdc8d8SChris Lattner   return exe_ctx;
94930fdc8d8SChris Lattner }
95030fdc8d8SChris Lattner 
951b9c1b51eSKate Stone void Debugger::DispatchInputInterrupt() {
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->Interrupt();
956efed6131SCaroline Tice }
957efed6131SCaroline Tice 
958b9c1b51eSKate Stone void Debugger::DispatchInputEndOfFile() {
95916ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex());
96044d93782SGreg Clayton   IOHandlerSP reader_sp(m_input_reader_stack.Top());
961efed6131SCaroline Tice   if (reader_sp)
96244d93782SGreg Clayton     reader_sp->GotEOF();
963efed6131SCaroline Tice }
964efed6131SCaroline Tice 
965b9c1b51eSKate Stone void Debugger::ClearIOHandlers() {
966b9c1b51eSKate Stone   // The bottom input reader should be the main debugger input reader.  We do
967b9c1b51eSKate Stone   // not want to close that one here.
96816ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex());
969b9c1b51eSKate Stone   while (m_input_reader_stack.GetSize() > 1) {
97044d93782SGreg Clayton     IOHandlerSP reader_sp(m_input_reader_stack.Top());
9713d6086f6SCaroline Tice     if (reader_sp)
9724446487dSPavel Labath       PopIOHandler(reader_sp);
9733d6086f6SCaroline Tice   }
9743d6086f6SCaroline Tice }
9753d6086f6SCaroline Tice 
976b9c1b51eSKate Stone void Debugger::ExecuteIOHandlers() {
977b9c1b51eSKate Stone   while (true) {
97844d93782SGreg Clayton     IOHandlerSP reader_sp(m_input_reader_stack.Top());
97930fdc8d8SChris Lattner     if (!reader_sp)
98030fdc8d8SChris Lattner       break;
98130fdc8d8SChris Lattner 
98244d93782SGreg Clayton     reader_sp->Run();
98344d93782SGreg Clayton 
98444d93782SGreg Clayton     // Remove all input readers that are done from the top of the stack
985b9c1b51eSKate Stone     while (true) {
98644d93782SGreg Clayton       IOHandlerSP top_reader_sp = m_input_reader_stack.Top();
98744d93782SGreg Clayton       if (top_reader_sp && top_reader_sp->GetIsDone())
9884446487dSPavel Labath         PopIOHandler(top_reader_sp);
98930fdc8d8SChris Lattner       else
99030fdc8d8SChris Lattner         break;
99130fdc8d8SChris Lattner     }
99230fdc8d8SChris Lattner   }
99344d93782SGreg Clayton   ClearIOHandlers();
99444d93782SGreg Clayton }
99530fdc8d8SChris Lattner 
996b9c1b51eSKate Stone bool Debugger::IsTopIOHandler(const lldb::IOHandlerSP &reader_sp) {
99744d93782SGreg Clayton   return m_input_reader_stack.IsTop(reader_sp);
99844d93782SGreg Clayton }
99930fdc8d8SChris Lattner 
1000b9c1b51eSKate Stone bool Debugger::CheckTopIOHandlerTypes(IOHandler::Type top_type,
1001b9c1b51eSKate Stone                                       IOHandler::Type second_top_type) {
10026681041dSSean Callanan   return m_input_reader_stack.CheckTopIOHandlerTypes(top_type, second_top_type);
10036681041dSSean Callanan }
10046681041dSSean Callanan 
1005b9c1b51eSKate Stone void Debugger::PrintAsync(const char *s, size_t len, bool is_stdout) {
10064446487dSPavel Labath   lldb::StreamFileSP stream = is_stdout ? GetOutputFile() : GetErrorFile();
10074446487dSPavel Labath   m_input_reader_stack.PrintAsync(stream.get(), s, len);
10084446487dSPavel Labath }
100944d93782SGreg Clayton 
1010b9c1b51eSKate Stone ConstString Debugger::GetTopIOHandlerControlSequence(char ch) {
101144d93782SGreg Clayton   return m_input_reader_stack.GetTopIOHandlerControlSequence(ch);
101230fdc8d8SChris Lattner }
101330fdc8d8SChris Lattner 
1014b9c1b51eSKate Stone const char *Debugger::GetIOHandlerCommandPrefix() {
1015a487aa4cSKate Stone   return m_input_reader_stack.GetTopIOHandlerCommandPrefix();
1016a487aa4cSKate Stone }
1017a487aa4cSKate Stone 
1018b9c1b51eSKate Stone const char *Debugger::GetIOHandlerHelpPrologue() {
1019a487aa4cSKate Stone   return m_input_reader_stack.GetTopIOHandlerHelpPrologue();
1020a487aa4cSKate Stone }
1021a487aa4cSKate Stone 
1022b9c1b51eSKate Stone void Debugger::RunIOHandler(const IOHandlerSP &reader_sp) {
102344d93782SGreg Clayton   PushIOHandler(reader_sp);
1024577508dfSGreg Clayton 
1025577508dfSGreg Clayton   IOHandlerSP top_reader_sp = reader_sp;
1026b9c1b51eSKate Stone   while (top_reader_sp) {
1027577508dfSGreg Clayton     top_reader_sp->Run();
1028577508dfSGreg Clayton 
1029b9c1b51eSKate Stone     if (top_reader_sp.get() == reader_sp.get()) {
1030577508dfSGreg Clayton       if (PopIOHandler(reader_sp))
1031577508dfSGreg Clayton         break;
1032577508dfSGreg Clayton     }
1033577508dfSGreg Clayton 
1034b9c1b51eSKate Stone     while (true) {
1035577508dfSGreg Clayton       top_reader_sp = m_input_reader_stack.Top();
1036577508dfSGreg Clayton       if (top_reader_sp && top_reader_sp->GetIsDone())
10374446487dSPavel Labath         PopIOHandler(top_reader_sp);
1038577508dfSGreg Clayton       else
1039577508dfSGreg Clayton         break;
1040577508dfSGreg Clayton     }
1041577508dfSGreg Clayton   }
104244d93782SGreg Clayton }
104344d93782SGreg Clayton 
1044b9c1b51eSKate Stone void Debugger::AdoptTopIOHandlerFilesIfInvalid(StreamFileSP &in,
1045b9c1b51eSKate Stone                                                StreamFileSP &out,
1046b9c1b51eSKate Stone                                                StreamFileSP &err) {
104705097246SAdrian Prantl   // Before an IOHandler runs, it must have in/out/err streams. This function
104805097246SAdrian Prantl   // is called when one ore more of the streams are nullptr. We use the top
104905097246SAdrian Prantl   // input reader's in/out/err streams, or fall back to the debugger file
105005097246SAdrian Prantl   // handles, or we fall back onto stdin/stdout/stderr as a last resort.
105144d93782SGreg Clayton 
105216ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex());
105344d93782SGreg Clayton   IOHandlerSP top_reader_sp(m_input_reader_stack.Top());
105444d93782SGreg Clayton   // If no STDIN has been set, then set it appropriately
1055b9c1b51eSKate Stone   if (!in) {
105644d93782SGreg Clayton     if (top_reader_sp)
105744d93782SGreg Clayton       in = top_reader_sp->GetInputStreamFile();
105844d93782SGreg Clayton     else
105944d93782SGreg Clayton       in = GetInputFile();
106044d93782SGreg Clayton 
106144d93782SGreg Clayton     // If there is nothing, use stdin
106244d93782SGreg Clayton     if (!in)
10632f3df613SZachary Turner       in = std::make_shared<StreamFile>(stdin, false);
106444d93782SGreg Clayton   }
106544d93782SGreg Clayton   // If no STDOUT has been set, then set it appropriately
1066b9c1b51eSKate Stone   if (!out) {
106744d93782SGreg Clayton     if (top_reader_sp)
106844d93782SGreg Clayton       out = top_reader_sp->GetOutputStreamFile();
106944d93782SGreg Clayton     else
107044d93782SGreg Clayton       out = GetOutputFile();
107144d93782SGreg Clayton 
107244d93782SGreg Clayton     // If there is nothing, use stdout
107344d93782SGreg Clayton     if (!out)
10742f3df613SZachary Turner       out = std::make_shared<StreamFile>(stdout, false);
107544d93782SGreg Clayton   }
107644d93782SGreg Clayton   // If no STDERR has been set, then set it appropriately
1077b9c1b51eSKate Stone   if (!err) {
107844d93782SGreg Clayton     if (top_reader_sp)
107944d93782SGreg Clayton       err = top_reader_sp->GetErrorStreamFile();
108044d93782SGreg Clayton     else
108144d93782SGreg Clayton       err = GetErrorFile();
108244d93782SGreg Clayton 
108344d93782SGreg Clayton     // If there is nothing, use stderr
108444d93782SGreg Clayton     if (!err)
10852f3df613SZachary Turner       err = std::make_shared<StreamFile>(stdout, false);
108644d93782SGreg Clayton   }
108744d93782SGreg Clayton }
108844d93782SGreg Clayton 
1089c01783a8SRaphael Isemann void Debugger::PushIOHandler(const IOHandlerSP &reader_sp,
1090c01783a8SRaphael Isemann                              bool cancel_top_handler) {
109130fdc8d8SChris Lattner   if (!reader_sp)
109230fdc8d8SChris Lattner     return;
1093b44880caSCaroline Tice 
109416ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex());
10954446487dSPavel Labath 
10964446487dSPavel Labath   // Get the current top input reader...
109744d93782SGreg Clayton   IOHandlerSP top_reader_sp(m_input_reader_stack.Top());
1098b44880caSCaroline Tice 
1099b4874f1aSGreg Clayton   // Don't push the same IO handler twice...
11004446487dSPavel Labath   if (reader_sp == top_reader_sp)
11014446487dSPavel Labath     return;
11024446487dSPavel Labath 
110344d93782SGreg Clayton   // Push our new input reader
1104d5a0a01bSCaroline Tice   m_input_reader_stack.Push(reader_sp);
11054446487dSPavel Labath   reader_sp->Activate();
110644d93782SGreg Clayton 
110705097246SAdrian Prantl   // Interrupt the top input reader to it will exit its Run() function and let
110805097246SAdrian Prantl   // this new input reader take over
1109b9c1b51eSKate Stone   if (top_reader_sp) {
111044d93782SGreg Clayton     top_reader_sp->Deactivate();
1111c01783a8SRaphael Isemann     if (cancel_top_handler)
11124446487dSPavel Labath       top_reader_sp->Cancel();
111330fdc8d8SChris Lattner   }
1114b4874f1aSGreg Clayton }
111530fdc8d8SChris Lattner 
1116b9c1b51eSKate Stone bool Debugger::PopIOHandler(const IOHandlerSP &pop_reader_sp) {
11174446487dSPavel Labath   if (!pop_reader_sp)
11184446487dSPavel Labath     return false;
111930fdc8d8SChris Lattner 
112016ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex());
112144d93782SGreg Clayton 
112205097246SAdrian Prantl   // The reader on the stop of the stack is done, so let the next read on the
112305097246SAdrian Prantl   // stack refresh its prompt and if there is one...
11244446487dSPavel Labath   if (m_input_reader_stack.IsEmpty())
11254446487dSPavel Labath     return false;
11264446487dSPavel Labath 
112744d93782SGreg Clayton   IOHandlerSP reader_sp(m_input_reader_stack.Top());
112830fdc8d8SChris Lattner 
11294446487dSPavel Labath   if (pop_reader_sp != reader_sp)
11304446487dSPavel Labath     return false;
11314446487dSPavel Labath 
113244d93782SGreg Clayton   reader_sp->Deactivate();
1133b4874f1aSGreg Clayton   reader_sp->Cancel();
1134d5a0a01bSCaroline Tice   m_input_reader_stack.Pop();
113530fdc8d8SChris Lattner 
1136d5a0a01bSCaroline Tice   reader_sp = m_input_reader_stack.Top();
113730fdc8d8SChris Lattner   if (reader_sp)
113844d93782SGreg Clayton     reader_sp->Activate();
113944d93782SGreg Clayton 
114044d93782SGreg Clayton   return true;
114130fdc8d8SChris Lattner }
11426611103cSGreg Clayton 
1143b9c1b51eSKate Stone StreamSP Debugger::GetAsyncOutputStream() {
11442f3df613SZachary Turner   return std::make_shared<StreamAsynchronousIO>(*this, true);
11455b52f0c7SJim Ingham }
11465b52f0c7SJim Ingham 
1147b9c1b51eSKate Stone StreamSP Debugger::GetAsyncErrorStream() {
11482f3df613SZachary Turner   return std::make_shared<StreamAsynchronousIO>(*this, false);
11495b52f0c7SJim Ingham }
11505b52f0c7SJim Ingham 
1151b9c1b51eSKate Stone size_t Debugger::GetNumDebuggers() {
1152b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
11536c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
11546c42e063SGreg Clayton     return g_debugger_list_ptr->size();
1155061858ceSEnrico Granata   }
1156c15f55e2SGreg Clayton   return 0;
1157c15f55e2SGreg Clayton }
1158061858ceSEnrico Granata 
1159b9c1b51eSKate Stone lldb::DebuggerSP Debugger::GetDebuggerAtIndex(size_t index) {
1160061858ceSEnrico Granata   DebuggerSP debugger_sp;
1161061858ceSEnrico Granata 
1162b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
11636c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
11646c42e063SGreg Clayton     if (index < g_debugger_list_ptr->size())
11656c42e063SGreg Clayton       debugger_sp = g_debugger_list_ptr->at(index);
1166c15f55e2SGreg Clayton   }
1167061858ceSEnrico Granata 
1168061858ceSEnrico Granata   return debugger_sp;
1169061858ceSEnrico Granata }
1170061858ceSEnrico Granata 
1171b9c1b51eSKate Stone DebuggerSP Debugger::FindDebuggerWithID(lldb::user_id_t id) {
11724d122c40SGreg Clayton   DebuggerSP debugger_sp;
1173ebc1bb27SCaroline Tice 
1174b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
11756c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
11766c42e063SGreg Clayton     DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
1177b9c1b51eSKate Stone     for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
1178b9c1b51eSKate Stone       if ((*pos)->GetID() == id) {
1179ebc1bb27SCaroline Tice         debugger_sp = *pos;
1180ebc1bb27SCaroline Tice         break;
1181ebc1bb27SCaroline Tice       }
1182ebc1bb27SCaroline Tice     }
1183c15f55e2SGreg Clayton   }
1184ebc1bb27SCaroline Tice   return debugger_sp;
1185ebc1bb27SCaroline Tice }
11863df9a8dfSCaroline Tice 
1187b9c1b51eSKate Stone bool Debugger::FormatDisassemblerAddress(const FormatEntity::Entry *format,
1188aff1b357SJason Molenda                                          const SymbolContext *sc,
1189aff1b357SJason Molenda                                          const SymbolContext *prev_sc,
1190aff1b357SJason Molenda                                          const ExecutionContext *exe_ctx,
1191b9c1b51eSKate Stone                                          const Address *addr, Stream &s) {
1192554f68d3SGreg Clayton   FormatEntity::Entry format_entry;
1193554f68d3SGreg Clayton 
1194b9c1b51eSKate Stone   if (format == nullptr) {
1195df370550SEugene Zelenko     if (exe_ctx != nullptr && exe_ctx->HasTargetScope())
1196aff1b357SJason Molenda       format = exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat();
1197b9c1b51eSKate Stone     if (format == nullptr) {
1198554f68d3SGreg Clayton       FormatEntity::Parse("${addr}: ", format_entry);
1199554f68d3SGreg Clayton       format = &format_entry;
1200554f68d3SGreg Clayton     }
1201aff1b357SJason Molenda   }
1202aff1b357SJason Molenda   bool function_changed = false;
1203aff1b357SJason Molenda   bool initial_function = false;
1204b9c1b51eSKate Stone   if (prev_sc && (prev_sc->function || prev_sc->symbol)) {
1205b9c1b51eSKate Stone     if (sc && (sc->function || sc->symbol)) {
1206b9c1b51eSKate Stone       if (prev_sc->symbol && sc->symbol) {
1207b9c1b51eSKate Stone         if (!sc->symbol->Compare(prev_sc->symbol->GetName(),
1208b9c1b51eSKate Stone                                  prev_sc->symbol->GetType())) {
1209aff1b357SJason Molenda           function_changed = true;
1210aff1b357SJason Molenda         }
1211b9c1b51eSKate Stone       } else if (prev_sc->function && sc->function) {
1212b9c1b51eSKate Stone         if (prev_sc->function->GetMangled() != sc->function->GetMangled()) {
1213aff1b357SJason Molenda           function_changed = true;
1214aff1b357SJason Molenda         }
1215aff1b357SJason Molenda       }
1216aff1b357SJason Molenda     }
1217aff1b357SJason Molenda   }
121805097246SAdrian Prantl   // The first context on a list of instructions will have a prev_sc that has
121905097246SAdrian Prantl   // no Function or Symbol -- if SymbolContext had an IsValid() method, it
1220aff1b357SJason Molenda   // would return false.  But we do get a prev_sc pointer.
1221b9c1b51eSKate Stone   if ((sc && (sc->function || sc->symbol)) && prev_sc &&
1222b9c1b51eSKate Stone       (prev_sc->function == nullptr && prev_sc->symbol == nullptr)) {
1223aff1b357SJason Molenda     initial_function = true;
1224aff1b357SJason Molenda   }
1225b9c1b51eSKate Stone   return FormatEntity::Format(*format, s, sc, exe_ctx, addr, nullptr,
1226b9c1b51eSKate Stone                               function_changed, initial_function);
1227aff1b357SJason Molenda }
1228aff1b357SJason Molenda 
1229b9c1b51eSKate Stone void Debugger::SetLoggingCallback(lldb::LogOutputCallback log_callback,
1230b9c1b51eSKate Stone                                   void *baton) {
12314f02b22dSJim Ingham   // For simplicity's sake, I am not going to deal with how to close down any
12324f02b22dSJim Ingham   // open logging streams, I just redirect everything from here on out to the
12334f02b22dSJim Ingham   // callback.
12342f3df613SZachary Turner   m_log_callback_stream_sp =
12352f3df613SZachary Turner       std::make_shared<StreamCallback>(log_callback, baton);
1236228063cdSJim Ingham }
1237228063cdSJim Ingham 
12385e336903SPavel Labath bool Debugger::EnableLog(llvm::StringRef channel,
12395e336903SPavel Labath                          llvm::ArrayRef<const char *> categories,
12405e336903SPavel Labath                          llvm::StringRef log_file, uint32_t log_options,
1241775588c0SPavel Labath                          llvm::raw_ostream &error_stream) {
12425fae71c5SPavel Labath   const bool should_close = true;
12435fae71c5SPavel Labath   const bool unbuffered = true;
12445fae71c5SPavel Labath 
12455fae71c5SPavel Labath   std::shared_ptr<llvm::raw_ostream> log_stream_sp;
1246b9c1b51eSKate Stone   if (m_log_callback_stream_sp) {
1247228063cdSJim Ingham     log_stream_sp = m_log_callback_stream_sp;
1248228063cdSJim Ingham     // For now when using the callback mode you always get thread & timestamp.
1249b9c1b51eSKate Stone     log_options |=
1250b9c1b51eSKate Stone         LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_THREAD_NAME;
12515e336903SPavel Labath   } else if (log_file.empty()) {
12525fae71c5SPavel Labath     log_stream_sp = std::make_shared<llvm::raw_fd_ostream>(
12535fae71c5SPavel Labath         GetOutputFile()->GetFile().GetDescriptor(), !should_close, unbuffered);
1254b9c1b51eSKate Stone   } else {
12555fae71c5SPavel Labath     auto pos = m_log_streams.find(log_file);
1256c1b2ccfdSGreg Clayton     if (pos != m_log_streams.end())
1257c1b2ccfdSGreg Clayton       log_stream_sp = pos->second.lock();
1258b9c1b51eSKate Stone     if (!log_stream_sp) {
12595fae71c5SPavel Labath       llvm::sys::fs::OpenFlags flags = llvm::sys::fs::F_Text;
12605fae71c5SPavel Labath       if (log_options & LLDB_LOG_OPTION_APPEND)
12615fae71c5SPavel Labath         flags |= llvm::sys::fs::F_Append;
12625fae71c5SPavel Labath       int FD;
12631f67a3cbSZachary Turner       if (std::error_code ec = llvm::sys::fs::openFileForWrite(
12641f67a3cbSZachary Turner               log_file, FD, llvm::sys::fs::CD_CreateAlways, flags)) {
1265775588c0SPavel Labath         error_stream << "Unable to open log file: " << ec.message();
12665fae71c5SPavel Labath         return false;
12675fae71c5SPavel Labath       }
12682f3df613SZachary Turner       log_stream_sp =
12692f3df613SZachary Turner           std::make_shared<llvm::raw_fd_ostream>(FD, should_close, unbuffered);
1270228063cdSJim Ingham       m_log_streams[log_file] = log_stream_sp;
1271228063cdSJim Ingham     }
1272228063cdSJim Ingham   }
1273df370550SEugene Zelenko   assert(log_stream_sp);
1274228063cdSJim Ingham 
1275228063cdSJim Ingham   if (log_options == 0)
1276b9c1b51eSKate Stone     log_options =
1277b9c1b51eSKate Stone         LLDB_LOG_OPTION_PREPEND_THREAD_NAME | LLDB_LOG_OPTION_THREADSAFE;
1278228063cdSJim Ingham 
1279b9c1b51eSKate Stone   return Log::EnableLogChannel(log_stream_sp, log_options, channel, categories,
1280b9c1b51eSKate Stone                                error_stream);
1281228063cdSJim Ingham }
1282228063cdSJim Ingham 
1283b9c1b51eSKate Stone SourceManager &Debugger::GetSourceManager() {
1284df370550SEugene Zelenko   if (!m_source_manager_ap)
12852f3df613SZachary Turner     m_source_manager_ap = llvm::make_unique<SourceManager>(shared_from_this());
12869585fbfcSGreg Clayton   return *m_source_manager_ap;
12879585fbfcSGreg Clayton }
12889585fbfcSGreg Clayton 
128944d93782SGreg Clayton // This function handles events that were broadcast by the process.
1290b9c1b51eSKate Stone void Debugger::HandleBreakpointEvent(const EventSP &event_sp) {
129144d93782SGreg Clayton   using namespace lldb;
1292b9c1b51eSKate Stone   const uint32_t event_type =
1293b9c1b51eSKate Stone       Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent(
1294b9c1b51eSKate Stone           event_sp);
129544d93782SGreg Clayton 
129644d93782SGreg Clayton   //    if (event_type & eBreakpointEventTypeAdded
129744d93782SGreg Clayton   //        || event_type & eBreakpointEventTypeRemoved
129844d93782SGreg Clayton   //        || event_type & eBreakpointEventTypeEnabled
129944d93782SGreg Clayton   //        || event_type & eBreakpointEventTypeDisabled
130044d93782SGreg Clayton   //        || event_type & eBreakpointEventTypeCommandChanged
130144d93782SGreg Clayton   //        || event_type & eBreakpointEventTypeConditionChanged
130244d93782SGreg Clayton   //        || event_type & eBreakpointEventTypeIgnoreChanged
130344d93782SGreg Clayton   //        || event_type & eBreakpointEventTypeLocationsResolved)
130444d93782SGreg Clayton   //    {
1305b9c1b51eSKate Stone   //        // Don't do anything about these events, since the breakpoint
1306b9c1b51eSKate Stone   //        commands already echo these actions.
130744d93782SGreg Clayton   //    }
130844d93782SGreg Clayton   //
1309b9c1b51eSKate Stone   if (event_type & eBreakpointEventTypeLocationsAdded) {
1310b9c1b51eSKate Stone     uint32_t num_new_locations =
1311b9c1b51eSKate Stone         Breakpoint::BreakpointEventData::GetNumBreakpointLocationsFromEvent(
1312b9c1b51eSKate Stone             event_sp);
1313b9c1b51eSKate Stone     if (num_new_locations > 0) {
1314b9c1b51eSKate Stone       BreakpointSP breakpoint =
1315b9c1b51eSKate Stone           Breakpoint::BreakpointEventData::GetBreakpointFromEvent(event_sp);
13164446487dSPavel Labath       StreamSP output_sp(GetAsyncOutputStream());
1317b9c1b51eSKate Stone       if (output_sp) {
131844d93782SGreg Clayton         output_sp->Printf("%d location%s added to breakpoint %d\n",
1319b9c1b51eSKate Stone                           num_new_locations, num_new_locations == 1 ? "" : "s",
132044d93782SGreg Clayton                           breakpoint->GetID());
13214446487dSPavel Labath         output_sp->Flush();
132244d93782SGreg Clayton       }
132344d93782SGreg Clayton     }
132444d93782SGreg Clayton   }
132544d93782SGreg Clayton   //    else if (event_type & eBreakpointEventTypeLocationsRemoved)
132644d93782SGreg Clayton   //    {
1327b9c1b51eSKate Stone   //        // These locations just get disabled, not sure it is worth spamming
1328b9c1b51eSKate Stone   //        folks about this on the command line.
132944d93782SGreg Clayton   //    }
133044d93782SGreg Clayton   //    else if (event_type & eBreakpointEventTypeLocationsResolved)
133144d93782SGreg Clayton   //    {
1332b9c1b51eSKate Stone   //        // This might be an interesting thing to note, but I'm going to
1333b9c1b51eSKate Stone   //        leave it quiet for now, it just looked noisy.
133444d93782SGreg Clayton   //    }
133544d93782SGreg Clayton }
133644d93782SGreg Clayton 
1337b9c1b51eSKate Stone size_t Debugger::GetProcessSTDOUT(Process *process, Stream *stream) {
133844d93782SGreg Clayton   size_t total_bytes = 0;
1339df370550SEugene Zelenko   if (stream == nullptr)
134044d93782SGreg Clayton     stream = GetOutputFile().get();
134144d93782SGreg Clayton 
1342b9c1b51eSKate Stone   if (stream) {
1343b9c1b51eSKate Stone     //  The process has stuff waiting for stdout; get it and write it out to the
1344b9c1b51eSKate Stone     //  appropriate place.
1345b9c1b51eSKate Stone     if (process == nullptr) {
134644d93782SGreg Clayton       TargetSP target_sp = GetTargetList().GetSelectedTarget();
134744d93782SGreg Clayton       if (target_sp)
134844d93782SGreg Clayton         process = target_sp->GetProcessSP().get();
134944d93782SGreg Clayton     }
1350b9c1b51eSKate Stone     if (process) {
135197206d57SZachary Turner       Status error;
135244d93782SGreg Clayton       size_t len;
135344d93782SGreg Clayton       char stdio_buffer[1024];
1354b9c1b51eSKate Stone       while ((len = process->GetSTDOUT(stdio_buffer, sizeof(stdio_buffer),
1355b9c1b51eSKate Stone                                        error)) > 0) {
135644d93782SGreg Clayton         stream->Write(stdio_buffer, len);
135744d93782SGreg Clayton         total_bytes += len;
135844d93782SGreg Clayton       }
135944d93782SGreg Clayton     }
136044d93782SGreg Clayton     stream->Flush();
136144d93782SGreg Clayton   }
136244d93782SGreg Clayton   return total_bytes;
136344d93782SGreg Clayton }
136444d93782SGreg Clayton 
1365b9c1b51eSKate Stone size_t Debugger::GetProcessSTDERR(Process *process, Stream *stream) {
136644d93782SGreg Clayton   size_t total_bytes = 0;
1367df370550SEugene Zelenko   if (stream == nullptr)
136844d93782SGreg Clayton     stream = GetOutputFile().get();
136944d93782SGreg Clayton 
1370b9c1b51eSKate Stone   if (stream) {
1371b9c1b51eSKate Stone     //  The process has stuff waiting for stderr; get it and write it out to the
1372b9c1b51eSKate Stone     //  appropriate place.
1373b9c1b51eSKate Stone     if (process == nullptr) {
137444d93782SGreg Clayton       TargetSP target_sp = GetTargetList().GetSelectedTarget();
137544d93782SGreg Clayton       if (target_sp)
137644d93782SGreg Clayton         process = target_sp->GetProcessSP().get();
137744d93782SGreg Clayton     }
1378b9c1b51eSKate Stone     if (process) {
137997206d57SZachary Turner       Status error;
138044d93782SGreg Clayton       size_t len;
138144d93782SGreg Clayton       char stdio_buffer[1024];
1382b9c1b51eSKate Stone       while ((len = process->GetSTDERR(stdio_buffer, sizeof(stdio_buffer),
1383b9c1b51eSKate Stone                                        error)) > 0) {
138444d93782SGreg Clayton         stream->Write(stdio_buffer, len);
138544d93782SGreg Clayton         total_bytes += len;
138644d93782SGreg Clayton       }
138744d93782SGreg Clayton     }
138844d93782SGreg Clayton     stream->Flush();
138944d93782SGreg Clayton   }
139044d93782SGreg Clayton   return total_bytes;
139144d93782SGreg Clayton }
139244d93782SGreg Clayton 
139344d93782SGreg Clayton // This function handles events that were broadcast by the process.
1394b9c1b51eSKate Stone void Debugger::HandleProcessEvent(const EventSP &event_sp) {
139544d93782SGreg Clayton   using namespace lldb;
139644d93782SGreg Clayton   const uint32_t event_type = event_sp->GetType();
1397b9c1b51eSKate Stone   ProcessSP process_sp =
1398b9c1b51eSKate Stone       (event_type == Process::eBroadcastBitStructuredData)
139975930019STodd Fiala           ? EventDataStructuredData::GetProcessFromEvent(event_sp.get())
140075930019STodd Fiala           : Process::ProcessEventData::GetProcessFromEvent(event_sp.get());
140144d93782SGreg Clayton 
14024446487dSPavel Labath   StreamSP output_stream_sp = GetAsyncOutputStream();
14034446487dSPavel Labath   StreamSP error_stream_sp = GetAsyncErrorStream();
140444d93782SGreg Clayton   const bool gui_enabled = IsForwardingEvents();
140544d93782SGreg Clayton 
1406b9c1b51eSKate Stone   if (!gui_enabled) {
1407b4874f1aSGreg Clayton     bool pop_process_io_handler = false;
140844d93782SGreg Clayton     assert(process_sp);
140944d93782SGreg Clayton 
14104446487dSPavel Labath     bool state_is_stopped = false;
1411b9c1b51eSKate Stone     const bool got_state_changed =
1412b9c1b51eSKate Stone         (event_type & Process::eBroadcastBitStateChanged) != 0;
14134446487dSPavel Labath     const bool got_stdout = (event_type & Process::eBroadcastBitSTDOUT) != 0;
14144446487dSPavel Labath     const bool got_stderr = (event_type & Process::eBroadcastBitSTDERR) != 0;
1415b9c1b51eSKate Stone     const bool got_structured_data =
1416b9c1b51eSKate Stone         (event_type & Process::eBroadcastBitStructuredData) != 0;
141775930019STodd Fiala 
1418b9c1b51eSKate Stone     if (got_state_changed) {
1419b9c1b51eSKate Stone       StateType event_state =
1420b9c1b51eSKate Stone           Process::ProcessEventData::GetStateFromEvent(event_sp.get());
14214446487dSPavel Labath       state_is_stopped = StateIsStoppedState(event_state, false);
142244d93782SGreg Clayton     }
1423b4874f1aSGreg Clayton 
14244446487dSPavel Labath     // Display running state changes first before any STDIO
1425b9c1b51eSKate Stone     if (got_state_changed && !state_is_stopped) {
1426b9c1b51eSKate Stone       Process::HandleProcessStateChangedEvent(event_sp, output_stream_sp.get(),
1427b9c1b51eSKate Stone                                               pop_process_io_handler);
142844d93782SGreg Clayton     }
1429b4874f1aSGreg Clayton 
14304446487dSPavel Labath     // Now display and STDOUT
1431b9c1b51eSKate Stone     if (got_stdout || got_state_changed) {
14324446487dSPavel Labath       GetProcessSTDOUT(process_sp.get(), output_stream_sp.get());
143344d93782SGreg Clayton     }
1434b4874f1aSGreg Clayton 
14354446487dSPavel Labath     // Now display and STDERR
1436b9c1b51eSKate Stone     if (got_stderr || got_state_changed) {
14374446487dSPavel Labath       GetProcessSTDERR(process_sp.get(), error_stream_sp.get());
1438b4874f1aSGreg Clayton     }
1439b4874f1aSGreg Clayton 
144075930019STodd Fiala     // Give structured data events an opportunity to display.
1441b9c1b51eSKate Stone     if (got_structured_data) {
144275930019STodd Fiala       StructuredDataPluginSP plugin_sp =
144375930019STodd Fiala           EventDataStructuredData::GetPluginFromEvent(event_sp.get());
1444b9c1b51eSKate Stone       if (plugin_sp) {
144575930019STodd Fiala         auto structured_data_sp =
144675930019STodd Fiala             EventDataStructuredData::GetObjectFromEvent(event_sp.get());
1447b9c1b51eSKate Stone         if (output_stream_sp) {
144875930019STodd Fiala           StreamString content_stream;
144997206d57SZachary Turner           Status error =
1450b9c1b51eSKate Stone               plugin_sp->GetDescription(structured_data_sp, content_stream);
1451b9c1b51eSKate Stone           if (error.Success()) {
1452b9c1b51eSKate Stone             if (!content_stream.GetString().empty()) {
145375930019STodd Fiala               // Add newline.
145475930019STodd Fiala               content_stream.PutChar('\n');
145575930019STodd Fiala               content_stream.Flush();
145675930019STodd Fiala 
145775930019STodd Fiala               // Print it.
1458771ef6d4SMalcolm Parsons               output_stream_sp->PutCString(content_stream.GetString());
145975930019STodd Fiala             }
1460b9c1b51eSKate Stone           } else {
146175930019STodd Fiala             error_stream_sp->Printf("Failed to print structured "
146275930019STodd Fiala                                     "data with plugin %s: %s",
1463b9c1b51eSKate Stone                                     plugin_sp->GetPluginName().AsCString(),
146475930019STodd Fiala                                     error.AsCString());
146575930019STodd Fiala           }
146675930019STodd Fiala         }
146775930019STodd Fiala       }
146875930019STodd Fiala     }
146975930019STodd Fiala 
14704446487dSPavel Labath     // Now display any stopped state changes after any STDIO
1471b9c1b51eSKate Stone     if (got_state_changed && state_is_stopped) {
1472b9c1b51eSKate Stone       Process::HandleProcessStateChangedEvent(event_sp, output_stream_sp.get(),
1473b9c1b51eSKate Stone                                               pop_process_io_handler);
147444d93782SGreg Clayton     }
147544d93782SGreg Clayton 
14764446487dSPavel Labath     output_stream_sp->Flush();
14774446487dSPavel Labath     error_stream_sp->Flush();
147844d93782SGreg Clayton 
1479b4874f1aSGreg Clayton     if (pop_process_io_handler)
1480b4874f1aSGreg Clayton       process_sp->PopProcessIOHandler();
1481b4874f1aSGreg Clayton   }
1482b4874f1aSGreg Clayton }
1483b4874f1aSGreg Clayton 
1484b9c1b51eSKate Stone void Debugger::HandleThreadEvent(const EventSP &event_sp) {
148505097246SAdrian Prantl   // At present the only thread event we handle is the Frame Changed event, and
148605097246SAdrian Prantl   // all we do for that is just reprint the thread status for that thread.
148744d93782SGreg Clayton   using namespace lldb;
148844d93782SGreg Clayton   const uint32_t event_type = event_sp->GetType();
14896a9767c7SJim Ingham   const bool stop_format = true;
149044d93782SGreg Clayton   if (event_type == Thread::eBroadcastBitStackChanged ||
1491b9c1b51eSKate Stone       event_type == Thread::eBroadcastBitThreadSelected) {
1492b9c1b51eSKate Stone     ThreadSP thread_sp(
1493b9c1b51eSKate Stone         Thread::ThreadEventData::GetThreadFromEvent(event_sp.get()));
1494b9c1b51eSKate Stone     if (thread_sp) {
14956a9767c7SJim Ingham       thread_sp->GetStatus(*GetAsyncOutputStream(), 0, 1, 1, stop_format);
149644d93782SGreg Clayton     }
149744d93782SGreg Clayton   }
149844d93782SGreg Clayton }
149944d93782SGreg Clayton 
1500b9c1b51eSKate Stone bool Debugger::IsForwardingEvents() { return (bool)m_forward_listener_sp; }
150144d93782SGreg Clayton 
1502b9c1b51eSKate Stone void Debugger::EnableForwardEvents(const ListenerSP &listener_sp) {
150344d93782SGreg Clayton   m_forward_listener_sp = listener_sp;
150444d93782SGreg Clayton }
150544d93782SGreg Clayton 
1506b9c1b51eSKate Stone void Debugger::CancelForwardEvents(const ListenerSP &listener_sp) {
150744d93782SGreg Clayton   m_forward_listener_sp.reset();
150844d93782SGreg Clayton }
150944d93782SGreg Clayton 
1510b9c1b51eSKate Stone void Debugger::DefaultEventHandler() {
1511583bbb1dSJim Ingham   ListenerSP listener_sp(GetListener());
151244d93782SGreg Clayton   ConstString broadcaster_class_target(Target::GetStaticBroadcasterClass());
151344d93782SGreg Clayton   ConstString broadcaster_class_process(Process::GetStaticBroadcasterClass());
151444d93782SGreg Clayton   ConstString broadcaster_class_thread(Thread::GetStaticBroadcasterClass());
151544d93782SGreg Clayton   BroadcastEventSpec target_event_spec(broadcaster_class_target,
151644d93782SGreg Clayton                                        Target::eBroadcastBitBreakpointChanged);
151744d93782SGreg Clayton 
1518b9c1b51eSKate Stone   BroadcastEventSpec process_event_spec(
1519b9c1b51eSKate Stone       broadcaster_class_process,
1520b9c1b51eSKate Stone       Process::eBroadcastBitStateChanged | Process::eBroadcastBitSTDOUT |
1521b9c1b51eSKate Stone           Process::eBroadcastBitSTDERR | Process::eBroadcastBitStructuredData);
152244d93782SGreg Clayton 
152344d93782SGreg Clayton   BroadcastEventSpec thread_event_spec(broadcaster_class_thread,
152444d93782SGreg Clayton                                        Thread::eBroadcastBitStackChanged |
152544d93782SGreg Clayton                                            Thread::eBroadcastBitThreadSelected);
152644d93782SGreg Clayton 
1527b9c1b51eSKate Stone   listener_sp->StartListeningForEventSpec(m_broadcaster_manager_sp,
1528b9c1b51eSKate Stone                                           target_event_spec);
1529b9c1b51eSKate Stone   listener_sp->StartListeningForEventSpec(m_broadcaster_manager_sp,
1530b9c1b51eSKate Stone                                           process_event_spec);
1531b9c1b51eSKate Stone   listener_sp->StartListeningForEventSpec(m_broadcaster_manager_sp,
1532b9c1b51eSKate Stone                                           thread_event_spec);
1533b9c1b51eSKate Stone   listener_sp->StartListeningForEvents(
1534b9c1b51eSKate Stone       m_command_interpreter_ap.get(),
153544d93782SGreg Clayton       CommandInterpreter::eBroadcastBitQuitCommandReceived |
153644d93782SGreg Clayton           CommandInterpreter::eBroadcastBitAsynchronousOutputData |
153744d93782SGreg Clayton           CommandInterpreter::eBroadcastBitAsynchronousErrorData);
153844d93782SGreg Clayton 
153905097246SAdrian Prantl   // Let the thread that spawned us know that we have started up and that we
154005097246SAdrian Prantl   // are now listening to all required events so no events get missed
1541afa91e33SGreg Clayton   m_sync_broadcaster.BroadcastEvent(eBroadcastBitEventThreadIsListening);
1542afa91e33SGreg Clayton 
154344d93782SGreg Clayton   bool done = false;
1544b9c1b51eSKate Stone   while (!done) {
154544d93782SGreg Clayton     EventSP event_sp;
1546d35031e1SPavel Labath     if (listener_sp->GetEvent(event_sp, llvm::None)) {
1547b9c1b51eSKate Stone       if (event_sp) {
154844d93782SGreg Clayton         Broadcaster *broadcaster = event_sp->GetBroadcaster();
1549b9c1b51eSKate Stone         if (broadcaster) {
155044d93782SGreg Clayton           uint32_t event_type = event_sp->GetType();
155144d93782SGreg Clayton           ConstString broadcaster_class(broadcaster->GetBroadcasterClass());
1552b9c1b51eSKate Stone           if (broadcaster_class == broadcaster_class_process) {
155344d93782SGreg Clayton             HandleProcessEvent(event_sp);
1554b9c1b51eSKate Stone           } else if (broadcaster_class == broadcaster_class_target) {
1555b9c1b51eSKate Stone             if (Breakpoint::BreakpointEventData::GetEventDataFromEvent(
1556b9c1b51eSKate Stone                     event_sp.get())) {
155744d93782SGreg Clayton               HandleBreakpointEvent(event_sp);
155844d93782SGreg Clayton             }
1559b9c1b51eSKate Stone           } else if (broadcaster_class == broadcaster_class_thread) {
156044d93782SGreg Clayton             HandleThreadEvent(event_sp);
1561b9c1b51eSKate Stone           } else if (broadcaster == m_command_interpreter_ap.get()) {
1562b9c1b51eSKate Stone             if (event_type &
1563b9c1b51eSKate Stone                 CommandInterpreter::eBroadcastBitQuitCommandReceived) {
156444d93782SGreg Clayton               done = true;
1565b9c1b51eSKate Stone             } else if (event_type &
1566b9c1b51eSKate Stone                        CommandInterpreter::eBroadcastBitAsynchronousErrorData) {
1567b9c1b51eSKate Stone               const char *data = reinterpret_cast<const char *>(
1568b9c1b51eSKate Stone                   EventDataBytes::GetBytesFromEvent(event_sp.get()));
1569b9c1b51eSKate Stone               if (data && data[0]) {
15704446487dSPavel Labath                 StreamSP error_sp(GetAsyncErrorStream());
1571b9c1b51eSKate Stone                 if (error_sp) {
157244d93782SGreg Clayton                   error_sp->PutCString(data);
157344d93782SGreg Clayton                   error_sp->Flush();
157444d93782SGreg Clayton                 }
157544d93782SGreg Clayton               }
1576b9c1b51eSKate Stone             } else if (event_type & CommandInterpreter::
1577b9c1b51eSKate Stone                                         eBroadcastBitAsynchronousOutputData) {
1578b9c1b51eSKate Stone               const char *data = reinterpret_cast<const char *>(
1579b9c1b51eSKate Stone                   EventDataBytes::GetBytesFromEvent(event_sp.get()));
1580b9c1b51eSKate Stone               if (data && data[0]) {
15814446487dSPavel Labath                 StreamSP output_sp(GetAsyncOutputStream());
1582b9c1b51eSKate Stone                 if (output_sp) {
158344d93782SGreg Clayton                   output_sp->PutCString(data);
158444d93782SGreg Clayton                   output_sp->Flush();
158544d93782SGreg Clayton                 }
158644d93782SGreg Clayton               }
158744d93782SGreg Clayton             }
158844d93782SGreg Clayton           }
158944d93782SGreg Clayton         }
159044d93782SGreg Clayton 
159144d93782SGreg Clayton         if (m_forward_listener_sp)
159244d93782SGreg Clayton           m_forward_listener_sp->AddEvent(event_sp);
159344d93782SGreg Clayton       }
159444d93782SGreg Clayton     }
159544d93782SGreg Clayton   }
159644d93782SGreg Clayton }
159744d93782SGreg Clayton 
1598b9c1b51eSKate Stone lldb::thread_result_t Debugger::EventHandlerThread(lldb::thread_arg_t arg) {
159944d93782SGreg Clayton   ((Debugger *)arg)->DefaultEventHandler();
160044d93782SGreg Clayton   return NULL;
160144d93782SGreg Clayton }
160244d93782SGreg Clayton 
1603b9c1b51eSKate Stone bool Debugger::StartEventHandlerThread() {
1604b9c1b51eSKate Stone   if (!m_event_handler_thread.IsJoinable()) {
160505097246SAdrian Prantl     // We must synchronize with the DefaultEventHandler() thread to ensure it
160605097246SAdrian Prantl     // is up and running and listening to events before we return from this
160705097246SAdrian Prantl     // function. We do this by listening to events for the
1608afa91e33SGreg Clayton     // eBroadcastBitEventThreadIsListening from the m_sync_broadcaster
16091a728f66STatyana Krasnukha     ConstString full_name("lldb.debugger.event-handler");
16101a728f66STatyana Krasnukha     ListenerSP listener_sp(Listener::MakeListener(full_name.AsCString()));
1611b9c1b51eSKate Stone     listener_sp->StartListeningForEvents(&m_sync_broadcaster,
1612b9c1b51eSKate Stone                                          eBroadcastBitEventThreadIsListening);
1613afa91e33SGreg Clayton 
16141a728f66STatyana Krasnukha     auto thread_name =
16151a728f66STatyana Krasnukha         full_name.GetLength() < llvm::get_max_thread_name_length() ?
16161a728f66STatyana Krasnukha         full_name.AsCString() : "dbg.evt-handler";
16171a728f66STatyana Krasnukha 
16187c2896a2SZachary Turner     // Use larger 8MB stack for this thread
16191a728f66STatyana Krasnukha     m_event_handler_thread = ThreadLauncher::LaunchThread(thread_name,
16201a728f66STatyana Krasnukha         EventHandlerThread, this, nullptr, g_debugger_event_thread_stack_bytes);
1621afa91e33SGreg Clayton 
162205097246SAdrian Prantl     // Make sure DefaultEventHandler() is running and listening to events
162305097246SAdrian Prantl     // before we return from this function. We are only listening for events of
162405097246SAdrian Prantl     // type eBroadcastBitEventThreadIsListening so we don't need to check the
162505097246SAdrian Prantl     // event, we just need to wait an infinite amount of time for it (nullptr
162605097246SAdrian Prantl     // timeout as the first parameter)
1627afa91e33SGreg Clayton     lldb::EventSP event_sp;
1628d35031e1SPavel Labath     listener_sp->GetEvent(event_sp, llvm::None);
1629807b6b32SGreg Clayton   }
1630acee96aeSZachary Turner   return m_event_handler_thread.IsJoinable();
163144d93782SGreg Clayton }
163244d93782SGreg Clayton 
1633b9c1b51eSKate Stone void Debugger::StopEventHandlerThread() {
1634b9c1b51eSKate Stone   if (m_event_handler_thread.IsJoinable()) {
1635b9c1b51eSKate Stone     GetCommandInterpreter().BroadcastEvent(
1636b9c1b51eSKate Stone         CommandInterpreter::eBroadcastBitQuitCommandReceived);
163739de3110SZachary Turner     m_event_handler_thread.Join(nullptr);
163844d93782SGreg Clayton   }
163944d93782SGreg Clayton }
164044d93782SGreg Clayton 
1641b9c1b51eSKate Stone lldb::thread_result_t Debugger::IOHandlerThread(lldb::thread_arg_t arg) {
164244d93782SGreg Clayton   Debugger *debugger = (Debugger *)arg;
16439aaab558SSiva Chandra   debugger->ExecuteIOHandlers();
164444d93782SGreg Clayton   debugger->StopEventHandlerThread();
164544d93782SGreg Clayton   return NULL;
164644d93782SGreg Clayton }
164744d93782SGreg Clayton 
1648b9c1b51eSKate Stone bool Debugger::HasIOHandlerThread() { return m_io_handler_thread.IsJoinable(); }
16496681041dSSean Callanan 
1650b9c1b51eSKate Stone bool Debugger::StartIOHandlerThread() {
1651acee96aeSZachary Turner   if (!m_io_handler_thread.IsJoinable())
1652b9c1b51eSKate Stone     m_io_handler_thread = ThreadLauncher::LaunchThread(
1653b9c1b51eSKate Stone         "lldb.debugger.io-handler", IOHandlerThread, this, nullptr,
1654807b6b32SGreg Clayton         8 * 1024 * 1024); // Use larger 8MB stack for this thread
1655acee96aeSZachary Turner   return m_io_handler_thread.IsJoinable();
165644d93782SGreg Clayton }
165744d93782SGreg Clayton 
1658b9c1b51eSKate Stone void Debugger::StopIOHandlerThread() {
1659b9c1b51eSKate Stone   if (m_io_handler_thread.IsJoinable()) {
166044d93782SGreg Clayton     if (m_input_file_sp)
166144d93782SGreg Clayton       m_input_file_sp->GetFile().Close();
166239de3110SZachary Turner     m_io_handler_thread.Join(nullptr);
166344d93782SGreg Clayton   }
166444d93782SGreg Clayton }
166544d93782SGreg Clayton 
1666b9c1b51eSKate Stone void Debugger::JoinIOHandlerThread() {
1667b9c1b51eSKate Stone   if (HasIOHandlerThread()) {
16686681041dSSean Callanan     thread_result_t result;
16696681041dSSean Callanan     m_io_handler_thread.Join(&result);
16706681041dSSean Callanan     m_io_handler_thread = LLDB_INVALID_HOST_THREAD;
16716681041dSSean Callanan   }
16726681041dSSean Callanan }
16736681041dSSean Callanan 
1674b9c1b51eSKate Stone Target *Debugger::GetDummyTarget() {
1675893c932aSJim Ingham   return m_target_list.GetDummyTarget(*this).get();
1676893c932aSJim Ingham }
1677893c932aSJim Ingham 
1678b9c1b51eSKate Stone Target *Debugger::GetSelectedOrDummyTarget(bool prefer_dummy) {
167933df7cd3SJim Ingham   Target *target = nullptr;
1680b9c1b51eSKate Stone   if (!prefer_dummy) {
168133df7cd3SJim Ingham     target = m_target_list.GetSelectedTarget().get();
168233df7cd3SJim Ingham     if (target)
168333df7cd3SJim Ingham       return target;
168433df7cd3SJim Ingham   }
1685893c932aSJim Ingham 
1686893c932aSJim Ingham   return GetDummyTarget();
1687893c932aSJim Ingham }
168844d93782SGreg Clayton 
168997206d57SZachary Turner Status Debugger::RunREPL(LanguageType language, const char *repl_options) {
169097206d57SZachary Turner   Status err;
16913e7e915dSSean Callanan   FileSpec repl_executable;
16923e7e915dSSean Callanan 
1693b9c1b51eSKate Stone   if (language == eLanguageTypeUnknown) {
169497f84e87SSean Callanan     std::set<LanguageType> repl_languages;
169597f84e87SSean Callanan 
169697f84e87SSean Callanan     Language::GetLanguagesSupportingREPLs(repl_languages);
169797f84e87SSean Callanan 
1698b9c1b51eSKate Stone     if (repl_languages.size() == 1) {
169997f84e87SSean Callanan       language = *repl_languages.begin();
1700b9c1b51eSKate Stone     } else if (repl_languages.empty()) {
1701b9c1b51eSKate Stone       err.SetErrorStringWithFormat(
1702b9c1b51eSKate Stone           "LLDB isn't configured with REPL support for any languages.");
170397f84e87SSean Callanan       return err;
1704b9c1b51eSKate Stone     } else {
1705b9c1b51eSKate Stone       err.SetErrorStringWithFormat(
1706b9c1b51eSKate Stone           "Multiple possible REPL languages.  Please specify a language.");
170797f84e87SSean Callanan       return err;
170897f84e87SSean Callanan     }
170997f84e87SSean Callanan   }
171097f84e87SSean Callanan 
1711b9c1b51eSKate Stone   Target *const target =
1712b9c1b51eSKate Stone       nullptr; // passing in an empty target means the REPL must create one
17133e7e915dSSean Callanan 
17143b682de6SSean Callanan   REPLSP repl_sp(REPL::Create(err, language, this, target, repl_options));
17153e7e915dSSean Callanan 
1716b9c1b51eSKate Stone   if (!err.Success()) {
17173e7e915dSSean Callanan     return err;
17183e7e915dSSean Callanan   }
17193e7e915dSSean Callanan 
1720b9c1b51eSKate Stone   if (!repl_sp) {
1721b9c1b51eSKate Stone     err.SetErrorStringWithFormat("couldn't find a REPL for %s",
1722b9c1b51eSKate Stone                                  Language::GetNameForLanguageType(language));
17233e7e915dSSean Callanan     return err;
17243e7e915dSSean Callanan   }
17253e7e915dSSean Callanan 
17263e7e915dSSean Callanan   repl_sp->SetCompilerOptions(repl_options);
17273e7e915dSSean Callanan   repl_sp->RunLoop();
17283e7e915dSSean Callanan 
17293e7e915dSSean Callanan   return err;
17303e7e915dSSean Callanan }
1731