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"
1930fdc8d8SChris Lattner #include "lldb/Core/State.h"
205b52f0c7SJim Ingham #include "lldb/Core/StreamAsynchronousIO.h"
2144d93782SGreg Clayton #include "lldb/Core/StreamFile.h"
225548cb50SEnrico Granata #include "lldb/DataFormatters/DataVisualization.h"
233e7e915dSSean Callanan #include "lldb/Expression/REPL.h"
242f3df613SZachary Turner #include "lldb/Host/File.h" // for File, File::kInv...
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_...
472f3df613SZachary Turner #include "lldb/Utility/Stream.h" // for Stream
48fb1a0a0dSZachary Turner #include "lldb/Utility/StreamCallback.h"
49bf9a7730SZachary Turner #include "lldb/Utility/StreamString.h"
502f3df613SZachary Turner 
512f3df613SZachary Turner #if defined(LLVM_ON_WIN32)
522f3df613SZachary Turner #include "lldb/Host/windows/PosixApi.h" // for PATH_MAX
532f3df613SZachary Turner #endif
542f3df613SZachary Turner 
552f3df613SZachary Turner #include "llvm/ADT/None.h"      // for None
562f3df613SZachary Turner #include "llvm/ADT/STLExtras.h" // for make_unique
572f3df613SZachary Turner #include "llvm/ADT/StringRef.h"
582f3df613SZachary Turner #include "llvm/ADT/iterator.h" // for iterator_facade_...
592f3df613SZachary Turner #include "llvm/Support/DynamicLibrary.h"
602f3df613SZachary Turner #include "llvm/Support/FileSystem.h"
612f3df613SZachary Turner #include "llvm/Support/Threading.h"
622f3df613SZachary Turner #include "llvm/Support/raw_ostream.h" // for raw_fd_ostream
632f3df613SZachary Turner 
642f3df613SZachary Turner #include <list>   // for list
652f3df613SZachary Turner #include <memory> // for make_shared
662f3df613SZachary Turner #include <mutex>
672f3df613SZachary Turner #include <set>          // for set
682f3df613SZachary Turner #include <stdio.h>      // for size_t, NULL
692f3df613SZachary Turner #include <stdlib.h>     // for getenv
702f3df613SZachary Turner #include <string.h>     // for strcmp
712f3df613SZachary Turner #include <string>       // for string
722f3df613SZachary Turner #include <system_error> // for error_code
732f3df613SZachary Turner 
742f3df613SZachary Turner namespace lldb_private {
752f3df613SZachary Turner class Address;
762f3df613SZachary Turner }
7730fdc8d8SChris Lattner 
7830fdc8d8SChris Lattner using namespace lldb;
7930fdc8d8SChris Lattner using namespace lldb_private;
8030fdc8d8SChris Lattner 
81ebc1bb27SCaroline Tice static lldb::user_id_t g_unique_id = 1;
827c2896a2SZachary Turner static size_t g_debugger_event_thread_stack_bytes = 8 * 1024 * 1024;
83ebc1bb27SCaroline Tice 
841b654882SGreg Clayton #pragma mark Static Functions
851b654882SGreg Clayton 
861b654882SGreg Clayton typedef std::vector<DebuggerSP> DebuggerList;
87b9c1b51eSKate Stone static std::recursive_mutex *g_debugger_list_mutex_ptr =
88b9c1b51eSKate Stone     nullptr; // NOTE: intentional leak to avoid issues with C++ destructor chain
89b9c1b51eSKate Stone static DebuggerList *g_debugger_list_ptr =
90b9c1b51eSKate Stone     nullptr; // NOTE: intentional leak to avoid issues with C++ destructor chain
91e372b98dSGreg Clayton 
92b9c1b51eSKate Stone OptionEnumValueElement g_show_disassembly_enum_values[] = {
93b9c1b51eSKate Stone     {Debugger::eStopDisassemblyTypeNever, "never",
94b9c1b51eSKate Stone      "Never show disassembly when displaying a stop context."},
95b9c1b51eSKate Stone     {Debugger::eStopDisassemblyTypeNoDebugInfo, "no-debuginfo",
96b9c1b51eSKate Stone      "Show disassembly when there is no debug information."},
97b9c1b51eSKate Stone     {Debugger::eStopDisassemblyTypeNoSource, "no-source",
98b9c1b51eSKate Stone      "Show disassembly when there is no source information, or the source file "
99b9c1b51eSKate Stone      "is missing when displaying a stop context."},
100b9c1b51eSKate Stone     {Debugger::eStopDisassemblyTypeAlways, "always",
101b9c1b51eSKate Stone      "Always show disassembly when displaying a stop context."},
102b9c1b51eSKate Stone     {0, nullptr, nullptr}};
103e372b98dSGreg Clayton 
104b9c1b51eSKate Stone OptionEnumValueElement g_language_enumerators[] = {
10567cc0636SGreg Clayton     {eScriptLanguageNone, "none", "Disable scripting languages."},
106b9c1b51eSKate Stone     {eScriptLanguagePython, "python",
107b9c1b51eSKate Stone      "Select python as the default scripting language."},
108b9c1b51eSKate Stone     {eScriptLanguageDefault, "default",
109b9c1b51eSKate Stone      "Select the lldb default as the default scripting language."},
110b9c1b51eSKate Stone     {0, nullptr, nullptr}};
111e372b98dSGreg Clayton 
112b9c1b51eSKate Stone #define MODULE_WITH_FUNC                                                       \
113b9c1b51eSKate Stone   "{ "                                                                         \
1146a9767c7SJim Ingham   "${module.file.basename}{`${function.name-with-args}"                        \
1156a9767c7SJim Ingham   "{${frame.no-debug}${function.pc-offset}}}}"
1167f1c1211SPavel Labath 
1177f1c1211SPavel Labath #define MODULE_WITH_FUNC_NO_ARGS                                               \
1187f1c1211SPavel Labath   "{ "                                                                         \
1197f1c1211SPavel Labath   "${module.file.basename}{`${function.name-without-args}"                     \
1207f1c1211SPavel Labath   "{${frame.no-debug}${function.pc-offset}}}}"
1217f1c1211SPavel Labath 
12267cc0636SGreg Clayton #define FILE_AND_LINE "{ at ${line.file.basename}:${line.number}}"
1236ab659a9SJason Molenda #define IS_OPTIMIZED "{${function.is-optimized} [opt]}"
12467cc0636SGreg Clayton 
125b9c1b51eSKate Stone #define DEFAULT_THREAD_FORMAT                                                  \
126b9c1b51eSKate Stone   "thread #${thread.index}: tid = ${thread.id%tid}"                            \
127b9c1b51eSKate Stone   "{, ${frame.pc}}" MODULE_WITH_FUNC FILE_AND_LINE                             \
1280769b2b1SMichael Sartain   "{, name = '${thread.name}'}"                                                \
1290769b2b1SMichael Sartain   "{, queue = '${thread.queue}'}"                                              \
130705b1809SJason Molenda   "{, activity = '${thread.info.activity.name}'}"                              \
131705b1809SJason Molenda   "{, ${thread.info.trace_messages} messages}"                                 \
13267cc0636SGreg Clayton   "{, stop reason = ${thread.stop-reason}}"                                    \
13367cc0636SGreg Clayton   "{\\nReturn value: ${thread.return-value}}"                                  \
13430fadafeSJim Ingham   "{\\nCompleted expression: ${thread.completed-expression}}"                  \
13567cc0636SGreg Clayton   "\\n"
13667cc0636SGreg Clayton 
1376a9767c7SJim Ingham #define DEFAULT_THREAD_STOP_FORMAT                                             \
1386a9767c7SJim Ingham   "thread #${thread.index}{, name = '${thread.name}'}"                         \
1396a9767c7SJim Ingham   "{, queue = '${thread.queue}'}"                                              \
1406a9767c7SJim Ingham   "{, activity = '${thread.info.activity.name}'}"                              \
1416a9767c7SJim Ingham   "{, ${thread.info.trace_messages} messages}"                                 \
1426a9767c7SJim Ingham   "{, stop reason = ${thread.stop-reason}}"                                    \
1436a9767c7SJim Ingham   "{\\nReturn value: ${thread.return-value}}"                                  \
1446a9767c7SJim Ingham   "{\\nCompleted expression: ${thread.completed-expression}}"                  \
1456a9767c7SJim Ingham   "\\n"
1466a9767c7SJim Ingham 
147b9c1b51eSKate Stone #define DEFAULT_FRAME_FORMAT                                                   \
148270e8228SJason Molenda   "frame #${frame.index}: ${frame.pc}" MODULE_WITH_FUNC FILE_AND_LINE          \
149b9c1b51eSKate Stone       IS_OPTIMIZED "\\n"
15067cc0636SGreg Clayton 
1517f1c1211SPavel Labath #define DEFAULT_FRAME_FORMAT_NO_ARGS                                           \
1527f1c1211SPavel Labath   "frame #${frame.index}: ${frame.pc}" MODULE_WITH_FUNC_NO_ARGS FILE_AND_LINE  \
1537f1c1211SPavel Labath       IS_OPTIMIZED "\\n"
1547f1c1211SPavel Labath 
155c980fa92SJason Molenda // Three parts to this disassembly format specification:
156c980fa92SJason Molenda //   1. If this is a new function/symbol (no previous symbol/function), print
157c980fa92SJason Molenda //      dylib`funcname:\n
158b9c1b51eSKate Stone //   2. If this is a symbol context change (different from previous
159b9c1b51eSKate Stone //   symbol/function), print
160c980fa92SJason Molenda //      dylib`funcname:\n
161c980fa92SJason Molenda //   3. print
162c980fa92SJason Molenda //      address <+offset>:
163b9c1b51eSKate Stone #define DEFAULT_DISASSEMBLY_FORMAT                                             \
164b9c1b51eSKate Stone   "{${function.initial-function}{${module.file.basename}`}{${function.name-"   \
165b9c1b51eSKate Stone   "without-args}}:\n}{${function.changed}\n{${module.file.basename}`}{${"      \
166b9c1b51eSKate Stone   "function.name-without-args}}:\n}{${current-pc-arrow} "                      \
167b9c1b51eSKate Stone   "}${addr-file-or-load}{ "                                                    \
168b9c1b51eSKate Stone   "<${function.concrete-only-addr-offset-no-padding}>}: "
169c980fa92SJason Molenda 
170c980fa92SJason Molenda // gdb's disassembly format can be emulated with
171b9c1b51eSKate Stone // ${current-pc-arrow}${addr-file-or-load}{
172b9c1b51eSKate Stone // <${function.name-without-args}${function.concrete-only-addr-offset-no-padding}>}:
173c980fa92SJason Molenda 
174c980fa92SJason Molenda // lldb's original format for disassembly would look like this format string -
175b9c1b51eSKate Stone // {${function.initial-function}{${module.file.basename}`}{${function.name-without-args}}:\n}{${function.changed}\n{${module.file.basename}`}{${function.name-without-args}}:\n}{${current-pc-arrow}
176b9c1b51eSKate Stone // }{${addr-file-or-load}}:
177c980fa92SJason Molenda 
1789666ba75STodd Fiala #define DEFAULT_STOP_SHOW_COLUMN_ANSI_PREFIX "${ansi.underline}"
1799666ba75STodd Fiala #define DEFAULT_STOP_SHOW_COLUMN_ANSI_SUFFIX "${ansi.normal}"
1809666ba75STodd Fiala 
1819666ba75STodd Fiala static OptionEnumValueElement s_stop_show_column_values[] = {
1829666ba75STodd Fiala     {eStopShowColumnAnsiOrCaret, "ansi-or-caret",
1839666ba75STodd Fiala      "Highlight the stop column with ANSI terminal codes when color/ANSI mode "
1849666ba75STodd Fiala      "is enabled; otherwise, fall back to using a text-only caret (^) as if "
1859666ba75STodd Fiala      "\"caret-only\" mode was selected."},
1869666ba75STodd Fiala     {eStopShowColumnAnsi, "ansi", "Highlight the stop column with ANSI "
1879666ba75STodd Fiala                                   "terminal codes when running LLDB with "
1889666ba75STodd Fiala                                   "color/ANSI enabled."},
1899666ba75STodd Fiala     {eStopShowColumnCaret, "caret",
1909666ba75STodd Fiala      "Highlight the stop column with a caret character (^) underneath the stop "
1919666ba75STodd Fiala      "column. This method introduces a new line in source listings that "
1929666ba75STodd Fiala      "display thread stop locations."},
1939666ba75STodd Fiala     {eStopShowColumnNone, "none", "Do not highlight the stop column."},
1949666ba75STodd Fiala     {0, nullptr, nullptr}};
1959666ba75STodd Fiala 
196b9c1b51eSKate Stone static PropertyDefinition g_properties[] = {
197b9c1b51eSKate Stone     {"auto-confirm", OptionValue::eTypeBoolean, true, false, nullptr, nullptr,
198b9c1b51eSKate Stone      "If true all confirmation prompts will receive their default reply."},
199b9c1b51eSKate Stone     {"disassembly-format", OptionValue::eTypeFormatEntity, true, 0,
2007f1c1211SPavel Labath      DEFAULT_DISASSEMBLY_FORMAT, nullptr,
2017f1c1211SPavel Labath      "The default disassembly format "
202b9c1b51eSKate Stone      "string to use when disassembling "
203b9c1b51eSKate Stone      "instruction sequences."},
204b9c1b51eSKate Stone     {"frame-format", OptionValue::eTypeFormatEntity, true, 0,
2057f1c1211SPavel Labath      DEFAULT_FRAME_FORMAT, nullptr,
2067f1c1211SPavel Labath      "The default frame format string to use "
207b9c1b51eSKate Stone      "when displaying stack frame information "
208b9c1b51eSKate Stone      "for threads."},
209b9c1b51eSKate Stone     {"notify-void", OptionValue::eTypeBoolean, true, false, nullptr, nullptr,
210b9c1b51eSKate Stone      "Notify the user explicitly if an expression returns void (default: "
211b9c1b51eSKate Stone      "false)."},
212b9c1b51eSKate Stone     {"prompt", OptionValue::eTypeString, true,
213b9c1b51eSKate Stone      OptionValueString::eOptionEncodeCharacterEscapeSequences, "(lldb) ",
214b9c1b51eSKate Stone      nullptr, "The debugger command line prompt displayed for the user."},
215b9c1b51eSKate Stone     {"script-lang", OptionValue::eTypeEnum, true, eScriptLanguagePython,
216b9c1b51eSKate Stone      nullptr, g_language_enumerators,
217b9c1b51eSKate Stone      "The script language to be used for evaluating user-written scripts."},
218b9c1b51eSKate Stone     {"stop-disassembly-count", OptionValue::eTypeSInt64, true, 4, nullptr,
2197f1c1211SPavel Labath      nullptr,
2207f1c1211SPavel Labath      "The number of disassembly lines to show when displaying a "
221b9c1b51eSKate Stone      "stopped context."},
222b9c1b51eSKate Stone     {"stop-disassembly-display", OptionValue::eTypeEnum, true,
223b9c1b51eSKate Stone      Debugger::eStopDisassemblyTypeNoDebugInfo, nullptr,
224b9c1b51eSKate Stone      g_show_disassembly_enum_values,
225b9c1b51eSKate Stone      "Control when to display disassembly when displaying a stopped context."},
226b9c1b51eSKate Stone     {"stop-line-count-after", OptionValue::eTypeSInt64, true, 3, nullptr,
2277f1c1211SPavel Labath      nullptr,
2287f1c1211SPavel Labath      "The number of sources lines to display that come after the "
229b9c1b51eSKate Stone      "current source line when displaying a stopped context."},
230b9c1b51eSKate Stone     {"stop-line-count-before", OptionValue::eTypeSInt64, true, 3, nullptr,
2317f1c1211SPavel Labath      nullptr,
2327f1c1211SPavel Labath      "The number of sources lines to display that come before the "
233b9c1b51eSKate Stone      "current source line when displaying a stopped context."},
2349666ba75STodd Fiala     {"stop-show-column", OptionValue::eTypeEnum, false,
2359666ba75STodd Fiala      eStopShowColumnAnsiOrCaret, nullptr, s_stop_show_column_values,
2369666ba75STodd Fiala      "If true, LLDB will use the column information from the debug info to "
2379666ba75STodd Fiala      "mark the current position when displaying a stopped context."},
2389666ba75STodd Fiala     {"stop-show-column-ansi-prefix", OptionValue::eTypeFormatEntity, true, 0,
2399666ba75STodd Fiala      DEFAULT_STOP_SHOW_COLUMN_ANSI_PREFIX, nullptr,
2409666ba75STodd Fiala      "When displaying the column marker in a color-enabled (i.e. ANSI) "
2419666ba75STodd Fiala      "terminal, use the ANSI terminal code specified in this format at the "
2429666ba75STodd Fiala      "immediately before the column to be marked."},
2439666ba75STodd Fiala     {"stop-show-column-ansi-suffix", OptionValue::eTypeFormatEntity, true, 0,
2449666ba75STodd Fiala      DEFAULT_STOP_SHOW_COLUMN_ANSI_SUFFIX, nullptr,
2459666ba75STodd Fiala      "When displaying the column marker in a color-enabled (i.e. ANSI) "
2469666ba75STodd Fiala      "terminal, use the ANSI terminal code specified in this format "
2479666ba75STodd Fiala      "immediately after the column to be marked."},
248b9c1b51eSKate Stone     {"term-width", OptionValue::eTypeSInt64, true, 80, nullptr, nullptr,
249b9c1b51eSKate Stone      "The maximum number of columns to use for displaying text."},
250b9c1b51eSKate Stone     {"thread-format", OptionValue::eTypeFormatEntity, true, 0,
2517f1c1211SPavel Labath      DEFAULT_THREAD_FORMAT, nullptr,
2527f1c1211SPavel Labath      "The default thread format string to use "
253b9c1b51eSKate Stone      "when displaying thread information."},
2546a9767c7SJim Ingham     {"thread-stop-format", OptionValue::eTypeFormatEntity, true, 0,
2557f1c1211SPavel Labath      DEFAULT_THREAD_STOP_FORMAT, nullptr,
2567f1c1211SPavel Labath      "The default thread format  "
2576a9767c7SJim Ingham      "string to use when displaying thread "
2586a9767c7SJim Ingham      "information as part of the stop display."},
259b9c1b51eSKate Stone     {"use-external-editor", OptionValue::eTypeBoolean, true, false, nullptr,
260b9c1b51eSKate Stone      nullptr, "Whether to use an external editor or not."},
261b9c1b51eSKate Stone     {"use-color", OptionValue::eTypeBoolean, true, true, nullptr, nullptr,
262b9c1b51eSKate Stone      "Whether to use Ansi color codes or not."},
263b9c1b51eSKate Stone     {"auto-one-line-summaries", OptionValue::eTypeBoolean, true, true, nullptr,
2647f1c1211SPavel Labath      nullptr,
2657f1c1211SPavel Labath      "If true, LLDB will automatically display small structs in "
266b9c1b51eSKate Stone      "one-liner format (default: true)."},
267b9c1b51eSKate Stone     {"auto-indent", OptionValue::eTypeBoolean, true, true, nullptr, nullptr,
268b9c1b51eSKate Stone      "If true, LLDB will auto indent/outdent code. Currently only supported in "
269b9c1b51eSKate Stone      "the REPL (default: true)."},
270b9c1b51eSKate Stone     {"print-decls", OptionValue::eTypeBoolean, true, true, nullptr, nullptr,
271b9c1b51eSKate Stone      "If true, LLDB will print the values of variables declared in an "
272b9c1b51eSKate Stone      "expression. Currently only supported in the REPL (default: true)."},
273b9c1b51eSKate Stone     {"tab-size", OptionValue::eTypeUInt64, true, 4, nullptr, nullptr,
274b9c1b51eSKate Stone      "The tab size to use when indenting code in multi-line input mode "
275b9c1b51eSKate Stone      "(default: 4)."},
276b9c1b51eSKate Stone     {"escape-non-printables", OptionValue::eTypeBoolean, true, true, nullptr,
2777f1c1211SPavel Labath      nullptr,
2787f1c1211SPavel Labath      "If true, LLDB will automatically escape non-printable and "
279b9c1b51eSKate Stone      "escape characters when formatting strings."},
2807f1c1211SPavel Labath     {"frame-format-unique", OptionValue::eTypeFormatEntity, true, 0,
2817f1c1211SPavel Labath      DEFAULT_FRAME_FORMAT_NO_ARGS, nullptr,
2827f1c1211SPavel Labath      "The default frame format string to use when displaying stack frame"
2837f1c1211SPavel Labath      "information for threads from thread backtrace unique."},
284b9c1b51eSKate Stone     {nullptr, OptionValue::eTypeInvalid, true, 0, nullptr, nullptr, nullptr}};
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,
2979666ba75STodd Fiala   ePropertyStopShowColumn,
2989666ba75STodd Fiala   ePropertyStopShowColumnAnsiPrefix,
2999666ba75STodd Fiala   ePropertyStopShowColumnAnsiSuffix,
30067cc0636SGreg Clayton   ePropertyTerminalWidth,
30167cc0636SGreg Clayton   ePropertyThreadFormat,
3026a9767c7SJim Ingham   ePropertyThreadStopFormat,
303c3ce7f27SMichael Sartain   ePropertyUseExternalEditor,
304c3ce7f27SMichael Sartain   ePropertyUseColor,
305ebdc1ac0SEnrico Granata   ePropertyAutoOneLineSummaries,
3066681041dSSean Callanan   ePropertyAutoIndent,
3076681041dSSean Callanan   ePropertyPrintDecls,
3086681041dSSean Callanan   ePropertyTabSize,
3097f1c1211SPavel Labath   ePropertyEscapeNonPrintables,
3107f1c1211SPavel Labath   ePropertyFrameFormatUnique,
31167cc0636SGreg Clayton };
31267cc0636SGreg Clayton 
313df370550SEugene Zelenko LoadPluginCallbackType Debugger::g_load_plugin_callback = nullptr;
3144c05410fSGreg Clayton 
31597206d57SZachary Turner Status Debugger::SetPropertyValue(const ExecutionContext *exe_ctx,
3164c05410fSGreg Clayton                                   VarSetOperationType op,
31797206d57SZachary Turner                                   llvm::StringRef property_path,
31897206d57SZachary Turner                                   llvm::StringRef value) {
31931d97a5cSZachary Turner   bool is_load_script = (property_path == "target.load-script-from-symbol-file");
32031d97a5cSZachary Turner   bool is_escape_non_printables = (property_path == "escape-non-printables");
32184a53dfbSEnrico Granata   TargetSP target_sp;
322397ddd5fSEnrico Granata   LoadScriptFromSymFile load_script_old_value;
323b9c1b51eSKate Stone   if (is_load_script && exe_ctx->GetTargetSP()) {
32484a53dfbSEnrico Granata     target_sp = exe_ctx->GetTargetSP();
325b9c1b51eSKate Stone     load_script_old_value =
326b9c1b51eSKate Stone         target_sp->TargetProperties::GetLoadScriptFromSymbolFile();
32784a53dfbSEnrico Granata   }
32897206d57SZachary Turner   Status error(Properties::SetPropertyValue(exe_ctx, op, property_path, value));
329b9c1b51eSKate Stone   if (error.Success()) {
33084a53dfbSEnrico Granata     // FIXME it would be nice to have "on-change" callbacks for properties
33131d97a5cSZachary Turner     if (property_path == g_properties[ePropertyPrompt].name) {
332514d8cd8SZachary Turner       llvm::StringRef new_prompt = GetPrompt();
333b9c1b51eSKate Stone       std::string str = lldb_utility::ansi::FormatAnsiTerminalCodes(
334b9c1b51eSKate Stone           new_prompt, GetUseColor());
335c3ce7f27SMichael Sartain       if (str.length())
336771ef6d4SMalcolm Parsons         new_prompt = str;
33744d93782SGreg Clayton       GetCommandInterpreter().UpdatePrompt(new_prompt);
3382f3df613SZachary Turner       auto bytes = llvm::make_unique<EventDataBytes>(new_prompt);
3392f3df613SZachary Turner       auto prompt_change_event_sp = std::make_shared<Event>(
3402f3df613SZachary Turner           CommandInterpreter::eBroadcastBitResetPrompt, bytes.release());
3414c05410fSGreg Clayton       GetCommandInterpreter().BroadcastEvent(prompt_change_event_sp);
34231d97a5cSZachary Turner     } else if (property_path == g_properties[ePropertyUseColor].name) {
343b9c1b51eSKate Stone       // use-color changed. Ping the prompt so it can reset the ansi terminal
344b9c1b51eSKate Stone       // codes.
345c3ce7f27SMichael Sartain       SetPrompt(GetPrompt());
346b9c1b51eSKate Stone     } else if (is_load_script && target_sp &&
347b9c1b51eSKate Stone                load_script_old_value == eLoadScriptFromSymFileWarn) {
348b9c1b51eSKate Stone       if (target_sp->TargetProperties::GetLoadScriptFromSymbolFile() ==
349b9c1b51eSKate Stone           eLoadScriptFromSymFileTrue) {
35097206d57SZachary Turner         std::list<Status> errors;
3519730339bSEnrico Granata         StreamString feedback_stream;
352b9c1b51eSKate Stone         if (!target_sp->LoadScriptingResources(errors, &feedback_stream)) {
35344d93782SGreg Clayton           StreamFileSP stream_sp(GetErrorFile());
354b9c1b51eSKate Stone           if (stream_sp) {
355b9c1b51eSKate Stone             for (auto error : errors) {
35644d93782SGreg Clayton               stream_sp->Printf("%s\n", error.AsCString());
35784a53dfbSEnrico Granata             }
3589730339bSEnrico Granata             if (feedback_stream.GetSize())
359c156427dSZachary Turner               stream_sp->PutCString(feedback_stream.GetString());
36044d93782SGreg Clayton           }
36184a53dfbSEnrico Granata         }
36284a53dfbSEnrico Granata       }
363b9c1b51eSKate Stone     } else if (is_escape_non_printables) {
364ebdc1ac0SEnrico Granata       DataVisualization::ForceUpdate();
365ebdc1ac0SEnrico Granata     }
3664c05410fSGreg Clayton   }
3674c05410fSGreg Clayton   return error;
3684c05410fSGreg Clayton }
3694c05410fSGreg Clayton 
370b9c1b51eSKate Stone bool Debugger::GetAutoConfirm() const {
37167cc0636SGreg Clayton   const uint32_t idx = ePropertyAutoConfirm;
372b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsBoolean(
373b9c1b51eSKate Stone       nullptr, idx, g_properties[idx].default_uint_value != 0);
37467cc0636SGreg Clayton }
37567cc0636SGreg Clayton 
376b9c1b51eSKate Stone const FormatEntity::Entry *Debugger::GetDisassemblyFormat() const {
377aff1b357SJason Molenda   const uint32_t idx = ePropertyDisassemblyFormat;
378df370550SEugene Zelenko   return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
379aff1b357SJason Molenda }
380aff1b357SJason Molenda 
381b9c1b51eSKate Stone const FormatEntity::Entry *Debugger::GetFrameFormat() const {
38267cc0636SGreg Clayton   const uint32_t idx = ePropertyFrameFormat;
383df370550SEugene Zelenko   return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
38467cc0636SGreg Clayton }
38567cc0636SGreg Clayton 
3867f1c1211SPavel Labath const FormatEntity::Entry *Debugger::GetFrameFormatUnique() const {
3877f1c1211SPavel Labath   const uint32_t idx = ePropertyFrameFormatUnique;
3887f1c1211SPavel Labath   return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
3897f1c1211SPavel Labath }
3907f1c1211SPavel Labath 
391b9c1b51eSKate Stone bool Debugger::GetNotifyVoid() const {
39267cc0636SGreg Clayton   const uint32_t idx = ePropertyNotiftVoid;
393b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsBoolean(
394b9c1b51eSKate Stone       nullptr, idx, g_properties[idx].default_uint_value != 0);
39567cc0636SGreg Clayton }
39667cc0636SGreg Clayton 
397514d8cd8SZachary Turner llvm::StringRef Debugger::GetPrompt() const {
39867cc0636SGreg Clayton   const uint32_t idx = ePropertyPrompt;
399b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsString(
400b9c1b51eSKate Stone       nullptr, idx, g_properties[idx].default_cstr_value);
40167cc0636SGreg Clayton }
40267cc0636SGreg Clayton 
403514d8cd8SZachary Turner void Debugger::SetPrompt(llvm::StringRef p) {
40467cc0636SGreg Clayton   const uint32_t idx = ePropertyPrompt;
405df370550SEugene Zelenko   m_collection_sp->SetPropertyAtIndexAsString(nullptr, idx, p);
406514d8cd8SZachary Turner   llvm::StringRef new_prompt = GetPrompt();
407b9c1b51eSKate Stone   std::string str =
408b9c1b51eSKate Stone       lldb_utility::ansi::FormatAnsiTerminalCodes(new_prompt, GetUseColor());
409c3ce7f27SMichael Sartain   if (str.length())
410771ef6d4SMalcolm Parsons     new_prompt = str;
41144d93782SGreg Clayton   GetCommandInterpreter().UpdatePrompt(new_prompt);
41267cc0636SGreg Clayton }
41367cc0636SGreg Clayton 
414b9c1b51eSKate Stone const FormatEntity::Entry *Debugger::GetThreadFormat() const {
41567cc0636SGreg Clayton   const uint32_t idx = ePropertyThreadFormat;
416df370550SEugene Zelenko   return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
41767cc0636SGreg Clayton }
41867cc0636SGreg Clayton 
4196a9767c7SJim Ingham const FormatEntity::Entry *Debugger::GetThreadStopFormat() const {
4206a9767c7SJim Ingham   const uint32_t idx = ePropertyThreadStopFormat;
4216a9767c7SJim Ingham   return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
4226a9767c7SJim Ingham }
4236a9767c7SJim Ingham 
424b9c1b51eSKate Stone lldb::ScriptLanguage Debugger::GetScriptLanguage() const {
42567cc0636SGreg Clayton   const uint32_t idx = ePropertyScriptLanguage;
426b9c1b51eSKate Stone   return (lldb::ScriptLanguage)m_collection_sp->GetPropertyAtIndexAsEnumeration(
427b9c1b51eSKate Stone       nullptr, idx, g_properties[idx].default_uint_value);
42867cc0636SGreg Clayton }
42967cc0636SGreg Clayton 
430b9c1b51eSKate Stone bool Debugger::SetScriptLanguage(lldb::ScriptLanguage script_lang) {
43167cc0636SGreg Clayton   const uint32_t idx = ePropertyScriptLanguage;
432b9c1b51eSKate Stone   return m_collection_sp->SetPropertyAtIndexAsEnumeration(nullptr, idx,
433b9c1b51eSKate Stone                                                           script_lang);
43467cc0636SGreg Clayton }
43567cc0636SGreg Clayton 
436b9c1b51eSKate Stone uint32_t Debugger::GetTerminalWidth() const {
43767cc0636SGreg Clayton   const uint32_t idx = ePropertyTerminalWidth;
438b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsSInt64(
439b9c1b51eSKate Stone       nullptr, idx, g_properties[idx].default_uint_value);
44067cc0636SGreg Clayton }
44167cc0636SGreg Clayton 
442b9c1b51eSKate Stone bool Debugger::SetTerminalWidth(uint32_t term_width) {
44367cc0636SGreg Clayton   const uint32_t idx = ePropertyTerminalWidth;
444df370550SEugene Zelenko   return m_collection_sp->SetPropertyAtIndexAsSInt64(nullptr, idx, term_width);
44567cc0636SGreg Clayton }
44667cc0636SGreg Clayton 
447b9c1b51eSKate Stone bool Debugger::GetUseExternalEditor() const {
44867cc0636SGreg Clayton   const uint32_t idx = ePropertyUseExternalEditor;
449b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsBoolean(
450b9c1b51eSKate Stone       nullptr, idx, g_properties[idx].default_uint_value != 0);
45167cc0636SGreg Clayton }
45267cc0636SGreg Clayton 
453b9c1b51eSKate Stone bool Debugger::SetUseExternalEditor(bool b) {
45467cc0636SGreg Clayton   const uint32_t idx = ePropertyUseExternalEditor;
455df370550SEugene Zelenko   return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
45667cc0636SGreg Clayton }
45767cc0636SGreg Clayton 
458b9c1b51eSKate Stone bool Debugger::GetUseColor() const {
459c3ce7f27SMichael Sartain   const uint32_t idx = ePropertyUseColor;
460b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsBoolean(
461b9c1b51eSKate Stone       nullptr, idx, g_properties[idx].default_uint_value != 0);
462c3ce7f27SMichael Sartain }
463c3ce7f27SMichael Sartain 
464b9c1b51eSKate Stone bool Debugger::SetUseColor(bool b) {
465c3ce7f27SMichael Sartain   const uint32_t idx = ePropertyUseColor;
466df370550SEugene Zelenko   bool ret = m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
467c3ce7f27SMichael Sartain   SetPrompt(GetPrompt());
468c3ce7f27SMichael Sartain   return ret;
469c3ce7f27SMichael Sartain }
470c3ce7f27SMichael Sartain 
4719666ba75STodd Fiala StopShowColumn Debugger::GetStopShowColumn() const {
4729666ba75STodd Fiala   const uint32_t idx = ePropertyStopShowColumn;
4739666ba75STodd Fiala   return (lldb::StopShowColumn)m_collection_sp->GetPropertyAtIndexAsEnumeration(
4749666ba75STodd Fiala       nullptr, idx, g_properties[idx].default_uint_value);
4759666ba75STodd Fiala }
4769666ba75STodd Fiala 
4779666ba75STodd Fiala const FormatEntity::Entry *Debugger::GetStopShowColumnAnsiPrefix() const {
4789666ba75STodd Fiala   const uint32_t idx = ePropertyStopShowColumnAnsiPrefix;
4799666ba75STodd Fiala   return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
4809666ba75STodd Fiala }
4819666ba75STodd Fiala 
4829666ba75STodd Fiala const FormatEntity::Entry *Debugger::GetStopShowColumnAnsiSuffix() const {
4839666ba75STodd Fiala   const uint32_t idx = ePropertyStopShowColumnAnsiSuffix;
4849666ba75STodd Fiala   return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
4859666ba75STodd Fiala }
4869666ba75STodd Fiala 
487b9c1b51eSKate Stone uint32_t Debugger::GetStopSourceLineCount(bool before) const {
488b9c1b51eSKate Stone   const uint32_t idx =
489b9c1b51eSKate Stone       before ? ePropertyStopLineCountBefore : ePropertyStopLineCountAfter;
490b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsSInt64(
491b9c1b51eSKate Stone       nullptr, idx, g_properties[idx].default_uint_value);
49267cc0636SGreg Clayton }
49367cc0636SGreg Clayton 
494b9c1b51eSKate Stone Debugger::StopDisassemblyType Debugger::GetStopDisassemblyDisplay() const {
49567cc0636SGreg Clayton   const uint32_t idx = ePropertyStopDisassemblyDisplay;
496b9c1b51eSKate Stone   return (Debugger::StopDisassemblyType)
497b9c1b51eSKate Stone       m_collection_sp->GetPropertyAtIndexAsEnumeration(
498b9c1b51eSKate Stone           nullptr, idx, g_properties[idx].default_uint_value);
49967cc0636SGreg Clayton }
50067cc0636SGreg Clayton 
501b9c1b51eSKate Stone uint32_t Debugger::GetDisassemblyLineCount() const {
50267cc0636SGreg Clayton   const uint32_t idx = ePropertyStopDisassemblyCount;
503b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsSInt64(
504b9c1b51eSKate Stone       nullptr, idx, g_properties[idx].default_uint_value);
50567cc0636SGreg Clayton }
506e372b98dSGreg Clayton 
507b9c1b51eSKate Stone bool Debugger::GetAutoOneLineSummaries() const {
50890a8db30SEnrico Granata   const uint32_t idx = ePropertyAutoOneLineSummaries;
509df370550SEugene Zelenko   return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true);
510ebdc1ac0SEnrico Granata }
511553fad5cSEnrico Granata 
512b9c1b51eSKate Stone bool Debugger::GetEscapeNonPrintables() const {
513ebdc1ac0SEnrico Granata   const uint32_t idx = ePropertyEscapeNonPrintables;
514df370550SEugene Zelenko   return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true);
515553fad5cSEnrico Granata }
516553fad5cSEnrico Granata 
517b9c1b51eSKate Stone bool Debugger::GetAutoIndent() const {
5186681041dSSean Callanan   const uint32_t idx = ePropertyAutoIndent;
519df370550SEugene Zelenko   return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true);
5206681041dSSean Callanan }
5216681041dSSean Callanan 
522b9c1b51eSKate Stone bool Debugger::SetAutoIndent(bool b) {
5236681041dSSean Callanan   const uint32_t idx = ePropertyAutoIndent;
524df370550SEugene Zelenko   return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
5256681041dSSean Callanan }
5266681041dSSean Callanan 
527b9c1b51eSKate Stone bool Debugger::GetPrintDecls() const {
5286681041dSSean Callanan   const uint32_t idx = ePropertyPrintDecls;
529df370550SEugene Zelenko   return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true);
5306681041dSSean Callanan }
5316681041dSSean Callanan 
532b9c1b51eSKate Stone bool Debugger::SetPrintDecls(bool b) {
5336681041dSSean Callanan   const uint32_t idx = ePropertyPrintDecls;
534df370550SEugene Zelenko   return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
5356681041dSSean Callanan }
5366681041dSSean Callanan 
537b9c1b51eSKate Stone uint32_t Debugger::GetTabSize() const {
5386681041dSSean Callanan   const uint32_t idx = ePropertyTabSize;
539b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsUInt64(
540b9c1b51eSKate Stone       nullptr, idx, g_properties[idx].default_uint_value);
5416681041dSSean Callanan }
5426681041dSSean Callanan 
543b9c1b51eSKate Stone bool Debugger::SetTabSize(uint32_t tab_size) {
5446681041dSSean Callanan   const uint32_t idx = ePropertyTabSize;
545df370550SEugene Zelenko   return m_collection_sp->SetPropertyAtIndexAsUInt64(nullptr, idx, tab_size);
5466681041dSSean Callanan }
5476681041dSSean Callanan 
5481b654882SGreg Clayton #pragma mark Debugger
5491b654882SGreg Clayton 
55067cc0636SGreg Clayton // const DebuggerPropertiesSP &
55167cc0636SGreg Clayton // Debugger::GetSettings() const
55267cc0636SGreg Clayton //{
55367cc0636SGreg Clayton //    return m_properties_sp;
55467cc0636SGreg Clayton //}
55567cc0636SGreg Clayton //
55699d0faf2SGreg Clayton 
557b9c1b51eSKate Stone void Debugger::Initialize(LoadPluginCallbackType load_plugin_callback) {
558b9c1b51eSKate Stone   assert(g_debugger_list_ptr == nullptr &&
559b9c1b51eSKate Stone          "Debugger::Initialize called more than once!");
5606c42e063SGreg Clayton   g_debugger_list_mutex_ptr = new std::recursive_mutex();
5616c42e063SGreg Clayton   g_debugger_list_ptr = new DebuggerList();
5625fb8f797SGreg Clayton   g_load_plugin_callback = load_plugin_callback;
56399d0faf2SGreg Clayton }
56430fdc8d8SChris Lattner 
565b9c1b51eSKate Stone void Debugger::Terminate() {
566b9c1b51eSKate Stone   assert(g_debugger_list_ptr &&
567b9c1b51eSKate Stone          "Debugger::Terminate called without a matching Debugger::Initialize!");
568e6e2bb38SZachary Turner 
569b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
57099d0faf2SGreg Clayton     // Clear our master list of debugger objects
5716c42e063SGreg Clayton     {
5726c42e063SGreg Clayton       std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
5736c42e063SGreg Clayton       for (const auto &debugger : *g_debugger_list_ptr)
574f3cd1819SOleksiy Vyalov         debugger->Clear();
5756c42e063SGreg Clayton       g_debugger_list_ptr->clear();
5766c42e063SGreg Clayton     }
5776c42e063SGreg Clayton   }
57830fdc8d8SChris Lattner }
57930fdc8d8SChris Lattner 
580b9c1b51eSKate Stone void Debugger::SettingsInitialize() { Target::SettingsInitialize(); }
58120bd37f7SCaroline Tice 
582b9c1b51eSKate Stone void Debugger::SettingsTerminate() { Target::SettingsTerminate(); }
58320bd37f7SCaroline Tice 
58497206d57SZachary Turner bool Debugger::LoadPlugin(const FileSpec &spec, Status &error) {
585b9c1b51eSKate Stone   if (g_load_plugin_callback) {
586b9c1b51eSKate Stone     llvm::sys::DynamicLibrary dynlib =
587b9c1b51eSKate Stone         g_load_plugin_callback(shared_from_this(), spec, error);
588b9c1b51eSKate Stone     if (dynlib.isValid()) {
58958a559c0SZachary Turner       m_loaded_plugins.push_back(dynlib);
59021dfcd9dSEnrico Granata       return true;
59121dfcd9dSEnrico Granata     }
592b9c1b51eSKate Stone   } else {
5935fb8f797SGreg Clayton     // The g_load_plugin_callback is registered in SBDebugger::Initialize()
5945fb8f797SGreg Clayton     // and if the public API layer isn't available (code is linking against
5955fb8f797SGreg Clayton     // all of the internal LLDB static libraries), then we can't load plugins
5965fb8f797SGreg Clayton     error.SetErrorString("Public API layer is not available");
5975fb8f797SGreg Clayton   }
59821dfcd9dSEnrico Granata   return false;
59921dfcd9dSEnrico Granata }
60021dfcd9dSEnrico Granata 
60121dfcd9dSEnrico Granata static FileSpec::EnumerateDirectoryResult
6027d86ee5aSZachary Turner LoadPluginCallback(void *baton, llvm::sys::fs::file_type ft,
603b9c1b51eSKate Stone                    const FileSpec &file_spec) {
60497206d57SZachary Turner   Status error;
60521dfcd9dSEnrico Granata 
60621dfcd9dSEnrico Granata   static ConstString g_dylibext("dylib");
6073cf443ddSMichael Sartain   static ConstString g_solibext("so");
60821dfcd9dSEnrico Granata 
60921dfcd9dSEnrico Granata   if (!baton)
61021dfcd9dSEnrico Granata     return FileSpec::eEnumerateDirectoryResultQuit;
61121dfcd9dSEnrico Granata 
61221dfcd9dSEnrico Granata   Debugger *debugger = (Debugger *)baton;
61321dfcd9dSEnrico Granata 
6147d86ee5aSZachary Turner   namespace fs = llvm::sys::fs;
61521dfcd9dSEnrico Granata   // If we have a regular file, a symbolic link or unknown file type, try
61621dfcd9dSEnrico Granata   // and process the file. We must handle unknown as sometimes the directory
61721dfcd9dSEnrico Granata   // enumeration might be enumerating a file system that doesn't have correct
61821dfcd9dSEnrico Granata   // file type information.
6197d86ee5aSZachary Turner   if (ft == fs::file_type::regular_file || ft == fs::file_type::symlink_file ||
6207d86ee5aSZachary Turner       ft == fs::file_type::type_unknown) {
62121dfcd9dSEnrico Granata     FileSpec plugin_file_spec(file_spec);
62221dfcd9dSEnrico Granata     plugin_file_spec.ResolvePath();
62321dfcd9dSEnrico Granata 
6243cf443ddSMichael Sartain     if (plugin_file_spec.GetFileNameExtension() != g_dylibext &&
625b9c1b51eSKate Stone         plugin_file_spec.GetFileNameExtension() != g_solibext) {
62621dfcd9dSEnrico Granata       return FileSpec::eEnumerateDirectoryResultNext;
6273cf443ddSMichael Sartain     }
62821dfcd9dSEnrico Granata 
62997206d57SZachary Turner     Status plugin_load_error;
630e743c782SEnrico Granata     debugger->LoadPlugin(plugin_file_spec, plugin_load_error);
63121dfcd9dSEnrico Granata 
63221dfcd9dSEnrico Granata     return FileSpec::eEnumerateDirectoryResultNext;
6337d86ee5aSZachary Turner   } else if (ft == fs::file_type::directory_file ||
6347d86ee5aSZachary Turner              ft == fs::file_type::symlink_file ||
6357d86ee5aSZachary Turner              ft == fs::file_type::type_unknown) {
63621dfcd9dSEnrico Granata     // Try and recurse into anything that a directory or symbolic link.
63721dfcd9dSEnrico Granata     // We must also do this for unknown as sometimes the directory enumeration
6386a7f3338SBruce Mitchener     // might be enumerating a file system that doesn't have correct file type
63921dfcd9dSEnrico Granata     // information.
64021dfcd9dSEnrico Granata     return FileSpec::eEnumerateDirectoryResultEnter;
64121dfcd9dSEnrico Granata   }
64221dfcd9dSEnrico Granata 
64321dfcd9dSEnrico Granata   return FileSpec::eEnumerateDirectoryResultNext;
64421dfcd9dSEnrico Granata }
64521dfcd9dSEnrico Granata 
646b9c1b51eSKate Stone void Debugger::InstanceInitialize() {
64721dfcd9dSEnrico Granata   FileSpec dir_spec;
64821dfcd9dSEnrico Granata   const bool find_directories = true;
64921dfcd9dSEnrico Granata   const bool find_files = true;
65021dfcd9dSEnrico Granata   const bool find_other = true;
65121dfcd9dSEnrico Granata   char dir_path[PATH_MAX];
652b9c1b51eSKate Stone   if (HostInfo::GetLLDBPath(ePathTypeLLDBSystemPlugins, dir_spec)) {
653b9c1b51eSKate Stone     if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path))) {
654b9c1b51eSKate Stone       FileSpec::EnumerateDirectory(dir_path, find_directories, find_files,
655b9c1b51eSKate Stone                                    find_other, LoadPluginCallback, this);
65621dfcd9dSEnrico Granata     }
65721dfcd9dSEnrico Granata   }
65821dfcd9dSEnrico Granata 
659b9c1b51eSKate Stone   if (HostInfo::GetLLDBPath(ePathTypeLLDBUserPlugins, dir_spec)) {
660b9c1b51eSKate Stone     if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path))) {
661b9c1b51eSKate Stone       FileSpec::EnumerateDirectory(dir_path, find_directories, find_files,
662b9c1b51eSKate Stone                                    find_other, LoadPluginCallback, this);
66321dfcd9dSEnrico Granata     }
66421dfcd9dSEnrico Granata   }
665e8cd0c98SGreg Clayton 
666e8cd0c98SGreg Clayton   PluginManager::DebuggerInitialize(*this);
66721dfcd9dSEnrico Granata }
66821dfcd9dSEnrico Granata 
669b9c1b51eSKate Stone DebuggerSP Debugger::CreateInstance(lldb::LogOutputCallback log_callback,
670b9c1b51eSKate Stone                                     void *baton) {
671228063cdSJim Ingham   DebuggerSP debugger_sp(new Debugger(log_callback, baton));
672b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
6736c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
6746c42e063SGreg Clayton     g_debugger_list_ptr->push_back(debugger_sp);
6756611103cSGreg Clayton   }
67621dfcd9dSEnrico Granata   debugger_sp->InstanceInitialize();
6776611103cSGreg Clayton   return debugger_sp;
6786611103cSGreg Clayton }
6796611103cSGreg Clayton 
680b9c1b51eSKate Stone void Debugger::Destroy(DebuggerSP &debugger_sp) {
681df370550SEugene Zelenko   if (!debugger_sp)
682e02657b1SCaroline Tice     return;
683e02657b1SCaroline Tice 
6848314c525SJim Ingham   debugger_sp->Clear();
6858314c525SJim Ingham 
686b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
6876c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
6886c42e063SGreg Clayton     DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
689b9c1b51eSKate Stone     for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
690b9c1b51eSKate Stone       if ((*pos).get() == debugger_sp.get()) {
6916c42e063SGreg Clayton         g_debugger_list_ptr->erase(pos);
692e02657b1SCaroline Tice         return;
693e02657b1SCaroline Tice       }
694e02657b1SCaroline Tice     }
695e02657b1SCaroline Tice   }
696c15f55e2SGreg Clayton }
697e02657b1SCaroline Tice 
6984d122c40SGreg Clayton DebuggerSP
699b9c1b51eSKate Stone Debugger::FindDebuggerWithInstanceName(const ConstString &instance_name) {
7004d122c40SGreg Clayton   DebuggerSP debugger_sp;
701b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
7026c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
7036c42e063SGreg Clayton     DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
704b9c1b51eSKate Stone     for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
705b9c1b51eSKate Stone       if ((*pos)->m_instance_name == instance_name) {
7066920b52bSGreg Clayton         debugger_sp = *pos;
7076920b52bSGreg Clayton         break;
7086920b52bSGreg Clayton       }
7096920b52bSGreg Clayton     }
7106920b52bSGreg Clayton   }
7113df9a8dfSCaroline Tice   return debugger_sp;
7123df9a8dfSCaroline Tice }
7136611103cSGreg Clayton 
714b9c1b51eSKate Stone TargetSP Debugger::FindTargetWithProcessID(lldb::pid_t pid) {
7154d122c40SGreg Clayton   TargetSP target_sp;
716b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
7176c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
7186c42e063SGreg Clayton     DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
719b9c1b51eSKate Stone     for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
7206611103cSGreg Clayton       target_sp = (*pos)->GetTargetList().FindTargetWithProcessID(pid);
7216611103cSGreg Clayton       if (target_sp)
7226611103cSGreg Clayton         break;
7236611103cSGreg Clayton     }
724c15f55e2SGreg Clayton   }
7256611103cSGreg Clayton   return target_sp;
7266611103cSGreg Clayton }
7276611103cSGreg Clayton 
728b9c1b51eSKate Stone TargetSP Debugger::FindTargetWithProcess(Process *process) {
729e4e45924SGreg Clayton   TargetSP target_sp;
730b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
7316c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
7326c42e063SGreg Clayton     DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
733b9c1b51eSKate Stone     for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
734e4e45924SGreg Clayton       target_sp = (*pos)->GetTargetList().FindTargetWithProcess(process);
735e4e45924SGreg Clayton       if (target_sp)
736e4e45924SGreg Clayton         break;
737e4e45924SGreg Clayton     }
738c15f55e2SGreg Clayton   }
739e4e45924SGreg Clayton   return target_sp;
740e4e45924SGreg Clayton }
741e4e45924SGreg Clayton 
742b9c1b51eSKate Stone Debugger::Debugger(lldb::LogOutputCallback log_callback, void *baton)
743b9c1b51eSKate Stone     : UserID(g_unique_id++),
7442f3df613SZachary Turner       Properties(std::make_shared<OptionValueProperties>()),
7452f3df613SZachary Turner       m_input_file_sp(std::make_shared<StreamFile>(stdin, false)),
7462f3df613SZachary Turner       m_output_file_sp(std::make_shared<StreamFile>(stdout, false)),
7472f3df613SZachary Turner       m_error_file_sp(std::make_shared<StreamFile>(stderr, false)),
748583bbb1dSJim Ingham       m_broadcaster_manager_sp(BroadcasterManager::MakeBroadcasterManager()),
749b9c1b51eSKate Stone       m_terminal_state(), m_target_list(*this), m_platform_list(),
750583bbb1dSJim Ingham       m_listener_sp(Listener::MakeListener("lldb.Debugger")),
751b9c1b51eSKate Stone       m_source_manager_ap(), m_source_file_cache(),
7522f3df613SZachary Turner       m_command_interpreter_ap(llvm::make_unique<CommandInterpreter>(
7532f3df613SZachary Turner           *this, eScriptLanguageDefault, false)),
754b9c1b51eSKate Stone       m_input_reader_stack(), m_instance_name(), m_loaded_plugins(),
755b9c1b51eSKate Stone       m_event_handler_thread(), m_io_handler_thread(),
7564329fe42SGreg Clayton       m_sync_broadcaster(nullptr, "lldb.debugger.sync"),
757b9c1b51eSKate Stone       m_forward_listener_sp(), m_clear_once() {
75867cc0636SGreg Clayton   char instance_cstr[256];
75967cc0636SGreg Clayton   snprintf(instance_cstr, sizeof(instance_cstr), "debugger_%d", (int)GetID());
76067cc0636SGreg Clayton   m_instance_name.SetCString(instance_cstr);
761228063cdSJim Ingham   if (log_callback)
7622f3df613SZachary Turner     m_log_callback_stream_sp =
7632f3df613SZachary Turner         std::make_shared<StreamCallback>(log_callback, baton);
7646611103cSGreg Clayton   m_command_interpreter_ap->Initialize();
765ded470d3SGreg Clayton   // Always add our default platform to the platform list
766615eb7e6SGreg Clayton   PlatformSP default_platform_sp(Platform::GetHostPlatform());
767df370550SEugene Zelenko   assert(default_platform_sp);
768ded470d3SGreg Clayton   m_platform_list.Append(default_platform_sp, true);
76967cc0636SGreg Clayton 
770754a9369SGreg Clayton   m_collection_sp->Initialize(g_properties);
771b9c1b51eSKate Stone   m_collection_sp->AppendProperty(
772b9c1b51eSKate Stone       ConstString("target"),
773b9c1b51eSKate Stone       ConstString("Settings specify to debugging targets."), true,
77467cc0636SGreg Clayton       Target::GetGlobalProperties()->GetValueProperties());
775b9c1b51eSKate Stone   m_collection_sp->AppendProperty(
776b9c1b51eSKate Stone       ConstString("platform"), ConstString("Platform settings."), true,
77763acdfdeSOleksiy Vyalov       Platform::GetGlobalPlatformProperties()->GetValueProperties());
778235354beSAdrian Prantl   m_collection_sp->AppendProperty(
779*3cd29bcfSAdrian Prantl       ConstString("symbols"), ConstString("Symbol lookup and cache settings."),
780*3cd29bcfSAdrian Prantl       true, ModuleList::GetGlobalModuleListProperties().GetValueProperties());
781b9c1b51eSKate Stone   if (m_command_interpreter_ap) {
782b9c1b51eSKate Stone     m_collection_sp->AppendProperty(
783b9c1b51eSKate Stone         ConstString("interpreter"),
784754a9369SGreg Clayton         ConstString("Settings specify to the debugger's command interpreter."),
785b9c1b51eSKate Stone         true, m_command_interpreter_ap->GetValueProperties());
786754a9369SGreg Clayton   }
787b9c1b51eSKate Stone   OptionValueSInt64 *term_width =
788b9c1b51eSKate Stone       m_collection_sp->GetPropertyAtIndexAsOptionValueSInt64(
789b9c1b51eSKate Stone           nullptr, ePropertyTerminalWidth);
79067cc0636SGreg Clayton   term_width->SetMinimumValue(10);
79167cc0636SGreg Clayton   term_width->SetMaximumValue(1024);
792c3ce7f27SMichael Sartain 
793c3ce7f27SMichael Sartain   // Turn off use-color if this is a dumb terminal.
794c3ce7f27SMichael Sartain   const char *term = getenv("TERM");
795c3ce7f27SMichael Sartain   if (term && !strcmp(term, "dumb"))
796c3ce7f27SMichael Sartain     SetUseColor(false);
79730fdc8d8SChris Lattner }
79830fdc8d8SChris Lattner 
799b9c1b51eSKate Stone Debugger::~Debugger() { Clear(); }
8008314c525SJim Ingham 
801b9c1b51eSKate Stone void Debugger::Clear() {
8024329fe42SGreg Clayton   //----------------------------------------------------------------------
8034329fe42SGreg Clayton   // Make sure we call this function only once. With the C++ global
8044329fe42SGreg Clayton   // destructor chain having a list of debuggers and with code that can be
8054329fe42SGreg Clayton   // running on other threads, we need to ensure this doesn't happen
8064329fe42SGreg Clayton   // multiple times.
8074329fe42SGreg Clayton   //
8084329fe42SGreg Clayton   // The following functions call Debugger::Clear():
8094329fe42SGreg Clayton   //     Debugger::~Debugger();
8104329fe42SGreg Clayton   //     static void Debugger::Destroy(lldb::DebuggerSP &debugger_sp);
8114329fe42SGreg Clayton   //     static void Debugger::Terminate();
8124329fe42SGreg Clayton   //----------------------------------------------------------------------
813c5f28e2aSKamil Rytarowski   llvm::call_once(m_clear_once, [this]() {
81444d93782SGreg Clayton     ClearIOHandlers();
81544d93782SGreg Clayton     StopIOHandlerThread();
81644d93782SGreg Clayton     StopEventHandlerThread();
817583bbb1dSJim Ingham     m_listener_sp->Clear();
8186611103cSGreg Clayton     int num_targets = m_target_list.GetNumTargets();
819b9c1b51eSKate Stone     for (int i = 0; i < num_targets; i++) {
820ccbc08e6SGreg Clayton       TargetSP target_sp(m_target_list.GetTargetAtIndex(i));
821b9c1b51eSKate Stone       if (target_sp) {
822ccbc08e6SGreg Clayton         ProcessSP process_sp(target_sp->GetProcessSP());
8236611103cSGreg Clayton         if (process_sp)
8241fd07059SJim Ingham           process_sp->Finalize();
825ccbc08e6SGreg Clayton         target_sp->Destroy();
8266611103cSGreg Clayton       }
82730fdc8d8SChris Lattner     }
828583bbb1dSJim Ingham     m_broadcaster_manager_sp->Clear();
82930fdc8d8SChris Lattner 
830b9c1b51eSKate Stone     // Close the input file _before_ we close the input read communications
831b9c1b51eSKate Stone     // class
8320d69a3a4SGreg Clayton     // as it does NOT own the input file, our m_input_file does.
833c5917d9aSJim Ingham     m_terminal_state.Clear();
83444d93782SGreg Clayton     if (m_input_file_sp)
83544d93782SGreg Clayton       m_input_file_sp->GetFile().Close();
8360c4129f2SGreg Clayton 
8370c4129f2SGreg Clayton     m_command_interpreter_ap->Clear();
8384329fe42SGreg Clayton   });
8398314c525SJim Ingham }
84030fdc8d8SChris Lattner 
841b9c1b51eSKate Stone bool Debugger::GetCloseInputOnEOF() const {
84244d93782SGreg Clayton   //    return m_input_comm.GetCloseOnEOF();
84344d93782SGreg Clayton   return false;
844fc3f027dSGreg Clayton }
845fc3f027dSGreg Clayton 
846b9c1b51eSKate Stone void Debugger::SetCloseInputOnEOF(bool b) {
84744d93782SGreg Clayton   //    m_input_comm.SetCloseOnEOF(b);
848fc3f027dSGreg Clayton }
849fc3f027dSGreg Clayton 
850b9c1b51eSKate Stone bool Debugger::GetAsyncExecution() {
8516611103cSGreg Clayton   return !m_command_interpreter_ap->GetSynchronous();
85230fdc8d8SChris Lattner }
85330fdc8d8SChris Lattner 
854b9c1b51eSKate Stone void Debugger::SetAsyncExecution(bool async_execution) {
8556611103cSGreg Clayton   m_command_interpreter_ap->SetSynchronous(!async_execution);
85630fdc8d8SChris Lattner }
85730fdc8d8SChris Lattner 
858b9c1b51eSKate Stone void Debugger::SetInputFileHandle(FILE *fh, bool tranfer_ownership) {
85944d93782SGreg Clayton   if (m_input_file_sp)
86044d93782SGreg Clayton     m_input_file_sp->GetFile().SetStream(fh, tranfer_ownership);
86144d93782SGreg Clayton   else
8622f3df613SZachary Turner     m_input_file_sp = std::make_shared<StreamFile>(fh, tranfer_ownership);
86344d93782SGreg Clayton 
86444d93782SGreg Clayton   File &in_file = m_input_file_sp->GetFile();
865df370550SEugene Zelenko   if (!in_file.IsValid())
86651b1e2d2SGreg Clayton     in_file.SetStream(stdin, true);
86730fdc8d8SChris Lattner 
868b9c1b51eSKate Stone   // Save away the terminal state if that is relevant, so that we can restore it
869b9c1b51eSKate Stone   // in RestoreInputState.
870c5917d9aSJim Ingham   SaveInputTerminalState();
87130fdc8d8SChris Lattner }
87230fdc8d8SChris Lattner 
873b9c1b51eSKate Stone void Debugger::SetOutputFileHandle(FILE *fh, bool tranfer_ownership) {
87444d93782SGreg Clayton   if (m_output_file_sp)
87544d93782SGreg Clayton     m_output_file_sp->GetFile().SetStream(fh, tranfer_ownership);
87644d93782SGreg Clayton   else
8772f3df613SZachary Turner     m_output_file_sp = std::make_shared<StreamFile>(fh, tranfer_ownership);
87844d93782SGreg Clayton 
87944d93782SGreg Clayton   File &out_file = m_output_file_sp->GetFile();
880df370550SEugene Zelenko   if (!out_file.IsValid())
88151b1e2d2SGreg Clayton     out_file.SetStream(stdout, false);
8822f88aadfSCaroline Tice 
883b588726eSEnrico Granata   // do not create the ScriptInterpreter just for setting the output file handle
884b588726eSEnrico Granata   // as the constructor will know how to do the right thing on its own
885b588726eSEnrico Granata   const bool can_create = false;
886b9c1b51eSKate Stone   ScriptInterpreter *script_interpreter =
887b9c1b51eSKate Stone       GetCommandInterpreter().GetScriptInterpreter(can_create);
888b588726eSEnrico Granata   if (script_interpreter)
889b588726eSEnrico Granata     script_interpreter->ResetOutputFileHandle(fh);
89030fdc8d8SChris Lattner }
89130fdc8d8SChris Lattner 
892b9c1b51eSKate Stone void Debugger::SetErrorFileHandle(FILE *fh, bool tranfer_ownership) {
89344d93782SGreg Clayton   if (m_error_file_sp)
89444d93782SGreg Clayton     m_error_file_sp->GetFile().SetStream(fh, tranfer_ownership);
89544d93782SGreg Clayton   else
8962f3df613SZachary Turner     m_error_file_sp = std::make_shared<StreamFile>(fh, tranfer_ownership);
89744d93782SGreg Clayton 
89844d93782SGreg Clayton   File &err_file = m_error_file_sp->GetFile();
899df370550SEugene Zelenko   if (!err_file.IsValid())
90051b1e2d2SGreg Clayton     err_file.SetStream(stderr, false);
90130fdc8d8SChris Lattner }
90230fdc8d8SChris Lattner 
903b9c1b51eSKate Stone void Debugger::SaveInputTerminalState() {
904b9c1b51eSKate Stone   if (m_input_file_sp) {
90544d93782SGreg Clayton     File &in_file = m_input_file_sp->GetFile();
906c5917d9aSJim Ingham     if (in_file.GetDescriptor() != File::kInvalidDescriptor)
907c5917d9aSJim Ingham       m_terminal_state.Save(in_file.GetDescriptor(), true);
908c5917d9aSJim Ingham   }
90944d93782SGreg Clayton }
910c5917d9aSJim Ingham 
911b9c1b51eSKate Stone void Debugger::RestoreInputTerminalState() { m_terminal_state.Restore(); }
912c5917d9aSJim Ingham 
913b9c1b51eSKate Stone ExecutionContext Debugger::GetSelectedExecutionContext() {
91430fdc8d8SChris Lattner   ExecutionContext exe_ctx;
915c14ee32dSGreg Clayton   TargetSP target_sp(GetSelectedTarget());
916c14ee32dSGreg Clayton   exe_ctx.SetTargetSP(target_sp);
91730fdc8d8SChris Lattner 
918b9c1b51eSKate Stone   if (target_sp) {
919c14ee32dSGreg Clayton     ProcessSP process_sp(target_sp->GetProcessSP());
920c14ee32dSGreg Clayton     exe_ctx.SetProcessSP(process_sp);
921b9c1b51eSKate Stone     if (process_sp && !process_sp->IsRunning()) {
922c14ee32dSGreg Clayton       ThreadSP thread_sp(process_sp->GetThreadList().GetSelectedThread());
923b9c1b51eSKate Stone       if (thread_sp) {
924c14ee32dSGreg Clayton         exe_ctx.SetThreadSP(thread_sp);
925c14ee32dSGreg Clayton         exe_ctx.SetFrameSP(thread_sp->GetSelectedFrame());
926df370550SEugene Zelenko         if (exe_ctx.GetFramePtr() == nullptr)
927c14ee32dSGreg Clayton           exe_ctx.SetFrameSP(thread_sp->GetStackFrameAtIndex(0));
92830fdc8d8SChris Lattner       }
92930fdc8d8SChris Lattner     }
93030fdc8d8SChris Lattner   }
93130fdc8d8SChris Lattner   return exe_ctx;
93230fdc8d8SChris Lattner }
93330fdc8d8SChris Lattner 
934b9c1b51eSKate Stone void Debugger::DispatchInputInterrupt() {
93516ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex());
93644d93782SGreg Clayton   IOHandlerSP reader_sp(m_input_reader_stack.Top());
937efed6131SCaroline Tice   if (reader_sp)
93844d93782SGreg Clayton     reader_sp->Interrupt();
939efed6131SCaroline Tice }
940efed6131SCaroline Tice 
941b9c1b51eSKate Stone void Debugger::DispatchInputEndOfFile() {
94216ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex());
94344d93782SGreg Clayton   IOHandlerSP reader_sp(m_input_reader_stack.Top());
944efed6131SCaroline Tice   if (reader_sp)
94544d93782SGreg Clayton     reader_sp->GotEOF();
946efed6131SCaroline Tice }
947efed6131SCaroline Tice 
948b9c1b51eSKate Stone void Debugger::ClearIOHandlers() {
949b9c1b51eSKate Stone   // The bottom input reader should be the main debugger input reader.  We do
950b9c1b51eSKate Stone   // not want to close that one here.
95116ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex());
952b9c1b51eSKate Stone   while (m_input_reader_stack.GetSize() > 1) {
95344d93782SGreg Clayton     IOHandlerSP reader_sp(m_input_reader_stack.Top());
9543d6086f6SCaroline Tice     if (reader_sp)
9554446487dSPavel Labath       PopIOHandler(reader_sp);
9563d6086f6SCaroline Tice   }
9573d6086f6SCaroline Tice }
9583d6086f6SCaroline Tice 
959b9c1b51eSKate Stone void Debugger::ExecuteIOHandlers() {
960b9c1b51eSKate Stone   while (true) {
96144d93782SGreg Clayton     IOHandlerSP reader_sp(m_input_reader_stack.Top());
96230fdc8d8SChris Lattner     if (!reader_sp)
96330fdc8d8SChris Lattner       break;
96430fdc8d8SChris Lattner 
96544d93782SGreg Clayton     reader_sp->Run();
96644d93782SGreg Clayton 
96744d93782SGreg Clayton     // Remove all input readers that are done from the top of the stack
968b9c1b51eSKate Stone     while (true) {
96944d93782SGreg Clayton       IOHandlerSP top_reader_sp = m_input_reader_stack.Top();
97044d93782SGreg Clayton       if (top_reader_sp && top_reader_sp->GetIsDone())
9714446487dSPavel Labath         PopIOHandler(top_reader_sp);
97230fdc8d8SChris Lattner       else
97330fdc8d8SChris Lattner         break;
97430fdc8d8SChris Lattner     }
97530fdc8d8SChris Lattner   }
97644d93782SGreg Clayton   ClearIOHandlers();
97744d93782SGreg Clayton }
97830fdc8d8SChris Lattner 
979b9c1b51eSKate Stone bool Debugger::IsTopIOHandler(const lldb::IOHandlerSP &reader_sp) {
98044d93782SGreg Clayton   return m_input_reader_stack.IsTop(reader_sp);
98144d93782SGreg Clayton }
98230fdc8d8SChris Lattner 
983b9c1b51eSKate Stone bool Debugger::CheckTopIOHandlerTypes(IOHandler::Type top_type,
984b9c1b51eSKate Stone                                       IOHandler::Type second_top_type) {
9856681041dSSean Callanan   return m_input_reader_stack.CheckTopIOHandlerTypes(top_type, second_top_type);
9866681041dSSean Callanan }
9876681041dSSean Callanan 
988b9c1b51eSKate Stone void Debugger::PrintAsync(const char *s, size_t len, bool is_stdout) {
9894446487dSPavel Labath   lldb::StreamFileSP stream = is_stdout ? GetOutputFile() : GetErrorFile();
9904446487dSPavel Labath   m_input_reader_stack.PrintAsync(stream.get(), s, len);
9914446487dSPavel Labath }
99244d93782SGreg Clayton 
993b9c1b51eSKate Stone ConstString Debugger::GetTopIOHandlerControlSequence(char ch) {
99444d93782SGreg Clayton   return m_input_reader_stack.GetTopIOHandlerControlSequence(ch);
99530fdc8d8SChris Lattner }
99630fdc8d8SChris Lattner 
997b9c1b51eSKate Stone const char *Debugger::GetIOHandlerCommandPrefix() {
998a487aa4cSKate Stone   return m_input_reader_stack.GetTopIOHandlerCommandPrefix();
999a487aa4cSKate Stone }
1000a487aa4cSKate Stone 
1001b9c1b51eSKate Stone const char *Debugger::GetIOHandlerHelpPrologue() {
1002a487aa4cSKate Stone   return m_input_reader_stack.GetTopIOHandlerHelpPrologue();
1003a487aa4cSKate Stone }
1004a487aa4cSKate Stone 
1005b9c1b51eSKate Stone void Debugger::RunIOHandler(const IOHandlerSP &reader_sp) {
100644d93782SGreg Clayton   PushIOHandler(reader_sp);
1007577508dfSGreg Clayton 
1008577508dfSGreg Clayton   IOHandlerSP top_reader_sp = reader_sp;
1009b9c1b51eSKate Stone   while (top_reader_sp) {
1010577508dfSGreg Clayton     top_reader_sp->Run();
1011577508dfSGreg Clayton 
1012b9c1b51eSKate Stone     if (top_reader_sp.get() == reader_sp.get()) {
1013577508dfSGreg Clayton       if (PopIOHandler(reader_sp))
1014577508dfSGreg Clayton         break;
1015577508dfSGreg Clayton     }
1016577508dfSGreg Clayton 
1017b9c1b51eSKate Stone     while (true) {
1018577508dfSGreg Clayton       top_reader_sp = m_input_reader_stack.Top();
1019577508dfSGreg Clayton       if (top_reader_sp && top_reader_sp->GetIsDone())
10204446487dSPavel Labath         PopIOHandler(top_reader_sp);
1021577508dfSGreg Clayton       else
1022577508dfSGreg Clayton         break;
1023577508dfSGreg Clayton     }
1024577508dfSGreg Clayton   }
102544d93782SGreg Clayton }
102644d93782SGreg Clayton 
1027b9c1b51eSKate Stone void Debugger::AdoptTopIOHandlerFilesIfInvalid(StreamFileSP &in,
1028b9c1b51eSKate Stone                                                StreamFileSP &out,
1029b9c1b51eSKate Stone                                                StreamFileSP &err) {
103044d93782SGreg Clayton   // Before an IOHandler runs, it must have in/out/err streams.
103144d93782SGreg Clayton   // This function is called when one ore more of the streams
1032df370550SEugene Zelenko   // are nullptr. We use the top input reader's in/out/err streams,
103344d93782SGreg Clayton   // or fall back to the debugger file handles, or we fall back
103444d93782SGreg Clayton   // onto stdin/stdout/stderr as a last resort.
103544d93782SGreg Clayton 
103616ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex());
103744d93782SGreg Clayton   IOHandlerSP top_reader_sp(m_input_reader_stack.Top());
103844d93782SGreg Clayton   // If no STDIN has been set, then set it appropriately
1039b9c1b51eSKate Stone   if (!in) {
104044d93782SGreg Clayton     if (top_reader_sp)
104144d93782SGreg Clayton       in = top_reader_sp->GetInputStreamFile();
104244d93782SGreg Clayton     else
104344d93782SGreg Clayton       in = GetInputFile();
104444d93782SGreg Clayton 
104544d93782SGreg Clayton     // If there is nothing, use stdin
104644d93782SGreg Clayton     if (!in)
10472f3df613SZachary Turner       in = std::make_shared<StreamFile>(stdin, false);
104844d93782SGreg Clayton   }
104944d93782SGreg Clayton   // If no STDOUT has been set, then set it appropriately
1050b9c1b51eSKate Stone   if (!out) {
105144d93782SGreg Clayton     if (top_reader_sp)
105244d93782SGreg Clayton       out = top_reader_sp->GetOutputStreamFile();
105344d93782SGreg Clayton     else
105444d93782SGreg Clayton       out = GetOutputFile();
105544d93782SGreg Clayton 
105644d93782SGreg Clayton     // If there is nothing, use stdout
105744d93782SGreg Clayton     if (!out)
10582f3df613SZachary Turner       out = std::make_shared<StreamFile>(stdout, false);
105944d93782SGreg Clayton   }
106044d93782SGreg Clayton   // If no STDERR has been set, then set it appropriately
1061b9c1b51eSKate Stone   if (!err) {
106244d93782SGreg Clayton     if (top_reader_sp)
106344d93782SGreg Clayton       err = top_reader_sp->GetErrorStreamFile();
106444d93782SGreg Clayton     else
106544d93782SGreg Clayton       err = GetErrorFile();
106644d93782SGreg Clayton 
106744d93782SGreg Clayton     // If there is nothing, use stderr
106844d93782SGreg Clayton     if (!err)
10692f3df613SZachary Turner       err = std::make_shared<StreamFile>(stdout, false);
107044d93782SGreg Clayton   }
107144d93782SGreg Clayton }
107244d93782SGreg Clayton 
1073b9c1b51eSKate Stone void Debugger::PushIOHandler(const IOHandlerSP &reader_sp) {
107430fdc8d8SChris Lattner   if (!reader_sp)
107530fdc8d8SChris Lattner     return;
1076b44880caSCaroline Tice 
107716ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex());
10784446487dSPavel Labath 
10794446487dSPavel Labath   // Get the current top input reader...
108044d93782SGreg Clayton   IOHandlerSP top_reader_sp(m_input_reader_stack.Top());
1081b44880caSCaroline Tice 
1082b4874f1aSGreg Clayton   // Don't push the same IO handler twice...
10834446487dSPavel Labath   if (reader_sp == top_reader_sp)
10844446487dSPavel Labath     return;
10854446487dSPavel Labath 
108644d93782SGreg Clayton   // Push our new input reader
1087d5a0a01bSCaroline Tice   m_input_reader_stack.Push(reader_sp);
10884446487dSPavel Labath   reader_sp->Activate();
108944d93782SGreg Clayton 
109044d93782SGreg Clayton   // Interrupt the top input reader to it will exit its Run() function
109144d93782SGreg Clayton   // and let this new input reader take over
1092b9c1b51eSKate Stone   if (top_reader_sp) {
109344d93782SGreg Clayton     top_reader_sp->Deactivate();
10944446487dSPavel Labath     top_reader_sp->Cancel();
109530fdc8d8SChris Lattner   }
1096b4874f1aSGreg Clayton }
109730fdc8d8SChris Lattner 
1098b9c1b51eSKate Stone bool Debugger::PopIOHandler(const IOHandlerSP &pop_reader_sp) {
10994446487dSPavel Labath   if (!pop_reader_sp)
11004446487dSPavel Labath     return false;
110130fdc8d8SChris Lattner 
110216ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex());
110344d93782SGreg Clayton 
110430fdc8d8SChris Lattner   // The reader on the stop of the stack is done, so let the next
11056a7f3338SBruce Mitchener   // read on the stack refresh its prompt and if there is one...
11064446487dSPavel Labath   if (m_input_reader_stack.IsEmpty())
11074446487dSPavel Labath     return false;
11084446487dSPavel Labath 
110944d93782SGreg Clayton   IOHandlerSP reader_sp(m_input_reader_stack.Top());
111030fdc8d8SChris Lattner 
11114446487dSPavel Labath   if (pop_reader_sp != reader_sp)
11124446487dSPavel Labath     return false;
11134446487dSPavel Labath 
111444d93782SGreg Clayton   reader_sp->Deactivate();
1115b4874f1aSGreg Clayton   reader_sp->Cancel();
1116d5a0a01bSCaroline Tice   m_input_reader_stack.Pop();
111730fdc8d8SChris Lattner 
1118d5a0a01bSCaroline Tice   reader_sp = m_input_reader_stack.Top();
111930fdc8d8SChris Lattner   if (reader_sp)
112044d93782SGreg Clayton     reader_sp->Activate();
112144d93782SGreg Clayton 
112244d93782SGreg Clayton   return true;
112330fdc8d8SChris Lattner }
11246611103cSGreg Clayton 
1125b9c1b51eSKate Stone StreamSP Debugger::GetAsyncOutputStream() {
11262f3df613SZachary Turner   return std::make_shared<StreamAsynchronousIO>(*this, true);
11275b52f0c7SJim Ingham }
11285b52f0c7SJim Ingham 
1129b9c1b51eSKate Stone StreamSP Debugger::GetAsyncErrorStream() {
11302f3df613SZachary Turner   return std::make_shared<StreamAsynchronousIO>(*this, false);
11315b52f0c7SJim Ingham }
11325b52f0c7SJim Ingham 
1133b9c1b51eSKate Stone size_t Debugger::GetNumDebuggers() {
1134b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
11356c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
11366c42e063SGreg Clayton     return g_debugger_list_ptr->size();
1137061858ceSEnrico Granata   }
1138c15f55e2SGreg Clayton   return 0;
1139c15f55e2SGreg Clayton }
1140061858ceSEnrico Granata 
1141b9c1b51eSKate Stone lldb::DebuggerSP Debugger::GetDebuggerAtIndex(size_t index) {
1142061858ceSEnrico Granata   DebuggerSP debugger_sp;
1143061858ceSEnrico Granata 
1144b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
11456c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
11466c42e063SGreg Clayton     if (index < g_debugger_list_ptr->size())
11476c42e063SGreg Clayton       debugger_sp = g_debugger_list_ptr->at(index);
1148c15f55e2SGreg Clayton   }
1149061858ceSEnrico Granata 
1150061858ceSEnrico Granata   return debugger_sp;
1151061858ceSEnrico Granata }
1152061858ceSEnrico Granata 
1153b9c1b51eSKate Stone DebuggerSP Debugger::FindDebuggerWithID(lldb::user_id_t id) {
11544d122c40SGreg Clayton   DebuggerSP debugger_sp;
1155ebc1bb27SCaroline Tice 
1156b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
11576c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
11586c42e063SGreg Clayton     DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
1159b9c1b51eSKate Stone     for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
1160b9c1b51eSKate Stone       if ((*pos)->GetID() == id) {
1161ebc1bb27SCaroline Tice         debugger_sp = *pos;
1162ebc1bb27SCaroline Tice         break;
1163ebc1bb27SCaroline Tice       }
1164ebc1bb27SCaroline Tice     }
1165c15f55e2SGreg Clayton   }
1166ebc1bb27SCaroline Tice   return debugger_sp;
1167ebc1bb27SCaroline Tice }
11683df9a8dfSCaroline Tice 
1169b9c1b51eSKate Stone bool Debugger::FormatDisassemblerAddress(const FormatEntity::Entry *format,
1170aff1b357SJason Molenda                                          const SymbolContext *sc,
1171aff1b357SJason Molenda                                          const SymbolContext *prev_sc,
1172aff1b357SJason Molenda                                          const ExecutionContext *exe_ctx,
1173b9c1b51eSKate Stone                                          const Address *addr, Stream &s) {
1174554f68d3SGreg Clayton   FormatEntity::Entry format_entry;
1175554f68d3SGreg Clayton 
1176b9c1b51eSKate Stone   if (format == nullptr) {
1177df370550SEugene Zelenko     if (exe_ctx != nullptr && exe_ctx->HasTargetScope())
1178aff1b357SJason Molenda       format = exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat();
1179b9c1b51eSKate Stone     if (format == nullptr) {
1180554f68d3SGreg Clayton       FormatEntity::Parse("${addr}: ", format_entry);
1181554f68d3SGreg Clayton       format = &format_entry;
1182554f68d3SGreg Clayton     }
1183aff1b357SJason Molenda   }
1184aff1b357SJason Molenda   bool function_changed = false;
1185aff1b357SJason Molenda   bool initial_function = false;
1186b9c1b51eSKate Stone   if (prev_sc && (prev_sc->function || prev_sc->symbol)) {
1187b9c1b51eSKate Stone     if (sc && (sc->function || sc->symbol)) {
1188b9c1b51eSKate Stone       if (prev_sc->symbol && sc->symbol) {
1189b9c1b51eSKate Stone         if (!sc->symbol->Compare(prev_sc->symbol->GetName(),
1190b9c1b51eSKate Stone                                  prev_sc->symbol->GetType())) {
1191aff1b357SJason Molenda           function_changed = true;
1192aff1b357SJason Molenda         }
1193b9c1b51eSKate Stone       } else if (prev_sc->function && sc->function) {
1194b9c1b51eSKate Stone         if (prev_sc->function->GetMangled() != sc->function->GetMangled()) {
1195aff1b357SJason Molenda           function_changed = true;
1196aff1b357SJason Molenda         }
1197aff1b357SJason Molenda       }
1198aff1b357SJason Molenda     }
1199aff1b357SJason Molenda   }
1200aff1b357SJason Molenda   // The first context on a list of instructions will have a prev_sc that
1201aff1b357SJason Molenda   // has no Function or Symbol -- if SymbolContext had an IsValid() method, it
1202aff1b357SJason Molenda   // would return false.  But we do get a prev_sc pointer.
1203b9c1b51eSKate Stone   if ((sc && (sc->function || sc->symbol)) && prev_sc &&
1204b9c1b51eSKate Stone       (prev_sc->function == nullptr && prev_sc->symbol == nullptr)) {
1205aff1b357SJason Molenda     initial_function = true;
1206aff1b357SJason Molenda   }
1207b9c1b51eSKate Stone   return FormatEntity::Format(*format, s, sc, exe_ctx, addr, nullptr,
1208b9c1b51eSKate Stone                               function_changed, initial_function);
1209aff1b357SJason Molenda }
1210aff1b357SJason Molenda 
1211b9c1b51eSKate Stone void Debugger::SetLoggingCallback(lldb::LogOutputCallback log_callback,
1212b9c1b51eSKate Stone                                   void *baton) {
12134f02b22dSJim Ingham   // For simplicity's sake, I am not going to deal with how to close down any
12144f02b22dSJim Ingham   // open logging streams, I just redirect everything from here on out to the
12154f02b22dSJim Ingham   // callback.
12162f3df613SZachary Turner   m_log_callback_stream_sp =
12172f3df613SZachary Turner       std::make_shared<StreamCallback>(log_callback, baton);
1218228063cdSJim Ingham }
1219228063cdSJim Ingham 
12205e336903SPavel Labath bool Debugger::EnableLog(llvm::StringRef channel,
12215e336903SPavel Labath                          llvm::ArrayRef<const char *> categories,
12225e336903SPavel Labath                          llvm::StringRef log_file, uint32_t log_options,
1223775588c0SPavel Labath                          llvm::raw_ostream &error_stream) {
12245fae71c5SPavel Labath   const bool should_close = true;
12255fae71c5SPavel Labath   const bool unbuffered = true;
12265fae71c5SPavel Labath 
12275fae71c5SPavel Labath   std::shared_ptr<llvm::raw_ostream> log_stream_sp;
1228b9c1b51eSKate Stone   if (m_log_callback_stream_sp) {
1229228063cdSJim Ingham     log_stream_sp = m_log_callback_stream_sp;
1230228063cdSJim Ingham     // For now when using the callback mode you always get thread & timestamp.
1231b9c1b51eSKate Stone     log_options |=
1232b9c1b51eSKate Stone         LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_THREAD_NAME;
12335e336903SPavel Labath   } else if (log_file.empty()) {
12345fae71c5SPavel Labath     log_stream_sp = std::make_shared<llvm::raw_fd_ostream>(
12355fae71c5SPavel Labath         GetOutputFile()->GetFile().GetDescriptor(), !should_close, unbuffered);
1236b9c1b51eSKate Stone   } else {
12375fae71c5SPavel Labath     auto pos = m_log_streams.find(log_file);
1238c1b2ccfdSGreg Clayton     if (pos != m_log_streams.end())
1239c1b2ccfdSGreg Clayton       log_stream_sp = pos->second.lock();
1240b9c1b51eSKate Stone     if (!log_stream_sp) {
12415fae71c5SPavel Labath       llvm::sys::fs::OpenFlags flags = llvm::sys::fs::F_Text;
12425fae71c5SPavel Labath       if (log_options & LLDB_LOG_OPTION_APPEND)
12435fae71c5SPavel Labath         flags |= llvm::sys::fs::F_Append;
12445fae71c5SPavel Labath       int FD;
12455fae71c5SPavel Labath       if (std::error_code ec =
12465fae71c5SPavel Labath               llvm::sys::fs::openFileForWrite(log_file, FD, flags)) {
1247775588c0SPavel Labath         error_stream << "Unable to open log file: " << ec.message();
12485fae71c5SPavel Labath         return false;
12495fae71c5SPavel Labath       }
12502f3df613SZachary Turner       log_stream_sp =
12512f3df613SZachary Turner           std::make_shared<llvm::raw_fd_ostream>(FD, should_close, unbuffered);
1252228063cdSJim Ingham       m_log_streams[log_file] = log_stream_sp;
1253228063cdSJim Ingham     }
1254228063cdSJim Ingham   }
1255df370550SEugene Zelenko   assert(log_stream_sp);
1256228063cdSJim Ingham 
1257228063cdSJim Ingham   if (log_options == 0)
1258b9c1b51eSKate Stone     log_options =
1259b9c1b51eSKate Stone         LLDB_LOG_OPTION_PREPEND_THREAD_NAME | LLDB_LOG_OPTION_THREADSAFE;
1260228063cdSJim Ingham 
1261b9c1b51eSKate Stone   return Log::EnableLogChannel(log_stream_sp, log_options, channel, categories,
1262b9c1b51eSKate Stone                                error_stream);
1263228063cdSJim Ingham }
1264228063cdSJim Ingham 
1265b9c1b51eSKate Stone SourceManager &Debugger::GetSourceManager() {
1266df370550SEugene Zelenko   if (!m_source_manager_ap)
12672f3df613SZachary Turner     m_source_manager_ap = llvm::make_unique<SourceManager>(shared_from_this());
12689585fbfcSGreg Clayton   return *m_source_manager_ap;
12699585fbfcSGreg Clayton }
12709585fbfcSGreg Clayton 
127144d93782SGreg Clayton // This function handles events that were broadcast by the process.
1272b9c1b51eSKate Stone void Debugger::HandleBreakpointEvent(const EventSP &event_sp) {
127344d93782SGreg Clayton   using namespace lldb;
1274b9c1b51eSKate Stone   const uint32_t event_type =
1275b9c1b51eSKate Stone       Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent(
1276b9c1b51eSKate Stone           event_sp);
127744d93782SGreg Clayton 
127844d93782SGreg Clayton   //    if (event_type & eBreakpointEventTypeAdded
127944d93782SGreg Clayton   //        || event_type & eBreakpointEventTypeRemoved
128044d93782SGreg Clayton   //        || event_type & eBreakpointEventTypeEnabled
128144d93782SGreg Clayton   //        || event_type & eBreakpointEventTypeDisabled
128244d93782SGreg Clayton   //        || event_type & eBreakpointEventTypeCommandChanged
128344d93782SGreg Clayton   //        || event_type & eBreakpointEventTypeConditionChanged
128444d93782SGreg Clayton   //        || event_type & eBreakpointEventTypeIgnoreChanged
128544d93782SGreg Clayton   //        || event_type & eBreakpointEventTypeLocationsResolved)
128644d93782SGreg Clayton   //    {
1287b9c1b51eSKate Stone   //        // Don't do anything about these events, since the breakpoint
1288b9c1b51eSKate Stone   //        commands already echo these actions.
128944d93782SGreg Clayton   //    }
129044d93782SGreg Clayton   //
1291b9c1b51eSKate Stone   if (event_type & eBreakpointEventTypeLocationsAdded) {
1292b9c1b51eSKate Stone     uint32_t num_new_locations =
1293b9c1b51eSKate Stone         Breakpoint::BreakpointEventData::GetNumBreakpointLocationsFromEvent(
1294b9c1b51eSKate Stone             event_sp);
1295b9c1b51eSKate Stone     if (num_new_locations > 0) {
1296b9c1b51eSKate Stone       BreakpointSP breakpoint =
1297b9c1b51eSKate Stone           Breakpoint::BreakpointEventData::GetBreakpointFromEvent(event_sp);
12984446487dSPavel Labath       StreamSP output_sp(GetAsyncOutputStream());
1299b9c1b51eSKate Stone       if (output_sp) {
130044d93782SGreg Clayton         output_sp->Printf("%d location%s added to breakpoint %d\n",
1301b9c1b51eSKate Stone                           num_new_locations, num_new_locations == 1 ? "" : "s",
130244d93782SGreg Clayton                           breakpoint->GetID());
13034446487dSPavel Labath         output_sp->Flush();
130444d93782SGreg Clayton       }
130544d93782SGreg Clayton     }
130644d93782SGreg Clayton   }
130744d93782SGreg Clayton   //    else if (event_type & eBreakpointEventTypeLocationsRemoved)
130844d93782SGreg Clayton   //    {
1309b9c1b51eSKate Stone   //        // These locations just get disabled, not sure it is worth spamming
1310b9c1b51eSKate Stone   //        folks about this on the command line.
131144d93782SGreg Clayton   //    }
131244d93782SGreg Clayton   //    else if (event_type & eBreakpointEventTypeLocationsResolved)
131344d93782SGreg Clayton   //    {
1314b9c1b51eSKate Stone   //        // This might be an interesting thing to note, but I'm going to
1315b9c1b51eSKate Stone   //        leave it quiet for now, it just looked noisy.
131644d93782SGreg Clayton   //    }
131744d93782SGreg Clayton }
131844d93782SGreg Clayton 
1319b9c1b51eSKate Stone size_t Debugger::GetProcessSTDOUT(Process *process, Stream *stream) {
132044d93782SGreg Clayton   size_t total_bytes = 0;
1321df370550SEugene Zelenko   if (stream == nullptr)
132244d93782SGreg Clayton     stream = GetOutputFile().get();
132344d93782SGreg Clayton 
1324b9c1b51eSKate Stone   if (stream) {
1325b9c1b51eSKate Stone     //  The process has stuff waiting for stdout; get it and write it out to the
1326b9c1b51eSKate Stone     //  appropriate place.
1327b9c1b51eSKate Stone     if (process == nullptr) {
132844d93782SGreg Clayton       TargetSP target_sp = GetTargetList().GetSelectedTarget();
132944d93782SGreg Clayton       if (target_sp)
133044d93782SGreg Clayton         process = target_sp->GetProcessSP().get();
133144d93782SGreg Clayton     }
1332b9c1b51eSKate Stone     if (process) {
133397206d57SZachary Turner       Status error;
133444d93782SGreg Clayton       size_t len;
133544d93782SGreg Clayton       char stdio_buffer[1024];
1336b9c1b51eSKate Stone       while ((len = process->GetSTDOUT(stdio_buffer, sizeof(stdio_buffer),
1337b9c1b51eSKate Stone                                        error)) > 0) {
133844d93782SGreg Clayton         stream->Write(stdio_buffer, len);
133944d93782SGreg Clayton         total_bytes += len;
134044d93782SGreg Clayton       }
134144d93782SGreg Clayton     }
134244d93782SGreg Clayton     stream->Flush();
134344d93782SGreg Clayton   }
134444d93782SGreg Clayton   return total_bytes;
134544d93782SGreg Clayton }
134644d93782SGreg Clayton 
1347b9c1b51eSKate Stone size_t Debugger::GetProcessSTDERR(Process *process, Stream *stream) {
134844d93782SGreg Clayton   size_t total_bytes = 0;
1349df370550SEugene Zelenko   if (stream == nullptr)
135044d93782SGreg Clayton     stream = GetOutputFile().get();
135144d93782SGreg Clayton 
1352b9c1b51eSKate Stone   if (stream) {
1353b9c1b51eSKate Stone     //  The process has stuff waiting for stderr; get it and write it out to the
1354b9c1b51eSKate Stone     //  appropriate place.
1355b9c1b51eSKate Stone     if (process == nullptr) {
135644d93782SGreg Clayton       TargetSP target_sp = GetTargetList().GetSelectedTarget();
135744d93782SGreg Clayton       if (target_sp)
135844d93782SGreg Clayton         process = target_sp->GetProcessSP().get();
135944d93782SGreg Clayton     }
1360b9c1b51eSKate Stone     if (process) {
136197206d57SZachary Turner       Status error;
136244d93782SGreg Clayton       size_t len;
136344d93782SGreg Clayton       char stdio_buffer[1024];
1364b9c1b51eSKate Stone       while ((len = process->GetSTDERR(stdio_buffer, sizeof(stdio_buffer),
1365b9c1b51eSKate Stone                                        error)) > 0) {
136644d93782SGreg Clayton         stream->Write(stdio_buffer, len);
136744d93782SGreg Clayton         total_bytes += len;
136844d93782SGreg Clayton       }
136944d93782SGreg Clayton     }
137044d93782SGreg Clayton     stream->Flush();
137144d93782SGreg Clayton   }
137244d93782SGreg Clayton   return total_bytes;
137344d93782SGreg Clayton }
137444d93782SGreg Clayton 
137544d93782SGreg Clayton // This function handles events that were broadcast by the process.
1376b9c1b51eSKate Stone void Debugger::HandleProcessEvent(const EventSP &event_sp) {
137744d93782SGreg Clayton   using namespace lldb;
137844d93782SGreg Clayton   const uint32_t event_type = event_sp->GetType();
1379b9c1b51eSKate Stone   ProcessSP process_sp =
1380b9c1b51eSKate Stone       (event_type == Process::eBroadcastBitStructuredData)
138175930019STodd Fiala           ? EventDataStructuredData::GetProcessFromEvent(event_sp.get())
138275930019STodd Fiala           : Process::ProcessEventData::GetProcessFromEvent(event_sp.get());
138344d93782SGreg Clayton 
13844446487dSPavel Labath   StreamSP output_stream_sp = GetAsyncOutputStream();
13854446487dSPavel Labath   StreamSP error_stream_sp = GetAsyncErrorStream();
138644d93782SGreg Clayton   const bool gui_enabled = IsForwardingEvents();
138744d93782SGreg Clayton 
1388b9c1b51eSKate Stone   if (!gui_enabled) {
1389b4874f1aSGreg Clayton     bool pop_process_io_handler = false;
139044d93782SGreg Clayton     assert(process_sp);
139144d93782SGreg Clayton 
13924446487dSPavel Labath     bool state_is_stopped = false;
1393b9c1b51eSKate Stone     const bool got_state_changed =
1394b9c1b51eSKate Stone         (event_type & Process::eBroadcastBitStateChanged) != 0;
13954446487dSPavel Labath     const bool got_stdout = (event_type & Process::eBroadcastBitSTDOUT) != 0;
13964446487dSPavel Labath     const bool got_stderr = (event_type & Process::eBroadcastBitSTDERR) != 0;
1397b9c1b51eSKate Stone     const bool got_structured_data =
1398b9c1b51eSKate Stone         (event_type & Process::eBroadcastBitStructuredData) != 0;
139975930019STodd Fiala 
1400b9c1b51eSKate Stone     if (got_state_changed) {
1401b9c1b51eSKate Stone       StateType event_state =
1402b9c1b51eSKate Stone           Process::ProcessEventData::GetStateFromEvent(event_sp.get());
14034446487dSPavel Labath       state_is_stopped = StateIsStoppedState(event_state, false);
140444d93782SGreg Clayton     }
1405b4874f1aSGreg Clayton 
14064446487dSPavel Labath     // Display running state changes first before any STDIO
1407b9c1b51eSKate Stone     if (got_state_changed && !state_is_stopped) {
1408b9c1b51eSKate Stone       Process::HandleProcessStateChangedEvent(event_sp, output_stream_sp.get(),
1409b9c1b51eSKate Stone                                               pop_process_io_handler);
141044d93782SGreg Clayton     }
1411b4874f1aSGreg Clayton 
14124446487dSPavel Labath     // Now display and STDOUT
1413b9c1b51eSKate Stone     if (got_stdout || got_state_changed) {
14144446487dSPavel Labath       GetProcessSTDOUT(process_sp.get(), output_stream_sp.get());
141544d93782SGreg Clayton     }
1416b4874f1aSGreg Clayton 
14174446487dSPavel Labath     // Now display and STDERR
1418b9c1b51eSKate Stone     if (got_stderr || got_state_changed) {
14194446487dSPavel Labath       GetProcessSTDERR(process_sp.get(), error_stream_sp.get());
1420b4874f1aSGreg Clayton     }
1421b4874f1aSGreg Clayton 
142275930019STodd Fiala     // Give structured data events an opportunity to display.
1423b9c1b51eSKate Stone     if (got_structured_data) {
142475930019STodd Fiala       StructuredDataPluginSP plugin_sp =
142575930019STodd Fiala           EventDataStructuredData::GetPluginFromEvent(event_sp.get());
1426b9c1b51eSKate Stone       if (plugin_sp) {
142775930019STodd Fiala         auto structured_data_sp =
142875930019STodd Fiala             EventDataStructuredData::GetObjectFromEvent(event_sp.get());
1429b9c1b51eSKate Stone         if (output_stream_sp) {
143075930019STodd Fiala           StreamString content_stream;
143197206d57SZachary Turner           Status error =
1432b9c1b51eSKate Stone               plugin_sp->GetDescription(structured_data_sp, content_stream);
1433b9c1b51eSKate Stone           if (error.Success()) {
1434b9c1b51eSKate Stone             if (!content_stream.GetString().empty()) {
143575930019STodd Fiala               // Add newline.
143675930019STodd Fiala               content_stream.PutChar('\n');
143775930019STodd Fiala               content_stream.Flush();
143875930019STodd Fiala 
143975930019STodd Fiala               // Print it.
1440771ef6d4SMalcolm Parsons               output_stream_sp->PutCString(content_stream.GetString());
144175930019STodd Fiala             }
1442b9c1b51eSKate Stone           } else {
144375930019STodd Fiala             error_stream_sp->Printf("Failed to print structured "
144475930019STodd Fiala                                     "data with plugin %s: %s",
1445b9c1b51eSKate Stone                                     plugin_sp->GetPluginName().AsCString(),
144675930019STodd Fiala                                     error.AsCString());
144775930019STodd Fiala           }
144875930019STodd Fiala         }
144975930019STodd Fiala       }
145075930019STodd Fiala     }
145175930019STodd Fiala 
14524446487dSPavel Labath     // Now display any stopped state changes after any STDIO
1453b9c1b51eSKate Stone     if (got_state_changed && state_is_stopped) {
1454b9c1b51eSKate Stone       Process::HandleProcessStateChangedEvent(event_sp, output_stream_sp.get(),
1455b9c1b51eSKate Stone                                               pop_process_io_handler);
145644d93782SGreg Clayton     }
145744d93782SGreg Clayton 
14584446487dSPavel Labath     output_stream_sp->Flush();
14594446487dSPavel Labath     error_stream_sp->Flush();
146044d93782SGreg Clayton 
1461b4874f1aSGreg Clayton     if (pop_process_io_handler)
1462b4874f1aSGreg Clayton       process_sp->PopProcessIOHandler();
1463b4874f1aSGreg Clayton   }
1464b4874f1aSGreg Clayton }
1465b4874f1aSGreg Clayton 
1466b9c1b51eSKate Stone void Debugger::HandleThreadEvent(const EventSP &event_sp) {
146744d93782SGreg Clayton   // At present the only thread event we handle is the Frame Changed event,
146844d93782SGreg Clayton   // and all we do for that is just reprint the thread status for that thread.
146944d93782SGreg Clayton   using namespace lldb;
147044d93782SGreg Clayton   const uint32_t event_type = event_sp->GetType();
14716a9767c7SJim Ingham   const bool stop_format = true;
147244d93782SGreg Clayton   if (event_type == Thread::eBroadcastBitStackChanged ||
1473b9c1b51eSKate Stone       event_type == Thread::eBroadcastBitThreadSelected) {
1474b9c1b51eSKate Stone     ThreadSP thread_sp(
1475b9c1b51eSKate Stone         Thread::ThreadEventData::GetThreadFromEvent(event_sp.get()));
1476b9c1b51eSKate Stone     if (thread_sp) {
14776a9767c7SJim Ingham       thread_sp->GetStatus(*GetAsyncOutputStream(), 0, 1, 1, stop_format);
147844d93782SGreg Clayton     }
147944d93782SGreg Clayton   }
148044d93782SGreg Clayton }
148144d93782SGreg Clayton 
1482b9c1b51eSKate Stone bool Debugger::IsForwardingEvents() { return (bool)m_forward_listener_sp; }
148344d93782SGreg Clayton 
1484b9c1b51eSKate Stone void Debugger::EnableForwardEvents(const ListenerSP &listener_sp) {
148544d93782SGreg Clayton   m_forward_listener_sp = listener_sp;
148644d93782SGreg Clayton }
148744d93782SGreg Clayton 
1488b9c1b51eSKate Stone void Debugger::CancelForwardEvents(const ListenerSP &listener_sp) {
148944d93782SGreg Clayton   m_forward_listener_sp.reset();
149044d93782SGreg Clayton }
149144d93782SGreg Clayton 
1492b9c1b51eSKate Stone void Debugger::DefaultEventHandler() {
1493583bbb1dSJim Ingham   ListenerSP listener_sp(GetListener());
149444d93782SGreg Clayton   ConstString broadcaster_class_target(Target::GetStaticBroadcasterClass());
149544d93782SGreg Clayton   ConstString broadcaster_class_process(Process::GetStaticBroadcasterClass());
149644d93782SGreg Clayton   ConstString broadcaster_class_thread(Thread::GetStaticBroadcasterClass());
149744d93782SGreg Clayton   BroadcastEventSpec target_event_spec(broadcaster_class_target,
149844d93782SGreg Clayton                                        Target::eBroadcastBitBreakpointChanged);
149944d93782SGreg Clayton 
1500b9c1b51eSKate Stone   BroadcastEventSpec process_event_spec(
1501b9c1b51eSKate Stone       broadcaster_class_process,
1502b9c1b51eSKate Stone       Process::eBroadcastBitStateChanged | Process::eBroadcastBitSTDOUT |
1503b9c1b51eSKate Stone           Process::eBroadcastBitSTDERR | Process::eBroadcastBitStructuredData);
150444d93782SGreg Clayton 
150544d93782SGreg Clayton   BroadcastEventSpec thread_event_spec(broadcaster_class_thread,
150644d93782SGreg Clayton                                        Thread::eBroadcastBitStackChanged |
150744d93782SGreg Clayton                                            Thread::eBroadcastBitThreadSelected);
150844d93782SGreg Clayton 
1509b9c1b51eSKate Stone   listener_sp->StartListeningForEventSpec(m_broadcaster_manager_sp,
1510b9c1b51eSKate Stone                                           target_event_spec);
1511b9c1b51eSKate Stone   listener_sp->StartListeningForEventSpec(m_broadcaster_manager_sp,
1512b9c1b51eSKate Stone                                           process_event_spec);
1513b9c1b51eSKate Stone   listener_sp->StartListeningForEventSpec(m_broadcaster_manager_sp,
1514b9c1b51eSKate Stone                                           thread_event_spec);
1515b9c1b51eSKate Stone   listener_sp->StartListeningForEvents(
1516b9c1b51eSKate Stone       m_command_interpreter_ap.get(),
151744d93782SGreg Clayton       CommandInterpreter::eBroadcastBitQuitCommandReceived |
151844d93782SGreg Clayton           CommandInterpreter::eBroadcastBitAsynchronousOutputData |
151944d93782SGreg Clayton           CommandInterpreter::eBroadcastBitAsynchronousErrorData);
152044d93782SGreg Clayton 
1521afa91e33SGreg Clayton   // Let the thread that spawned us know that we have started up and
1522afa91e33SGreg Clayton   // that we are now listening to all required events so no events get missed
1523afa91e33SGreg Clayton   m_sync_broadcaster.BroadcastEvent(eBroadcastBitEventThreadIsListening);
1524afa91e33SGreg Clayton 
152544d93782SGreg Clayton   bool done = false;
1526b9c1b51eSKate Stone   while (!done) {
152744d93782SGreg Clayton     EventSP event_sp;
1528d35031e1SPavel Labath     if (listener_sp->GetEvent(event_sp, llvm::None)) {
1529b9c1b51eSKate Stone       if (event_sp) {
153044d93782SGreg Clayton         Broadcaster *broadcaster = event_sp->GetBroadcaster();
1531b9c1b51eSKate Stone         if (broadcaster) {
153244d93782SGreg Clayton           uint32_t event_type = event_sp->GetType();
153344d93782SGreg Clayton           ConstString broadcaster_class(broadcaster->GetBroadcasterClass());
1534b9c1b51eSKate Stone           if (broadcaster_class == broadcaster_class_process) {
153544d93782SGreg Clayton             HandleProcessEvent(event_sp);
1536b9c1b51eSKate Stone           } else if (broadcaster_class == broadcaster_class_target) {
1537b9c1b51eSKate Stone             if (Breakpoint::BreakpointEventData::GetEventDataFromEvent(
1538b9c1b51eSKate Stone                     event_sp.get())) {
153944d93782SGreg Clayton               HandleBreakpointEvent(event_sp);
154044d93782SGreg Clayton             }
1541b9c1b51eSKate Stone           } else if (broadcaster_class == broadcaster_class_thread) {
154244d93782SGreg Clayton             HandleThreadEvent(event_sp);
1543b9c1b51eSKate Stone           } else if (broadcaster == m_command_interpreter_ap.get()) {
1544b9c1b51eSKate Stone             if (event_type &
1545b9c1b51eSKate Stone                 CommandInterpreter::eBroadcastBitQuitCommandReceived) {
154644d93782SGreg Clayton               done = true;
1547b9c1b51eSKate Stone             } else if (event_type &
1548b9c1b51eSKate Stone                        CommandInterpreter::eBroadcastBitAsynchronousErrorData) {
1549b9c1b51eSKate Stone               const char *data = reinterpret_cast<const char *>(
1550b9c1b51eSKate Stone                   EventDataBytes::GetBytesFromEvent(event_sp.get()));
1551b9c1b51eSKate Stone               if (data && data[0]) {
15524446487dSPavel Labath                 StreamSP error_sp(GetAsyncErrorStream());
1553b9c1b51eSKate Stone                 if (error_sp) {
155444d93782SGreg Clayton                   error_sp->PutCString(data);
155544d93782SGreg Clayton                   error_sp->Flush();
155644d93782SGreg Clayton                 }
155744d93782SGreg Clayton               }
1558b9c1b51eSKate Stone             } else if (event_type & CommandInterpreter::
1559b9c1b51eSKate Stone                                         eBroadcastBitAsynchronousOutputData) {
1560b9c1b51eSKate Stone               const char *data = reinterpret_cast<const char *>(
1561b9c1b51eSKate Stone                   EventDataBytes::GetBytesFromEvent(event_sp.get()));
1562b9c1b51eSKate Stone               if (data && data[0]) {
15634446487dSPavel Labath                 StreamSP output_sp(GetAsyncOutputStream());
1564b9c1b51eSKate Stone                 if (output_sp) {
156544d93782SGreg Clayton                   output_sp->PutCString(data);
156644d93782SGreg Clayton                   output_sp->Flush();
156744d93782SGreg Clayton                 }
156844d93782SGreg Clayton               }
156944d93782SGreg Clayton             }
157044d93782SGreg Clayton           }
157144d93782SGreg Clayton         }
157244d93782SGreg Clayton 
157344d93782SGreg Clayton         if (m_forward_listener_sp)
157444d93782SGreg Clayton           m_forward_listener_sp->AddEvent(event_sp);
157544d93782SGreg Clayton       }
157644d93782SGreg Clayton     }
157744d93782SGreg Clayton   }
157844d93782SGreg Clayton }
157944d93782SGreg Clayton 
1580b9c1b51eSKate Stone lldb::thread_result_t Debugger::EventHandlerThread(lldb::thread_arg_t arg) {
158144d93782SGreg Clayton   ((Debugger *)arg)->DefaultEventHandler();
158244d93782SGreg Clayton   return NULL;
158344d93782SGreg Clayton }
158444d93782SGreg Clayton 
1585b9c1b51eSKate Stone bool Debugger::StartEventHandlerThread() {
1586b9c1b51eSKate Stone   if (!m_event_handler_thread.IsJoinable()) {
1587afa91e33SGreg Clayton     // We must synchronize with the DefaultEventHandler() thread to ensure
1588afa91e33SGreg Clayton     // it is up and running and listening to events before we return from
1589afa91e33SGreg Clayton     // this function. We do this by listening to events for the
1590afa91e33SGreg Clayton     // eBroadcastBitEventThreadIsListening from the m_sync_broadcaster
1591b9c1b51eSKate Stone     ListenerSP listener_sp(
1592b9c1b51eSKate Stone         Listener::MakeListener("lldb.debugger.event-handler"));
1593b9c1b51eSKate Stone     listener_sp->StartListeningForEvents(&m_sync_broadcaster,
1594b9c1b51eSKate Stone                                          eBroadcastBitEventThreadIsListening);
1595afa91e33SGreg Clayton 
15967c2896a2SZachary Turner     // Use larger 8MB stack for this thread
1597b9c1b51eSKate Stone     m_event_handler_thread = ThreadLauncher::LaunchThread(
1598b9c1b51eSKate Stone         "lldb.debugger.event-handler", EventHandlerThread, this, nullptr,
15997c2896a2SZachary Turner         g_debugger_event_thread_stack_bytes);
1600afa91e33SGreg Clayton 
1601b9c1b51eSKate Stone     // Make sure DefaultEventHandler() is running and listening to events before
1602b9c1b51eSKate Stone     // we return
1603afa91e33SGreg Clayton     // from this function. We are only listening for events of type
1604b9c1b51eSKate Stone     // eBroadcastBitEventThreadIsListening so we don't need to check the event,
1605b9c1b51eSKate Stone     // we just need
1606b9c1b51eSKate Stone     // to wait an infinite amount of time for it (nullptr timeout as the first
1607b9c1b51eSKate Stone     // parameter)
1608afa91e33SGreg Clayton     lldb::EventSP event_sp;
1609d35031e1SPavel Labath     listener_sp->GetEvent(event_sp, llvm::None);
1610807b6b32SGreg Clayton   }
1611acee96aeSZachary Turner   return m_event_handler_thread.IsJoinable();
161244d93782SGreg Clayton }
161344d93782SGreg Clayton 
1614b9c1b51eSKate Stone void Debugger::StopEventHandlerThread() {
1615b9c1b51eSKate Stone   if (m_event_handler_thread.IsJoinable()) {
1616b9c1b51eSKate Stone     GetCommandInterpreter().BroadcastEvent(
1617b9c1b51eSKate Stone         CommandInterpreter::eBroadcastBitQuitCommandReceived);
161839de3110SZachary Turner     m_event_handler_thread.Join(nullptr);
161944d93782SGreg Clayton   }
162044d93782SGreg Clayton }
162144d93782SGreg Clayton 
1622b9c1b51eSKate Stone lldb::thread_result_t Debugger::IOHandlerThread(lldb::thread_arg_t arg) {
162344d93782SGreg Clayton   Debugger *debugger = (Debugger *)arg;
16249aaab558SSiva Chandra   debugger->ExecuteIOHandlers();
162544d93782SGreg Clayton   debugger->StopEventHandlerThread();
162644d93782SGreg Clayton   return NULL;
162744d93782SGreg Clayton }
162844d93782SGreg Clayton 
1629b9c1b51eSKate Stone bool Debugger::HasIOHandlerThread() { return m_io_handler_thread.IsJoinable(); }
16306681041dSSean Callanan 
1631b9c1b51eSKate Stone bool Debugger::StartIOHandlerThread() {
1632acee96aeSZachary Turner   if (!m_io_handler_thread.IsJoinable())
1633b9c1b51eSKate Stone     m_io_handler_thread = ThreadLauncher::LaunchThread(
1634b9c1b51eSKate Stone         "lldb.debugger.io-handler", IOHandlerThread, this, nullptr,
1635807b6b32SGreg Clayton         8 * 1024 * 1024); // Use larger 8MB stack for this thread
1636acee96aeSZachary Turner   return m_io_handler_thread.IsJoinable();
163744d93782SGreg Clayton }
163844d93782SGreg Clayton 
1639b9c1b51eSKate Stone void Debugger::StopIOHandlerThread() {
1640b9c1b51eSKate Stone   if (m_io_handler_thread.IsJoinable()) {
164144d93782SGreg Clayton     if (m_input_file_sp)
164244d93782SGreg Clayton       m_input_file_sp->GetFile().Close();
164339de3110SZachary Turner     m_io_handler_thread.Join(nullptr);
164444d93782SGreg Clayton   }
164544d93782SGreg Clayton }
164644d93782SGreg Clayton 
1647b9c1b51eSKate Stone void Debugger::JoinIOHandlerThread() {
1648b9c1b51eSKate Stone   if (HasIOHandlerThread()) {
16496681041dSSean Callanan     thread_result_t result;
16506681041dSSean Callanan     m_io_handler_thread.Join(&result);
16516681041dSSean Callanan     m_io_handler_thread = LLDB_INVALID_HOST_THREAD;
16526681041dSSean Callanan   }
16536681041dSSean Callanan }
16546681041dSSean Callanan 
1655b9c1b51eSKate Stone Target *Debugger::GetDummyTarget() {
1656893c932aSJim Ingham   return m_target_list.GetDummyTarget(*this).get();
1657893c932aSJim Ingham }
1658893c932aSJim Ingham 
1659b9c1b51eSKate Stone Target *Debugger::GetSelectedOrDummyTarget(bool prefer_dummy) {
166033df7cd3SJim Ingham   Target *target = nullptr;
1661b9c1b51eSKate Stone   if (!prefer_dummy) {
166233df7cd3SJim Ingham     target = m_target_list.GetSelectedTarget().get();
166333df7cd3SJim Ingham     if (target)
166433df7cd3SJim Ingham       return target;
166533df7cd3SJim Ingham   }
1666893c932aSJim Ingham 
1667893c932aSJim Ingham   return GetDummyTarget();
1668893c932aSJim Ingham }
166944d93782SGreg Clayton 
167097206d57SZachary Turner Status Debugger::RunREPL(LanguageType language, const char *repl_options) {
167197206d57SZachary Turner   Status err;
16723e7e915dSSean Callanan   FileSpec repl_executable;
16733e7e915dSSean Callanan 
1674b9c1b51eSKate Stone   if (language == eLanguageTypeUnknown) {
167597f84e87SSean Callanan     std::set<LanguageType> repl_languages;
167697f84e87SSean Callanan 
167797f84e87SSean Callanan     Language::GetLanguagesSupportingREPLs(repl_languages);
167897f84e87SSean Callanan 
1679b9c1b51eSKate Stone     if (repl_languages.size() == 1) {
168097f84e87SSean Callanan       language = *repl_languages.begin();
1681b9c1b51eSKate Stone     } else if (repl_languages.empty()) {
1682b9c1b51eSKate Stone       err.SetErrorStringWithFormat(
1683b9c1b51eSKate Stone           "LLDB isn't configured with REPL support for any languages.");
168497f84e87SSean Callanan       return err;
1685b9c1b51eSKate Stone     } else {
1686b9c1b51eSKate Stone       err.SetErrorStringWithFormat(
1687b9c1b51eSKate Stone           "Multiple possible REPL languages.  Please specify a language.");
168897f84e87SSean Callanan       return err;
168997f84e87SSean Callanan     }
169097f84e87SSean Callanan   }
169197f84e87SSean Callanan 
1692b9c1b51eSKate Stone   Target *const target =
1693b9c1b51eSKate Stone       nullptr; // passing in an empty target means the REPL must create one
16943e7e915dSSean Callanan 
16953b682de6SSean Callanan   REPLSP repl_sp(REPL::Create(err, language, this, target, repl_options));
16963e7e915dSSean Callanan 
1697b9c1b51eSKate Stone   if (!err.Success()) {
16983e7e915dSSean Callanan     return err;
16993e7e915dSSean Callanan   }
17003e7e915dSSean Callanan 
1701b9c1b51eSKate Stone   if (!repl_sp) {
1702b9c1b51eSKate Stone     err.SetErrorStringWithFormat("couldn't find a REPL for %s",
1703b9c1b51eSKate Stone                                  Language::GetNameForLanguageType(language));
17043e7e915dSSean Callanan     return err;
17053e7e915dSSean Callanan   }
17063e7e915dSSean Callanan 
17073e7e915dSSean Callanan   repl_sp->SetCompilerOptions(repl_options);
17083e7e915dSSean Callanan   repl_sp->RunLoop();
17093e7e915dSSean Callanan 
17103e7e915dSSean Callanan   return err;
17113e7e915dSSean Callanan }
1712